UNPKG

@gebrai/gebrai

Version:

Model Context Protocol server for GeoGebra mathematical visualization

732 lines 29.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockGeoGebraInstance = void 0; const geogebra_1 = require("../types/geogebra"); const logger_1 = __importDefault(require("./logger")); const uuid_1 = require("uuid"); /** * Mock GeoGebra Instance for demonstration and testing * This provides the same interface as the full implementation * but uses in-memory simulation instead of a real browser instance */ class MockGeoGebraInstance { isInitialized = false; lastActivity = new Date(); objects = new Map(); animatingObjects = new Set(); animationSpeeds = new Map(); tracedObjects = new Set(); isAnimating = false; id; config; constructor(config = {}) { this.id = (0, uuid_1.v4)(); this.config = { appName: 'graphing', width: 800, height: 600, showMenuBar: false, showToolBar: false, showAlgebraInput: false, showResetIcon: false, enableRightClick: true, language: 'en', ...config }; logger_1.default.info(`Created Mock GeoGebra instance ${this.id}`, { config: this.config }); } /** * Initialize the mock instance */ async initialize() { try { logger_1.default.info(`Initializing Mock GeoGebra instance ${this.id}`); // Simulate initialization delay await new Promise(resolve => setTimeout(resolve, 100)); this.isInitialized = true; this.updateActivity(); logger_1.default.info(`Mock GeoGebra instance ${this.id} initialized successfully`); } catch (error) { logger_1.default.error(`Failed to initialize Mock GeoGebra instance ${this.id}`, error); throw new geogebra_1.GeoGebraConnectionError(`Failed to initialize GeoGebra: ${error instanceof Error ? error.message : String(error)}`); } } /** * Execute a GeoGebra command (mock implementation) */ async evalCommand(command) { this.ensureInitialized(); this.updateActivity(); try { logger_1.default.debug(`Executing mock command on instance ${this.id}: ${command}`); // Parse basic commands const result = this.parseCommand(command); logger_1.default.debug(`Mock command executed successfully on instance ${this.id}: ${command}`); return { success: true, result: result }; } catch (error) { logger_1.default.error(`Mock command execution failed on instance ${this.id}`, { command, error }); return { success: false, error: error instanceof Error ? error.message : String(error) }; } } /** * Parse and execute basic GeoGebra commands */ parseCommand(command) { const trimmed = command.trim(); // Point creation: A = (x, y) const pointMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)$/); if (pointMatch && pointMatch[1] && pointMatch[2] && pointMatch[3]) { const [, name, x, y] = pointMatch; this.objects.set(name, { name, type: 'point', visible: true, defined: true, x: parseFloat(x), y: parseFloat(y), z: 0, color: '#0000FF' }); return `Point ${name} created at (${x}, ${y})`; } // Slider creation: name = Slider(min, max, increment, speed, width, isAngle, horizontal, animating, random) const sliderMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*Slider\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*(?:\s*,\s*(\d+(?:\.\d+)?))?\s*.*?\)$/); if (sliderMatch && sliderMatch[1] && sliderMatch[2] && sliderMatch[3]) { const [, name, min, max, _increment] = sliderMatch; const defaultValue = parseFloat(min); this.objects.set(name, { name, type: 'slider', visible: true, defined: true, value: defaultValue, color: '#0073E6' }); return `Slider ${name} created with range [${min}, ${max}], current value: ${defaultValue}`; } // Line creation: l = Line(A, B) const lineMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*Line\s*\(\s*([A-Za-z]\w*)\s*,\s*([A-Za-z]\w*)\s*\)$/); if (lineMatch && lineMatch[1] && lineMatch[2] && lineMatch[3]) { const [, name, point1, point2] = lineMatch; if (!this.objects.has(point1) || !this.objects.has(point2)) { throw new Error(`Points ${point1} or ${point2} do not exist`); } this.objects.set(name, { name, type: 'line', visible: true, defined: true, color: '#000000' }); return `Line ${name} created through points ${point1} and ${point2}`; } // Function creation: f(x) = expression const functionMatch = trimmed.match(/^([A-Za-z]\w*)\s*\(\s*x\s*\)\s*=\s*(.+)$/); if (functionMatch && functionMatch[1] && functionMatch[2]) { const [, name, expression] = functionMatch; this.objects.set(name, { name, type: 'function', visible: true, defined: true, value: expression, color: '#FF0000' }); return `Function ${name}(x) = ${expression} created`; } // Parametric curve creation: name = Curve(x_expr, y_expr, param, start, end) const parametricMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*Curve\s*\(\s*(.+?)\s*,\s*(.+?)\s*,\s*([A-Za-z]\w*)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)$/); if (parametricMatch && parametricMatch[1] && parametricMatch[2] && parametricMatch[3] && parametricMatch[4] && parametricMatch[5] && parametricMatch[6]) { const [, name, xExpr, yExpr, param, tMin, tMax] = parametricMatch; this.objects.set(name, { name, type: 'curve', visible: true, defined: true, value: `Parametric: x(${param}) = ${xExpr}, y(${param}) = ${yExpr}, ${param} ∈ [${tMin}, ${tMax}]`, color: '#00AA00' }); return `Parametric curve ${name} created: x(${param}) = ${xExpr}, y(${param}) = ${yExpr}, ${param} ∈ [${tMin}, ${tMax}]`; } // Implicit curve creation: name = ImplicitCurve(expression) const implicitMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*ImplicitCurve\s*\(\s*(.+)\s*\)$/); if (implicitMatch && implicitMatch[1] && implicitMatch[2]) { const [, name, expression] = implicitMatch; this.objects.set(name, { name, type: 'implicitcurve', visible: true, defined: true, value: `Implicit: ${expression} = 0`, color: '#AA0000' }); return `Implicit curve ${name} created: ${expression} = 0`; } // Styling commands: SetColor, SetLineThickness, SetLineStyle const setColorMatch = trimmed.match(/^SetColor\s*\(\s*([A-Za-z]\w*)\s*,\s*"([^"]+)"\s*\)$/); if (setColorMatch && setColorMatch[1] && setColorMatch[2]) { const [, name, color] = setColorMatch; const obj = this.objects.get(name); if (obj) { obj.color = color; return `Color of ${name} set to ${color}`; } return `Object ${name} not found for color setting`; } const setThicknessMatch = trimmed.match(/^SetLineThickness\s*\(\s*([A-Za-z]\w*)\s*,\s*(\d+)\s*\)$/); if (setThicknessMatch && setThicknessMatch[1] && setThicknessMatch[2]) { const [, name, thickness] = setThicknessMatch; const obj = this.objects.get(name); if (obj) { // Store thickness in a custom property (mock doesn't have thickness in type) obj.thickness = parseInt(thickness); return `Line thickness of ${name} set to ${thickness}`; } return `Object ${name} not found for thickness setting`; } const setStyleMatch = trimmed.match(/^SetLineStyle\s*\(\s*([A-Za-z]\w*)\s*,\s*(\d+)\s*\)$/); if (setStyleMatch && setStyleMatch[1] && setStyleMatch[2]) { const [, name, lineType] = setStyleMatch; const obj = this.objects.get(name); if (obj) { const style = lineType === '10' ? 'dashed' : lineType === '20' ? 'dotted' : 'solid'; obj.style = style; return `Line style of ${name} set to ${style}`; } return `Object ${name} not found for style setting`; } // Circle creation: Circle((x, y), r) const circleMatch = trimmed.match(/^Circle\s*\(\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)\s*,\s*(\d+(?:\.\d+)?)\s*\)$/); if (circleMatch && circleMatch[1] && circleMatch[2] && circleMatch[3]) { const [, x, y, r] = circleMatch; const name = `circle_${Date.now()}`; this.objects.set(name, { name, type: 'circle', visible: true, defined: true, x: parseFloat(x), y: parseFloat(y), value: parseFloat(r), color: '#00FF00' }); return `Circle created at (${x}, ${y}) with radius ${r}`; } // CAS Operations // Solve equation: Solve(equation) const solveMatch = trimmed.match(/^Solve\s*\(\s*(.+)\s*\)$/); if (solveMatch && solveMatch[1]) { const [, equation] = solveMatch; return this.mockSolveEquation(equation); } // Solve equation for variable: Solve(equation, variable) const solveVarMatch = trimmed.match(/^Solve\s*\(\s*(.+?)\s*,\s*([a-zA-Z]\w*)\s*\)$/); if (solveVarMatch && solveVarMatch[1] && solveVarMatch[2]) { const [, equation, variable] = solveVarMatch; return this.mockSolveEquation(equation, variable); } // Differentiate with respect to variable: Derivative(expression, variable) const derivativeVarMatch = trimmed.match(/^Derivative\s*\(\s*(.+?)\s*,\s*([a-zA-Z]\w*)\s*\)$/); if (derivativeVarMatch && derivativeVarMatch[1] && derivativeVarMatch[2]) { const [, expression, variable] = derivativeVarMatch; return this.mockDifferentiate(expression, variable); } // Differentiate: Derivative(expression) const derivativeMatch = trimmed.match(/^Derivative\s*\(\s*(.+)\s*\)$/); if (derivativeMatch && derivativeMatch[1]) { const [, expression] = derivativeMatch; return this.mockDifferentiate(expression); } // Integrate with respect to variable: Integral(expression, variable) const integralVarMatch = trimmed.match(/^Integral\s*\(\s*(.+?)\s*,\s*([a-zA-Z]\w*)\s*\)$/); if (integralVarMatch && integralVarMatch[1] && integralVarMatch[2]) { const [, expression, variable] = integralVarMatch; return this.mockIntegrate(expression, variable); } // Integrate: Integral(expression) const integralMatch = trimmed.match(/^Integral\s*\(\s*(.+)\s*\)$/); if (integralMatch && integralMatch[1]) { const [, expression] = integralMatch; return this.mockIntegrate(expression); } // Simplify: Simplify(expression) const simplifyMatch = trimmed.match(/^Simplify\s*\(\s*(.+)\s*\)$/); if (simplifyMatch && simplifyMatch[1]) { const [, expression] = simplifyMatch; return this.mockSimplify(expression); } // Generic command (just acknowledge) return `Command executed: ${command}`; } /** * Execute command and get labels of created objects */ async evalCommandGetLabels(command) { this.ensureInitialized(); this.updateActivity(); try { const beforeObjects = new Set(this.objects.keys()); await this.evalCommand(command); const afterObjects = new Set(this.objects.keys()); const newLabels = Array.from(afterObjects).filter(label => !beforeObjects.has(label)); logger_1.default.debug(`Mock command executed on instance ${this.id}, labels: ${newLabels.join(', ')}`); return newLabels; } catch (error) { logger_1.default.error(`Failed to execute mock command with labels on instance ${this.id}`, { command, error }); throw new geogebra_1.GeoGebraCommandError(`Failed to execute command: ${error instanceof Error ? error.message : String(error)}`, command); } } /** * Delete an object */ async deleteObject(objName) { this.ensureInitialized(); this.updateActivity(); try { const deleted = this.objects.delete(objName); if (deleted) { logger_1.default.debug(`Deleted object ${objName} from mock instance ${this.id}`); } return deleted; } catch (error) { logger_1.default.error(`Failed to delete object ${objName} on mock instance ${this.id}`, error); return false; } } /** * Check if object exists */ async exists(objName) { this.ensureInitialized(); this.updateActivity(); return this.objects.has(objName); } /** * Check if object is defined */ async isDefined(objName) { this.ensureInitialized(); this.updateActivity(); const obj = this.objects.get(objName); return obj ? obj.defined : false; } /** * Get all object names */ async getAllObjectNames(type) { this.ensureInitialized(); this.updateActivity(); if (type) { return Array.from(this.objects.values()) .filter(obj => obj.type === type) .map(obj => obj.name); } return Array.from(this.objects.keys()); } /** * Get object information */ async getObjectInfo(objName) { this.ensureInitialized(); this.updateActivity(); return this.objects.get(objName) || null; } /** * Get X coordinate of object */ async getXcoord(objName) { this.ensureInitialized(); this.updateActivity(); const obj = this.objects.get(objName); return obj?.x || 0; } /** * Get Y coordinate of object */ async getYcoord(objName) { this.ensureInitialized(); this.updateActivity(); const obj = this.objects.get(objName); return obj?.y || 0; } /** * Get Z coordinate of object */ async getZcoord(objName) { this.ensureInitialized(); this.updateActivity(); const obj = this.objects.get(objName); return obj?.z || 0; } /** * Get value of object */ async getValue(objName) { this.ensureInitialized(); this.updateActivity(); const obj = this.objects.get(objName); return typeof obj?.value === 'number' ? obj.value : 0; } /** * Get value as string */ async getValueString(objName) { this.ensureInitialized(); this.updateActivity(); const obj = this.objects.get(objName); return obj?.value?.toString() || ''; } /** * Create new construction */ async newConstruction() { this.ensureInitialized(); this.updateActivity(); this.objects.clear(); logger_1.default.debug(`New construction created on mock instance ${this.id}`); } /** * Reset to initial state */ async reset() { this.ensureInitialized(); this.updateActivity(); this.objects.clear(); logger_1.default.debug(`Mock instance ${this.id} reset to initial state`); } /** * Refresh all views */ async refreshViews() { this.ensureInitialized(); this.updateActivity(); logger_1.default.debug(`Views refreshed on mock instance ${this.id}`); } /** * Set coordinate system bounds (mock implementation) */ async setCoordSystem(xmin, xmax, ymin, ymax) { this.ensureInitialized(); this.updateActivity(); logger_1.default.debug(`Mock coordinate system set on instance ${this.id}: x[${xmin}, ${xmax}], y[${ymin}, ${ymax}]`); } /** * Set axes visibility (mock implementation) */ async setAxesVisible(xAxis, yAxis) { this.ensureInitialized(); this.updateActivity(); logger_1.default.debug(`Mock axes visibility set on instance ${this.id}: x=${xAxis}, y=${yAxis}`); } /** * Set grid visibility (mock implementation) */ async setGridVisible(visible) { this.ensureInitialized(); this.updateActivity(); logger_1.default.debug(`Mock instance ${this.id}: Set grid visible: ${visible}`); } /** * Check if instance is ready */ async isReady() { return this.isInitialized; } /** * Export construction as PNG (base64) - Mock implementation with enhanced parameters */ async exportPNG(scale = 1, transparent = false, dpi = 72, width, height) { this.ensureInitialized(); this.updateActivity(); // Return a simple base64 encoded placeholder PNG const placeholderPNG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=='; logger_1.default.debug(`Mock PNG exported from instance ${this.id} with scale ${scale}, transparent ${transparent}, dpi ${dpi}, dimensions ${width}x${height}`); return placeholderPNG; } /** * Export construction as SVG - Mock implementation */ async exportSVG() { this.ensureInitialized(); this.updateActivity(); // Return a simple SVG with mock construction const mockSVG = `<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg"> <rect width="800" height="600" fill="white"/> <text x="400" y="300" text-anchor="middle" font-family="Arial" font-size="20">Mock GeoGebra Construction</text> ${Array.from(this.objects.values()).map(obj => { if (obj.type === 'point') { return `<circle cx="${(obj.x || 0) * 50 + 400}" cy="${(obj.y || 0) * -50 + 300}" r="3" fill="${obj.color || '#0000FF'}"/>`; } return ''; }).join('\n ')} </svg>`; logger_1.default.debug(`Mock SVG exported from instance ${this.id}`); return mockSVG.trim(); } /** * Export construction as PDF (base64) - Mock implementation */ async exportPDF() { this.ensureInitialized(); this.updateActivity(); logger_1.default.debug(`Mock PDF export from instance ${this.id}`); // Return mock PDF data (base64 encoded) const mockPdfData = 'JVBERi0xLjQKJcOkw7zDtsOgCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nDPQM1Qo5ypUMFAw0DMwULBVqOZSUDBQykvMTbVSUDC2UshIzStRyMnPS7VVqAUAYQsKZAplbmRzdHJlYW0KZW5kb2JqCgozIDAgb2JqCjI4CmVuZG9iagoKMSAwIG9iago8PC9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFI+PgplbmRvYmoKCjQgMCBvYmoKPDwvVHlwZS9QYWdlcy9LaWRzWzUgMCBSXS9Db3VudCAxPj4KZW5kb2JqCgo1IDAgb2JqCjw8L1R5cGUvUGFnZS9QYXJlbnQgNCAwIFIvTWVkaWFCb3hbMCAwIDYxMiA3OTJdL0NvbnRlbnRzIDIgMCBSPj4KZW5kb2JqCgp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAyOTQgMDAwMDAgbiAKMDAwMDAwMDAwOSAwMDAwMCBuIAowMDAwMDAwMjc0IDAwMDAwIG4gCjAwMDAwMDAzNDMgMDAwMDAgbiAKMDAwMDAwMDQwMCAwMDAwMCBuIAp0cmFpbGVyCjw8L1NpemUgNi9Sb290IDEgMCBSPj4Kc3RhcnR4cmVmCjUwMwolJUVPRg=='; return mockPdfData; } /** * Export animation as frames (GEB-17 enhancement) */ async exportAnimation(options = {}) { this.ensureInitialized(); this.updateActivity(); const { duration = 5000, // 5 seconds frameRate = 10, // 10 fps format = 'frames', width = 800, height = 600 } = options; logger_1.default.debug(`Mock animation export from instance ${this.id}`, { duration, frameRate, format, width, height }); // Calculate number of frames const totalFrames = Math.ceil((duration / 1000) * frameRate); // Generate mock frame data const frames = []; for (let i = 0; i < totalFrames; i++) { // Generate a simple mock PNG frame (base64 encoded) const mockFrameData = `iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==_frame_${i}`; frames.push(mockFrameData); } logger_1.default.debug(`Mock animation export completed: ${frames.length} frames generated`); if (format === 'frames') { return frames; } else { // For GIF format, return a mock GIF data string return 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7_mock_gif'; } } /** * Cleanup resources */ async cleanup() { logger_1.default.info(`Cleaning up Mock GeoGebra instance ${this.id}`); this.objects.clear(); this.isInitialized = false; logger_1.default.info(`Mock GeoGebra instance ${this.id} cleaned up successfully`); } /** * Get instance state */ getState() { return { id: this.id, isReady: this.isInitialized, lastActivity: this.lastActivity, config: this.config }; } /** * Update last activity timestamp */ updateActivity() { this.lastActivity = new Date(); } /** * Ensure instance is initialized */ ensureInitialized() { if (!this.isInitialized) { throw new geogebra_1.GeoGebraConnectionError('Mock GeoGebra instance not initialized'); } } /** * Mock implementation of equation solving */ mockSolveEquation(equation, variable) { logger_1.default.debug(`Mock solving equation: ${equation}${variable ? ` for ${variable}` : ''}`); // Simple mock responses for common cases if (equation.includes('x^2')) { return variable ? `{${variable} = -√(solution), ${variable} = √(solution)}` : `Solutions: x = -√(solution), x = √(solution)`; } if (equation.includes('x =') || equation.includes('= x')) { const match = equation.match(/(-?\d+(?:\.\d+)?)/); const value = match ? match[1] : '0'; return variable ? `{${variable} = ${value}}` : `Solution: x = ${value}`; } // Linear equation pattern if (equation.match(/\d*x\s*[+-]/)) { return variable ? `{${variable} = solution_value}` : `Solution: x = solution_value`; } return `Mock solution for equation: ${equation}`; } /** * Mock implementation of differentiation */ mockDifferentiate(expression, variable = 'x') { logger_1.default.debug(`Mock differentiating: ${expression} with respect to ${variable}`); // Simple mock responses for common cases if (expression === variable) { return '1'; } if (expression.includes(`${variable}^2`)) { return `2*${variable}`; } if (expression.includes(`${variable}^3`)) { return `3*${variable}^2`; } if (expression.includes(`sin(${variable})`)) { return `cos(${variable})`; } if (expression.includes(`cos(${variable})`)) { return `-sin(${variable})`; } if (expression.includes(`e^${variable}`)) { return `e^${variable}`; } if (!expression.includes(variable)) { return '0'; } return `d/d${variable}(${expression})`; } /** * Mock implementation of integration */ mockIntegrate(expression, variable = 'x') { logger_1.default.debug(`Mock integrating: ${expression} with respect to ${variable}`); // Simple mock responses for common cases if (expression === '1') { return variable; } if (expression === variable) { return `${variable}^2/2`; } if (expression.includes(`${variable}^2`)) { return `${variable}^3/3`; } if (expression.includes(`${variable}^3`)) { return `${variable}^4/4`; } if (expression.includes(`sin(${variable})`)) { return `-cos(${variable})`; } if (expression.includes(`cos(${variable})`)) { return `sin(${variable})`; } if (expression.includes(`e^${variable}`)) { return `e^${variable}`; } return `∫(${expression}, ${variable})dx`; } /** * Mock implementation of expression simplification */ mockSimplify(expression) { logger_1.default.debug(`Mock simplifying: ${expression}`); // Simple mock simplifications let simplified = expression; // Remove unnecessary parentheses and spaces simplified = simplified.replace(/\s+/g, ''); simplified = simplified.replace(/\(([^()]+)\)/g, '$1'); // Combine like terms (very basic) simplified = simplified.replace(/(\d+)\*x\+(\d+)\*x/g, (_match, a, b) => { return `${parseInt(a) + parseInt(b)}*x`; }); // Basic arithmetic simplified = simplified.replace(/(\d+)\+(\d+)/g, (_match, a, b) => { return `${parseInt(a) + parseInt(b)}`; }); simplified = simplified.replace(/(\d+)\*1/g, '$1'); simplified = simplified.replace(/1\*(\d+)/g, '$1'); simplified = simplified.replace(/\+0/g, ''); simplified = simplified.replace(/0\+/g, ''); return simplified === expression ? expression : simplified; } /** * Animation Methods */ async setAnimating(objName, animate) { this.ensureInitialized(); this.updateActivity(); if (!this.objects.has(objName)) { throw new Error(`Object ${objName} does not exist`); } if (animate) { this.animatingObjects.add(objName); if (!this.animationSpeeds.has(objName)) { this.animationSpeeds.set(objName, 1); // Default speed } } else { this.animatingObjects.delete(objName); } logger_1.default.debug(`Mock instance ${this.id}: Set animating for ${objName}: ${animate}`); } async setAnimationSpeed(objName, speed) { this.ensureInitialized(); this.updateActivity(); if (!this.objects.has(objName)) { throw new Error(`Object ${objName} does not exist`); } this.animationSpeeds.set(objName, speed); logger_1.default.debug(`Mock instance ${this.id}: Set animation speed for ${objName}: ${speed}`); } async startAnimation() { this.ensureInitialized(); this.updateActivity(); this.isAnimating = true; logger_1.default.debug(`Mock instance ${this.id}: Started animation for ${this.animatingObjects.size} objects`); } async stopAnimation() { this.ensureInitialized(); this.updateActivity(); this.isAnimating = false; logger_1.default.debug(`Mock instance ${this.id}: Stopped animation`); } async isAnimationRunning() { this.ensureInitialized(); this.updateActivity(); return this.isAnimating && this.animatingObjects.size > 0; } async setTrace(objName, flag) { this.ensureInitialized(); this.updateActivity(); if (!this.objects.has(objName)) { throw new Error(`Object ${objName} does not exist`); } if (flag) { this.tracedObjects.add(objName); } else { this.tracedObjects.delete(objName); } logger_1.default.debug(`Mock instance ${this.id}: Set trace for ${objName}: ${flag}`); } async setValue(objName, value) { this.ensureInitialized(); this.updateActivity(); const obj = this.objects.get(objName); if (!obj) { throw new Error(`Object ${objName} does not exist`); } obj.value = value; logger_1.default.debug(`Mock instance ${this.id}: Set value for ${objName}: ${value}`); } } exports.MockGeoGebraInstance = MockGeoGebraInstance; //# sourceMappingURL=geogebra-mock.js.map