UNPKG

@neuroequality/neuroadapt-ai

Version:

AI-powered accessibility personalization for neurodivergent users

276 lines (275 loc) 10.2 kB
import { EventEmitter as l } from "eventemitter3"; class h { constructor(t = 0.01) { this.weights = /* @__PURE__ */ new Map(), this.bias = 0, this.learningRate = t; } predict(t) { let i = this.bias; for (const [e, n] of Object.entries(t)) { const a = this.weights.get(e) || 0; i += a * n; } return Math.max(0, Math.min(1, i)); } train(t) { for (const i of t) { const e = this.predict(i.input.features), a = (typeof i.output == "number" ? i.output : 0) - e, s = i.weight || 1; this.bias += this.learningRate * a * s; for (const [r, o] of Object.entries(i.input.features)) { const g = this.weights.get(r) || 0; this.weights.set(r, g + this.learningRate * a * o * s); } } } getWeights() { return Object.fromEntries(this.weights); } setWeights(t) { this.weights = new Map(Object.entries(t)); } } class m extends l { constructor(t = {}) { super(), this.trainingData = [], this.interactions = [], this.config = { modelPath: t.modelPath || "neuroadapt-model.json", autoTrain: t.autoTrain ?? !0, trainingInterval: t.trainingInterval || 3e5, // 5 minutes minSamplesForTraining: t.minSamplesForTraining || 10, maxTrainingData: t.maxTrainingData || 1e3, learningRate: t.learningRate || 0.01, featureEngineering: t.featureEngineering ?? !0, enableOnlinelearning: t.enableOnlinelearning ?? !0 }, this.model = new h(this.config.learningRate), this.featureConfig = { temporal: !0, interaction: !0, preference: !0, context: !0, aggregation: !0 }, this.modelState = { version: "1.0.0", trainingData: 0, lastUpdated: Date.now(), features: this.getFeatureNames() }, this.config.autoTrain && this.startAutoTraining(); } /** * Record user interaction for learning */ recordInteraction(t) { try { this.interactions.push(t); const i = this.config.maxTrainingData * 2; this.interactions.length > i && (this.interactions = this.interactions.slice(-i)), this.config.enableOnlinelearning && this.processInteractionForLearning(t); } catch (i) { this.emit("error", i instanceof Error ? i : new Error(String(i))); } } /** * Predict preference adjustment based on current context */ async predictPreference(t, i = {}) { try { const e = this.extractFeatures(t, i), n = this.model.predict(e.features), a = this.calculateConfidence(n, e), r = { prediction: this.generateAdaptationSuggestions(t, n, a), confidence: a.level, score: a.score, reasoning: this.generateReasoning(e, n), metadata: { featureCount: Object.keys(e.features).length, modelVersion: this.modelState.version, trainingDataSize: this.modelState.trainingData } }; return this.emit("prediction", r), r; } catch (e) { const n = e instanceof Error ? e : new Error(String(e)); throw this.emit("error", n), n; } } /** * Suggest adaptations based on current behavior */ async suggestAdaptations(t, i) { try { const e = i || this.interactions.slice(-50), n = this.extractBehaviorFeatures(e, t), a = []; return this.detectMotionSensitivity(e) && a.push({ type: "sensory", target: "motionReduction", action: "enable", reasoning: "Detected potential motion sensitivity from interaction patterns", confidence: "medium", priority: "medium", estimatedImpact: 0.7 }), this.detectCognitiveLoad(e) && a.push({ type: "cognitive", target: "chunkSize", action: "adjust", value: 2, reasoning: "Detected signs of cognitive overload, reducing content chunk size", confidence: "high", priority: "high", estimatedImpact: 0.8 }), a.forEach((s) => { this.emit("adaptation-suggested", s); }), a; } catch (e) { const n = e instanceof Error ? e : new Error(String(e)); throw this.emit("error", n), n; } } /** * Add training data with feedback */ addTrainingData(t, i, e) { try { const n = { input: t, output: i, ...e !== void 0 && { feedback: e }, weight: e ? Math.abs(e) : 1 }; this.trainingData.push(n), this.trainingData.length > this.config.maxTrainingData && (this.trainingData = this.trainingData.slice(-this.config.maxTrainingData)), this.trainingData.length >= this.config.minSamplesForTraining && this.trainModel(); } catch (n) { this.emit("error", n instanceof Error ? n : new Error(String(n))); } } /** * Train the model with current data */ trainModel() { try { if (this.trainingData.length < this.config.minSamplesForTraining) return; const t = Date.now(); this.model.train(this.trainingData), this.modelState = { ...this.modelState, trainingData: this.trainingData.length, lastUpdated: Date.now(), accuracy: this.evaluateModel(), hyperparameters: { learningRate: this.config.learningRate, trainingDataSize: this.trainingData.length } }; const i = { accuracy: this.modelState.accuracy || 0, precision: 0.85, // Placeholder - would be calculated in real implementation recall: 0.8, f1Score: 0.82, sampleSize: this.trainingData.length, lastEvaluated: Date.now() }; this.emit("model-updated", this.modelState), this.emit("training-complete", i); } catch (t) { this.emit("error", t instanceof Error ? t : new Error(String(t))); } } /** * Get current model state */ getModelState() { return { ...this.modelState }; } /** * Clear training data and reset model */ reset() { this.trainingData = [], this.interactions = [], this.model = new h(this.config.learningRate), this.modelState = { version: "1.0.0", trainingData: 0, lastUpdated: Date.now(), features: this.getFeatureNames() }; } /** * Stop auto-training */ destroy() { this.trainingTimer && (clearInterval(this.trainingTimer), this.trainingTimer = void 0), this.removeAllListeners(); } // Private methods startAutoTraining() { this.trainingTimer = setInterval(() => { this.trainingData.length >= this.config.minSamplesForTraining && this.trainModel(); }, this.config.trainingInterval); } extractFeatures(t, i) { const e = {}; if (this.featureConfig.preference && (e.motionReduction = t.motionReduction ? 1 : 0, e.highContrast = t.highContrast ? 1 : 0, e.fontSize = typeof t.fontSize == "number" ? t.fontSize : 1, e.chunkSize = typeof t.chunkSize == "number" ? t.chunkSize : 3), this.featureConfig.context && (e.timeOfDay = (/* @__PURE__ */ new Date()).getHours() / 24, e.viewport_width = typeof i.viewportWidth == "number" ? i.viewportWidth / 1920 : 0.5, e.viewport_height = typeof i.viewportHeight == "number" ? i.viewportHeight / 1080 : 0.5), this.featureConfig.interaction) { const n = this.interactions.slice(-10); e.interaction_frequency = n.length / 10, e.click_ratio = n.filter((a) => a.type === "click").length / Math.max(1, n.length), e.scroll_ratio = n.filter((a) => a.type === "scroll").length / Math.max(1, n.length); } return { features: e, timestamp: Date.now(), metadata: { source: "prediction-engine" } }; } extractBehaviorFeatures(t, i) { const e = {}; if (t.length === 0) return { features: e, timestamp: Date.now() }; const n = t[t.length - 1].timestamp - t[0].timestamp; e.session_duration = Math.min(n / (1e3 * 60 * 60), 4), e.interaction_rate = t.length / Math.max(n / 1e3, 1); const a = t.filter((o) => o.type === "click").length, s = t.filter((o) => o.type === "scroll").length, r = t.filter((o) => o.type === "focus").length; return e.click_frequency = a / t.length, e.scroll_frequency = s / t.length, e.focus_frequency = r / t.length, { features: e, timestamp: Date.now() }; } processInteractionForLearning(t) { if (t.type === "preference_change" && t.value) { const i = this.extractFeatures(t.value, {}); this.addTrainingData(i, t.value, 1); } } calculateConfidence(t, i) { const e = Object.keys(i.features).length, n = Math.min(e / 10, 1), a = Math.abs(t - 0.5) * 2, s = (n + a) / 2; let r; return s >= 0.8 ? r = "very_high" : s >= 0.6 ? r = "high" : s >= 0.4 ? r = "medium" : r = "low", { level: r, score: s }; } generateAdaptationSuggestions(t, i, e) { const n = { ...t }; return e.score > 0.6 && (i > 0.7 && !t.motionReduction && (n.motionReduction = !0), i > 0.8 && typeof t.fontSize == "number" && t.fontSize < 1.2 && (n.fontSize = Math.min(t.fontSize + 0.1, 1.5))), n; } generateReasoning(t, i) { return `Prediction based on ${Object.entries(t.features).filter(([n, a]) => a > 0.5).map(([n, a]) => n).slice(0, 3).join(", ")} with confidence score ${i.toFixed(2)}`; } detectMotionSensitivity(t) { const i = t.filter((n) => n.type === "scroll"), e = t.filter((n) => n.type === "focus" || n.type === "blur"); return i.length > t.length * 0.4 || e.length > t.length * 0.3; } detectCognitiveLoad(t) { let i = 0; for (let e = 1; e < t.length; e++) t[e].timestamp - t[e - 1].timestamp > 5e3 && i++; return i > t.length * 0.2; } evaluateModel() { if (this.trainingData.length < 5) return 0; const t = this.trainingData.slice(-Math.min(10, this.trainingData.length)); let i = 0; for (const e of t) { const n = this.model.predict(e.input.features), a = typeof e.output == "number" ? e.output : 0; Math.abs(n - a) < 0.3 && i++; } return i / t.length; } getFeatureNames() { return [ "motionReduction", "highContrast", "fontSize", "chunkSize", "timeOfDay", "viewport_width", "viewport_height", "interaction_frequency", "click_ratio", "scroll_ratio" ]; } } export { m as P }; //# sourceMappingURL=engine-BGE0wXCL.js.map