@lydt/geogebra-studio 0.0.0-stage → 0.4.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +21 -0
- package/.codex-plugin/plugin.json +21 -0
- package/.mcp.json +18 -0
- package/LICENSE +339 -0
- package/LICENSE-MIT +21 -0
- package/README.md +108 -2
- package/README.zh-CN.md +89 -0
- package/THIRD_PARTY_NOTICES.md +35 -0
- package/dist/cli.d.ts +27 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +234 -0
- package/dist/cli.js.map +1 -0
- package/dist/export/files.d.ts +4 -0
- package/dist/export/files.d.ts.map +1 -0
- package/dist/export/files.js +44 -0
- package/dist/export/files.js.map +1 -0
- package/dist/export/gikz.d.ts +11 -0
- package/dist/export/gikz.d.ts.map +1 -0
- package/dist/export/gikz.js +28 -0
- package/dist/export/gikz.js.map +1 -0
- package/dist/export/html.d.ts +14 -0
- package/dist/export/html.d.ts.map +1 -0
- package/dist/export/html.js +97 -0
- package/dist/export/html.js.map +1 -0
- package/dist/export/semantic.d.ts +43 -0
- package/dist/export/semantic.d.ts.map +1 -0
- package/dist/export/semantic.js +212 -0
- package/dist/export/semantic.js.map +1 -0
- package/dist/export/viewer-themes.d.ts +76 -0
- package/dist/export/viewer-themes.d.ts.map +1 -0
- package/dist/export/viewer-themes.js +169 -0
- package/dist/export/viewer-themes.js.map +1 -0
- package/dist/export/workspace.d.ts +4 -0
- package/dist/export/workspace.d.ts.map +1 -0
- package/dist/export/workspace.js +25 -0
- package/dist/export/workspace.js.map +1 -0
- package/dist/gikz-browser.js +770 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +35 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +187 -0
- package/dist/server.js.map +1 -0
- package/dist/studio/artifact.d.ts +37 -0
- package/dist/studio/artifact.d.ts.map +1 -0
- package/dist/studio/artifact.js +61 -0
- package/dist/studio/artifact.js.map +1 -0
- package/dist/studio/browser.d.ts +7 -0
- package/dist/studio/browser.d.ts.map +1 -0
- package/dist/studio/browser.js +67 -0
- package/dist/studio/browser.js.map +1 -0
- package/dist/studio/install.d.ts +4 -0
- package/dist/studio/install.d.ts.map +1 -0
- package/dist/studio/install.js +60 -0
- package/dist/studio/install.js.map +1 -0
- package/dist/tools/apps-api-tools.d.ts +4 -0
- package/dist/tools/apps-api-tools.d.ts.map +1 -0
- package/dist/tools/apps-api-tools.js +96 -0
- package/dist/tools/apps-api-tools.js.map +1 -0
- package/dist/tools/educational-templates.d.ts +33 -0
- package/dist/tools/educational-templates.d.ts.map +1 -0
- package/dist/tools/educational-templates.js +261 -0
- package/dist/tools/educational-templates.js.map +1 -0
- package/dist/tools/export-tools.d.ts +3 -0
- package/dist/tools/export-tools.d.ts.map +1 -0
- package/dist/tools/export-tools.js +118 -0
- package/dist/tools/export-tools.js.map +1 -0
- package/dist/tools/geogebra-tools.d.ts +15 -0
- package/dist/tools/geogebra-tools.d.ts.map +1 -0
- package/dist/tools/geogebra-tools.js +3442 -0
- package/dist/tools/geogebra-tools.js.map +1 -0
- package/dist/tools/index.d.ts +43 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +183 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/performance-tools.d.ts +7 -0
- package/dist/tools/performance-tools.d.ts.map +1 -0
- package/dist/tools/performance-tools.js +312 -0
- package/dist/tools/performance-tools.js.map +1 -0
- package/dist/tools/templates/algebra-templates.d.ts +7 -0
- package/dist/tools/templates/algebra-templates.d.ts.map +1 -0
- package/dist/tools/templates/algebra-templates.js +568 -0
- package/dist/tools/templates/algebra-templates.js.map +1 -0
- package/dist/tools/templates/geometry-templates.d.ts +7 -0
- package/dist/tools/templates/geometry-templates.d.ts.map +1 -0
- package/dist/tools/templates/geometry-templates.js +492 -0
- package/dist/tools/templates/geometry-templates.js.map +1 -0
- package/dist/types/geogebra.d.ts +103 -0
- package/dist/types/geogebra.d.ts.map +1 -0
- package/dist/types/geogebra.js +34 -0
- package/dist/types/geogebra.js.map +1 -0
- package/dist/types/mcp.d.ts +125 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +19 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/utils/app-info.d.ts +12 -0
- package/dist/utils/app-info.d.ts.map +1 -0
- package/dist/utils/app-info.js +30 -0
- package/dist/utils/app-info.js.map +1 -0
- package/dist/utils/errors.d.ts +37 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +72 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/gemini-compatibility.d.ts +39 -0
- package/dist/utils/gemini-compatibility.d.ts.map +1 -0
- package/dist/utils/gemini-compatibility.js +154 -0
- package/dist/utils/gemini-compatibility.js.map +1 -0
- package/dist/utils/geogebra-instance.d.ts +252 -0
- package/dist/utils/geogebra-instance.d.ts.map +1 -0
- package/dist/utils/geogebra-instance.js +1560 -0
- package/dist/utils/geogebra-instance.js.map +1 -0
- package/dist/utils/geogebra-mock.d.ts +172 -0
- package/dist/utils/geogebra-mock.d.ts.map +1 -0
- package/dist/utils/geogebra-mock.js +732 -0
- package/dist/utils/geogebra-mock.js.map +1 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +46 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/performance/index.d.ts +76 -0
- package/dist/utils/performance/index.d.ts.map +1 -0
- package/dist/utils/performance/index.js +163 -0
- package/dist/utils/performance/index.js.map +1 -0
- package/dist/utils/performance/instance-pool.d.ts +78 -0
- package/dist/utils/performance/instance-pool.d.ts.map +1 -0
- package/dist/utils/performance/instance-pool.js +268 -0
- package/dist/utils/performance/instance-pool.js.map +1 -0
- package/dist/utils/validation.d.ts +92 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +557 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/widget.html +110 -0
- package/docs/APPS-API-BRIDGE.md +28 -0
- package/docs/MODERNIZATION.md +15 -0
- package/docs/TANGENT-REGRESSION.md +34 -0
- package/docs/VALIDATION.md +26 -0
- package/docs/VISUAL-STANDARD.md +26 -0
- package/docs/images/native-construction.png +0 -0
- package/examples/tangent-construction.json +26 -0
- package/gikz/LICENSE +339 -0
- package/gikz/PROVENANCE.md +8 -0
- package/gikz/browser.cjs +2 -0
- package/gikz/cli.cjs +195 -0
- package/gikz/core.cjs +806 -0
- package/mcp.json +20 -0
- package/package.json +107 -4
- package/plugin.json +35 -0
- package/runtime/package.json +4 -0
- package/scripts/build-plugin.cjs +15 -0
- package/scripts/build-widget.cjs +7 -0
- package/skills/geogebra-construct/SKILL.md +40 -0
- package/skills/geogebra-setup/SKILL.md +37 -0
- package/skills/geometry-export/SKILL.md +31 -0
- package/src/cli.ts +212 -0
- package/src/export/files.ts +26 -0
- package/src/export/gikz.ts +22 -0
- package/src/export/html.ts +108 -0
- package/src/export/semantic.ts +180 -0
- package/src/export/viewer-themes.ts +165 -0
- package/src/export/workspace.ts +15 -0
- package/src/index.ts +71 -0
- package/src/server.ts +168 -0
- package/src/studio/artifact.ts +50 -0
- package/src/studio/browser.ts +38 -0
- package/src/studio/install.ts +43 -0
- package/src/tools/apps-api-tools.ts +96 -0
- package/src/tools/educational-templates.ts +299 -0
- package/src/tools/export-tools.ts +110 -0
- package/src/tools/geogebra-tools.ts +3836 -0
- package/src/tools/index.ts +192 -0
- package/src/tools/performance-tools.ts +322 -0
- package/src/tools/templates/algebra-templates.ts +619 -0
- package/src/tools/templates/geometry-templates.ts +550 -0
- package/src/types/geogebra.ts +140 -0
- package/src/types/global.d.ts +31 -0
- package/src/types/mcp.ts +141 -0
- package/src/utils/app-info.ts +35 -0
- package/src/utils/errors.ts +97 -0
- package/src/utils/gemini-compatibility.ts +193 -0
- package/src/utils/geogebra-instance.ts +1712 -0
- package/src/utils/geogebra-mock.ts +867 -0
- package/src/utils/logger.ts +60 -0
- package/src/utils/performance/index.ts +211 -0
- package/src/utils/performance/instance-pool.ts +323 -0
- package/src/utils/validation.ts +647 -0
- package/tsconfig.json +35 -0
- package/widget/main.ts +12 -0
|
@@ -0,0 +1,732 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MockGeoGebraInstance = void 0;
|
|
7
|
+
const geogebra_1 = require("../types/geogebra");
|
|
8
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
/**
|
|
11
|
+
* Mock GeoGebra Instance for demonstration and testing
|
|
12
|
+
* This provides the same interface as the full implementation
|
|
13
|
+
* but uses in-memory simulation instead of a real browser instance
|
|
14
|
+
*/
|
|
15
|
+
class MockGeoGebraInstance {
|
|
16
|
+
isInitialized = false;
|
|
17
|
+
lastActivity = new Date();
|
|
18
|
+
objects = new Map();
|
|
19
|
+
animatingObjects = new Set();
|
|
20
|
+
animationSpeeds = new Map();
|
|
21
|
+
tracedObjects = new Set();
|
|
22
|
+
isAnimating = false;
|
|
23
|
+
id;
|
|
24
|
+
config;
|
|
25
|
+
constructor(config = {}) {
|
|
26
|
+
this.id = (0, crypto_1.randomUUID)();
|
|
27
|
+
this.config = {
|
|
28
|
+
appName: 'graphing',
|
|
29
|
+
width: 800,
|
|
30
|
+
height: 600,
|
|
31
|
+
showMenuBar: false,
|
|
32
|
+
showToolBar: false,
|
|
33
|
+
showAlgebraInput: false,
|
|
34
|
+
showResetIcon: false,
|
|
35
|
+
enableRightClick: true,
|
|
36
|
+
language: 'en',
|
|
37
|
+
...config
|
|
38
|
+
};
|
|
39
|
+
logger_1.default.info(`Created Mock GeoGebra instance ${this.id}`, { config: this.config });
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Initialize the mock instance
|
|
43
|
+
*/
|
|
44
|
+
async initialize() {
|
|
45
|
+
try {
|
|
46
|
+
logger_1.default.info(`Initializing Mock GeoGebra instance ${this.id}`);
|
|
47
|
+
// Simulate initialization delay
|
|
48
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
49
|
+
this.isInitialized = true;
|
|
50
|
+
this.updateActivity();
|
|
51
|
+
logger_1.default.info(`Mock GeoGebra instance ${this.id} initialized successfully`);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
logger_1.default.error(`Failed to initialize Mock GeoGebra instance ${this.id}`, error);
|
|
55
|
+
throw new geogebra_1.GeoGebraConnectionError(`Failed to initialize GeoGebra: ${error instanceof Error ? error.message : String(error)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Execute a GeoGebra command (mock implementation)
|
|
60
|
+
*/
|
|
61
|
+
async evalCommand(command) {
|
|
62
|
+
this.ensureInitialized();
|
|
63
|
+
this.updateActivity();
|
|
64
|
+
try {
|
|
65
|
+
logger_1.default.debug(`Executing mock command on instance ${this.id}: ${command}`);
|
|
66
|
+
// Parse basic commands
|
|
67
|
+
const result = this.parseCommand(command);
|
|
68
|
+
logger_1.default.debug(`Mock command executed successfully on instance ${this.id}: ${command}`);
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
result: result
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
logger_1.default.error(`Mock command execution failed on instance ${this.id}`, { command, error });
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
error: error instanceof Error ? error.message : String(error)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Parse and execute basic GeoGebra commands
|
|
84
|
+
*/
|
|
85
|
+
parseCommand(command) {
|
|
86
|
+
const trimmed = command.trim();
|
|
87
|
+
// Point creation: A = (x, y)
|
|
88
|
+
const pointMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)$/);
|
|
89
|
+
if (pointMatch && pointMatch[1] && pointMatch[2] && pointMatch[3]) {
|
|
90
|
+
const [, name, x, y] = pointMatch;
|
|
91
|
+
this.objects.set(name, {
|
|
92
|
+
name,
|
|
93
|
+
type: 'point',
|
|
94
|
+
visible: true,
|
|
95
|
+
defined: true,
|
|
96
|
+
x: parseFloat(x),
|
|
97
|
+
y: parseFloat(y),
|
|
98
|
+
z: 0,
|
|
99
|
+
color: '#0000FF'
|
|
100
|
+
});
|
|
101
|
+
return `Point ${name} created at (${x}, ${y})`;
|
|
102
|
+
}
|
|
103
|
+
// Slider creation: name = Slider(min, max, increment, speed, width, isAngle, horizontal, animating, random)
|
|
104
|
+
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*.*?\)$/);
|
|
105
|
+
if (sliderMatch && sliderMatch[1] && sliderMatch[2] && sliderMatch[3]) {
|
|
106
|
+
const [, name, min, max, _increment] = sliderMatch;
|
|
107
|
+
const defaultValue = parseFloat(min);
|
|
108
|
+
this.objects.set(name, {
|
|
109
|
+
name,
|
|
110
|
+
type: 'slider',
|
|
111
|
+
visible: true,
|
|
112
|
+
defined: true,
|
|
113
|
+
value: defaultValue,
|
|
114
|
+
color: '#0073E6'
|
|
115
|
+
});
|
|
116
|
+
return `Slider ${name} created with range [${min}, ${max}], current value: ${defaultValue}`;
|
|
117
|
+
}
|
|
118
|
+
// Line creation: l = Line(A, B)
|
|
119
|
+
const lineMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*Line\s*\(\s*([A-Za-z]\w*)\s*,\s*([A-Za-z]\w*)\s*\)$/);
|
|
120
|
+
if (lineMatch && lineMatch[1] && lineMatch[2] && lineMatch[3]) {
|
|
121
|
+
const [, name, point1, point2] = lineMatch;
|
|
122
|
+
if (!this.objects.has(point1) || !this.objects.has(point2)) {
|
|
123
|
+
throw new Error(`Points ${point1} or ${point2} do not exist`);
|
|
124
|
+
}
|
|
125
|
+
this.objects.set(name, {
|
|
126
|
+
name,
|
|
127
|
+
type: 'line',
|
|
128
|
+
visible: true,
|
|
129
|
+
defined: true,
|
|
130
|
+
color: '#000000'
|
|
131
|
+
});
|
|
132
|
+
return `Line ${name} created through points ${point1} and ${point2}`;
|
|
133
|
+
}
|
|
134
|
+
// Function creation: f(x) = expression
|
|
135
|
+
const functionMatch = trimmed.match(/^([A-Za-z]\w*)\s*\(\s*x\s*\)\s*=\s*(.+)$/);
|
|
136
|
+
if (functionMatch && functionMatch[1] && functionMatch[2]) {
|
|
137
|
+
const [, name, expression] = functionMatch;
|
|
138
|
+
this.objects.set(name, {
|
|
139
|
+
name,
|
|
140
|
+
type: 'function',
|
|
141
|
+
visible: true,
|
|
142
|
+
defined: true,
|
|
143
|
+
value: expression,
|
|
144
|
+
color: '#FF0000'
|
|
145
|
+
});
|
|
146
|
+
return `Function ${name}(x) = ${expression} created`;
|
|
147
|
+
}
|
|
148
|
+
// Parametric curve creation: name = Curve(x_expr, y_expr, param, start, end)
|
|
149
|
+
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*\)$/);
|
|
150
|
+
if (parametricMatch && parametricMatch[1] && parametricMatch[2] && parametricMatch[3] && parametricMatch[4] && parametricMatch[5] && parametricMatch[6]) {
|
|
151
|
+
const [, name, xExpr, yExpr, param, tMin, tMax] = parametricMatch;
|
|
152
|
+
this.objects.set(name, {
|
|
153
|
+
name,
|
|
154
|
+
type: 'curve',
|
|
155
|
+
visible: true,
|
|
156
|
+
defined: true,
|
|
157
|
+
value: `Parametric: x(${param}) = ${xExpr}, y(${param}) = ${yExpr}, ${param} ∈ [${tMin}, ${tMax}]`,
|
|
158
|
+
color: '#00AA00'
|
|
159
|
+
});
|
|
160
|
+
return `Parametric curve ${name} created: x(${param}) = ${xExpr}, y(${param}) = ${yExpr}, ${param} ∈ [${tMin}, ${tMax}]`;
|
|
161
|
+
}
|
|
162
|
+
// Implicit curve creation: name = ImplicitCurve(expression)
|
|
163
|
+
const implicitMatch = trimmed.match(/^([A-Za-z]\w*)\s*=\s*ImplicitCurve\s*\(\s*(.+)\s*\)$/);
|
|
164
|
+
if (implicitMatch && implicitMatch[1] && implicitMatch[2]) {
|
|
165
|
+
const [, name, expression] = implicitMatch;
|
|
166
|
+
this.objects.set(name, {
|
|
167
|
+
name,
|
|
168
|
+
type: 'implicitcurve',
|
|
169
|
+
visible: true,
|
|
170
|
+
defined: true,
|
|
171
|
+
value: `Implicit: ${expression} = 0`,
|
|
172
|
+
color: '#AA0000'
|
|
173
|
+
});
|
|
174
|
+
return `Implicit curve ${name} created: ${expression} = 0`;
|
|
175
|
+
}
|
|
176
|
+
// Styling commands: SetColor, SetLineThickness, SetLineStyle
|
|
177
|
+
const setColorMatch = trimmed.match(/^SetColor\s*\(\s*([A-Za-z]\w*)\s*,\s*"([^"]+)"\s*\)$/);
|
|
178
|
+
if (setColorMatch && setColorMatch[1] && setColorMatch[2]) {
|
|
179
|
+
const [, name, color] = setColorMatch;
|
|
180
|
+
const obj = this.objects.get(name);
|
|
181
|
+
if (obj) {
|
|
182
|
+
obj.color = color;
|
|
183
|
+
return `Color of ${name} set to ${color}`;
|
|
184
|
+
}
|
|
185
|
+
return `Object ${name} not found for color setting`;
|
|
186
|
+
}
|
|
187
|
+
const setThicknessMatch = trimmed.match(/^SetLineThickness\s*\(\s*([A-Za-z]\w*)\s*,\s*(\d+)\s*\)$/);
|
|
188
|
+
if (setThicknessMatch && setThicknessMatch[1] && setThicknessMatch[2]) {
|
|
189
|
+
const [, name, thickness] = setThicknessMatch;
|
|
190
|
+
const obj = this.objects.get(name);
|
|
191
|
+
if (obj) {
|
|
192
|
+
// Store thickness in a custom property (mock doesn't have thickness in type)
|
|
193
|
+
obj.thickness = parseInt(thickness);
|
|
194
|
+
return `Line thickness of ${name} set to ${thickness}`;
|
|
195
|
+
}
|
|
196
|
+
return `Object ${name} not found for thickness setting`;
|
|
197
|
+
}
|
|
198
|
+
const setStyleMatch = trimmed.match(/^SetLineStyle\s*\(\s*([A-Za-z]\w*)\s*,\s*(\d+)\s*\)$/);
|
|
199
|
+
if (setStyleMatch && setStyleMatch[1] && setStyleMatch[2]) {
|
|
200
|
+
const [, name, lineType] = setStyleMatch;
|
|
201
|
+
const obj = this.objects.get(name);
|
|
202
|
+
if (obj) {
|
|
203
|
+
const style = lineType === '10' ? 'dashed' : lineType === '20' ? 'dotted' : 'solid';
|
|
204
|
+
obj.style = style;
|
|
205
|
+
return `Line style of ${name} set to ${style}`;
|
|
206
|
+
}
|
|
207
|
+
return `Object ${name} not found for style setting`;
|
|
208
|
+
}
|
|
209
|
+
// Circle creation: Circle((x, y), r)
|
|
210
|
+
const circleMatch = trimmed.match(/^Circle\s*\(\s*\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)\s*,\s*(\d+(?:\.\d+)?)\s*\)$/);
|
|
211
|
+
if (circleMatch && circleMatch[1] && circleMatch[2] && circleMatch[3]) {
|
|
212
|
+
const [, x, y, r] = circleMatch;
|
|
213
|
+
const name = `circle_${Date.now()}`;
|
|
214
|
+
this.objects.set(name, {
|
|
215
|
+
name,
|
|
216
|
+
type: 'circle',
|
|
217
|
+
visible: true,
|
|
218
|
+
defined: true,
|
|
219
|
+
x: parseFloat(x),
|
|
220
|
+
y: parseFloat(y),
|
|
221
|
+
value: parseFloat(r),
|
|
222
|
+
color: '#00FF00'
|
|
223
|
+
});
|
|
224
|
+
return `Circle created at (${x}, ${y}) with radius ${r}`;
|
|
225
|
+
}
|
|
226
|
+
// CAS Operations
|
|
227
|
+
// Solve equation: Solve(equation)
|
|
228
|
+
const solveMatch = trimmed.match(/^Solve\s*\(\s*(.+)\s*\)$/);
|
|
229
|
+
if (solveMatch && solveMatch[1]) {
|
|
230
|
+
const [, equation] = solveMatch;
|
|
231
|
+
return this.mockSolveEquation(equation);
|
|
232
|
+
}
|
|
233
|
+
// Solve equation for variable: Solve(equation, variable)
|
|
234
|
+
const solveVarMatch = trimmed.match(/^Solve\s*\(\s*(.+?)\s*,\s*([a-zA-Z]\w*)\s*\)$/);
|
|
235
|
+
if (solveVarMatch && solveVarMatch[1] && solveVarMatch[2]) {
|
|
236
|
+
const [, equation, variable] = solveVarMatch;
|
|
237
|
+
return this.mockSolveEquation(equation, variable);
|
|
238
|
+
}
|
|
239
|
+
// Differentiate with respect to variable: Derivative(expression, variable)
|
|
240
|
+
const derivativeVarMatch = trimmed.match(/^Derivative\s*\(\s*(.+?)\s*,\s*([a-zA-Z]\w*)\s*\)$/);
|
|
241
|
+
if (derivativeVarMatch && derivativeVarMatch[1] && derivativeVarMatch[2]) {
|
|
242
|
+
const [, expression, variable] = derivativeVarMatch;
|
|
243
|
+
return this.mockDifferentiate(expression, variable);
|
|
244
|
+
}
|
|
245
|
+
// Differentiate: Derivative(expression)
|
|
246
|
+
const derivativeMatch = trimmed.match(/^Derivative\s*\(\s*(.+)\s*\)$/);
|
|
247
|
+
if (derivativeMatch && derivativeMatch[1]) {
|
|
248
|
+
const [, expression] = derivativeMatch;
|
|
249
|
+
return this.mockDifferentiate(expression);
|
|
250
|
+
}
|
|
251
|
+
// Integrate with respect to variable: Integral(expression, variable)
|
|
252
|
+
const integralVarMatch = trimmed.match(/^Integral\s*\(\s*(.+?)\s*,\s*([a-zA-Z]\w*)\s*\)$/);
|
|
253
|
+
if (integralVarMatch && integralVarMatch[1] && integralVarMatch[2]) {
|
|
254
|
+
const [, expression, variable] = integralVarMatch;
|
|
255
|
+
return this.mockIntegrate(expression, variable);
|
|
256
|
+
}
|
|
257
|
+
// Integrate: Integral(expression)
|
|
258
|
+
const integralMatch = trimmed.match(/^Integral\s*\(\s*(.+)\s*\)$/);
|
|
259
|
+
if (integralMatch && integralMatch[1]) {
|
|
260
|
+
const [, expression] = integralMatch;
|
|
261
|
+
return this.mockIntegrate(expression);
|
|
262
|
+
}
|
|
263
|
+
// Simplify: Simplify(expression)
|
|
264
|
+
const simplifyMatch = trimmed.match(/^Simplify\s*\(\s*(.+)\s*\)$/);
|
|
265
|
+
if (simplifyMatch && simplifyMatch[1]) {
|
|
266
|
+
const [, expression] = simplifyMatch;
|
|
267
|
+
return this.mockSimplify(expression);
|
|
268
|
+
}
|
|
269
|
+
// Generic command (just acknowledge)
|
|
270
|
+
return `Command executed: ${command}`;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Execute command and get labels of created objects
|
|
274
|
+
*/
|
|
275
|
+
async evalCommandGetLabels(command) {
|
|
276
|
+
this.ensureInitialized();
|
|
277
|
+
this.updateActivity();
|
|
278
|
+
try {
|
|
279
|
+
const beforeObjects = new Set(this.objects.keys());
|
|
280
|
+
await this.evalCommand(command);
|
|
281
|
+
const afterObjects = new Set(this.objects.keys());
|
|
282
|
+
const newLabels = Array.from(afterObjects).filter(label => !beforeObjects.has(label));
|
|
283
|
+
logger_1.default.debug(`Mock command executed on instance ${this.id}, labels: ${newLabels.join(', ')}`);
|
|
284
|
+
return newLabels;
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
logger_1.default.error(`Failed to execute mock command with labels on instance ${this.id}`, { command, error });
|
|
288
|
+
throw new geogebra_1.GeoGebraCommandError(`Failed to execute command: ${error instanceof Error ? error.message : String(error)}`, command);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Delete an object
|
|
293
|
+
*/
|
|
294
|
+
async deleteObject(objName) {
|
|
295
|
+
this.ensureInitialized();
|
|
296
|
+
this.updateActivity();
|
|
297
|
+
try {
|
|
298
|
+
const deleted = this.objects.delete(objName);
|
|
299
|
+
if (deleted) {
|
|
300
|
+
logger_1.default.debug(`Deleted object ${objName} from mock instance ${this.id}`);
|
|
301
|
+
}
|
|
302
|
+
return deleted;
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
logger_1.default.error(`Failed to delete object ${objName} on mock instance ${this.id}`, error);
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Check if object exists
|
|
311
|
+
*/
|
|
312
|
+
async exists(objName) {
|
|
313
|
+
this.ensureInitialized();
|
|
314
|
+
this.updateActivity();
|
|
315
|
+
return this.objects.has(objName);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Check if object is defined
|
|
319
|
+
*/
|
|
320
|
+
async isDefined(objName) {
|
|
321
|
+
this.ensureInitialized();
|
|
322
|
+
this.updateActivity();
|
|
323
|
+
const obj = this.objects.get(objName);
|
|
324
|
+
return obj ? obj.defined : false;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Get all object names
|
|
328
|
+
*/
|
|
329
|
+
async getAllObjectNames(type) {
|
|
330
|
+
this.ensureInitialized();
|
|
331
|
+
this.updateActivity();
|
|
332
|
+
if (type) {
|
|
333
|
+
return Array.from(this.objects.values())
|
|
334
|
+
.filter(obj => obj.type === type)
|
|
335
|
+
.map(obj => obj.name);
|
|
336
|
+
}
|
|
337
|
+
return Array.from(this.objects.keys());
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Get object information
|
|
341
|
+
*/
|
|
342
|
+
async getObjectInfo(objName) {
|
|
343
|
+
this.ensureInitialized();
|
|
344
|
+
this.updateActivity();
|
|
345
|
+
return this.objects.get(objName) || null;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get X coordinate of object
|
|
349
|
+
*/
|
|
350
|
+
async getXcoord(objName) {
|
|
351
|
+
this.ensureInitialized();
|
|
352
|
+
this.updateActivity();
|
|
353
|
+
const obj = this.objects.get(objName);
|
|
354
|
+
return obj?.x || 0;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Get Y coordinate of object
|
|
358
|
+
*/
|
|
359
|
+
async getYcoord(objName) {
|
|
360
|
+
this.ensureInitialized();
|
|
361
|
+
this.updateActivity();
|
|
362
|
+
const obj = this.objects.get(objName);
|
|
363
|
+
return obj?.y || 0;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Get Z coordinate of object
|
|
367
|
+
*/
|
|
368
|
+
async getZcoord(objName) {
|
|
369
|
+
this.ensureInitialized();
|
|
370
|
+
this.updateActivity();
|
|
371
|
+
const obj = this.objects.get(objName);
|
|
372
|
+
return obj?.z || 0;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Get value of object
|
|
376
|
+
*/
|
|
377
|
+
async getValue(objName) {
|
|
378
|
+
this.ensureInitialized();
|
|
379
|
+
this.updateActivity();
|
|
380
|
+
const obj = this.objects.get(objName);
|
|
381
|
+
return typeof obj?.value === 'number' ? obj.value : 0;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Get value as string
|
|
385
|
+
*/
|
|
386
|
+
async getValueString(objName) {
|
|
387
|
+
this.ensureInitialized();
|
|
388
|
+
this.updateActivity();
|
|
389
|
+
const obj = this.objects.get(objName);
|
|
390
|
+
return obj?.value?.toString() || '';
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Create new construction
|
|
394
|
+
*/
|
|
395
|
+
async newConstruction() {
|
|
396
|
+
this.ensureInitialized();
|
|
397
|
+
this.updateActivity();
|
|
398
|
+
this.objects.clear();
|
|
399
|
+
logger_1.default.debug(`New construction created on mock instance ${this.id}`);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Reset to initial state
|
|
403
|
+
*/
|
|
404
|
+
async reset() {
|
|
405
|
+
this.ensureInitialized();
|
|
406
|
+
this.updateActivity();
|
|
407
|
+
this.objects.clear();
|
|
408
|
+
logger_1.default.debug(`Mock instance ${this.id} reset to initial state`);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Refresh all views
|
|
412
|
+
*/
|
|
413
|
+
async refreshViews() {
|
|
414
|
+
this.ensureInitialized();
|
|
415
|
+
this.updateActivity();
|
|
416
|
+
logger_1.default.debug(`Views refreshed on mock instance ${this.id}`);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Set coordinate system bounds (mock implementation)
|
|
420
|
+
*/
|
|
421
|
+
async setCoordSystem(xmin, xmax, ymin, ymax) {
|
|
422
|
+
this.ensureInitialized();
|
|
423
|
+
this.updateActivity();
|
|
424
|
+
logger_1.default.debug(`Mock coordinate system set on instance ${this.id}: x[${xmin}, ${xmax}], y[${ymin}, ${ymax}]`);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Set axes visibility (mock implementation)
|
|
428
|
+
*/
|
|
429
|
+
async setAxesVisible(xAxis, yAxis) {
|
|
430
|
+
this.ensureInitialized();
|
|
431
|
+
this.updateActivity();
|
|
432
|
+
logger_1.default.debug(`Mock axes visibility set on instance ${this.id}: x=${xAxis}, y=${yAxis}`);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Set grid visibility (mock implementation)
|
|
436
|
+
*/
|
|
437
|
+
async setGridVisible(visible) {
|
|
438
|
+
this.ensureInitialized();
|
|
439
|
+
this.updateActivity();
|
|
440
|
+
logger_1.default.debug(`Mock instance ${this.id}: Set grid visible: ${visible}`);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Check if instance is ready
|
|
444
|
+
*/
|
|
445
|
+
async isReady() {
|
|
446
|
+
return this.isInitialized;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Export construction as PNG (base64) - Mock implementation with enhanced parameters
|
|
450
|
+
*/
|
|
451
|
+
async exportPNG(scale = 1, transparent = false, dpi = 72, width, height) {
|
|
452
|
+
this.ensureInitialized();
|
|
453
|
+
this.updateActivity();
|
|
454
|
+
// Return a simple base64 encoded placeholder PNG
|
|
455
|
+
const placeholderPNG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
|
|
456
|
+
logger_1.default.debug(`Mock PNG exported from instance ${this.id} with scale ${scale}, transparent ${transparent}, dpi ${dpi}, dimensions ${width}x${height}`);
|
|
457
|
+
return placeholderPNG;
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Export construction as SVG - Mock implementation
|
|
461
|
+
*/
|
|
462
|
+
async exportSVG() {
|
|
463
|
+
this.ensureInitialized();
|
|
464
|
+
this.updateActivity();
|
|
465
|
+
// Return a simple SVG with mock construction
|
|
466
|
+
const mockSVG = `<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
|
|
467
|
+
<rect width="800" height="600" fill="white"/>
|
|
468
|
+
<text x="400" y="300" text-anchor="middle" font-family="Arial" font-size="20">Mock GeoGebra Construction</text>
|
|
469
|
+
${Array.from(this.objects.values()).map(obj => {
|
|
470
|
+
if (obj.type === 'point') {
|
|
471
|
+
return `<circle cx="${(obj.x || 0) * 50 + 400}" cy="${(obj.y || 0) * -50 + 300}" r="3" fill="${obj.color || '#0000FF'}"/>`;
|
|
472
|
+
}
|
|
473
|
+
return '';
|
|
474
|
+
}).join('\n ')}
|
|
475
|
+
</svg>`;
|
|
476
|
+
logger_1.default.debug(`Mock SVG exported from instance ${this.id}`);
|
|
477
|
+
return mockSVG.trim();
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Export construction as PDF (base64) - Mock implementation
|
|
481
|
+
*/
|
|
482
|
+
async exportPDF() {
|
|
483
|
+
this.ensureInitialized();
|
|
484
|
+
this.updateActivity();
|
|
485
|
+
logger_1.default.debug(`Mock PDF export from instance ${this.id}`);
|
|
486
|
+
// Return mock PDF data (base64 encoded)
|
|
487
|
+
const mockPdfData = 'JVBERi0xLjQKJcOkw7zDtsOgCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nDPQM1Qo5ypUMFAw0DMwULBVqOZSUDBQykvMTbVSUDC2UshIzStRyMnPS7VVqAUAYQsKZAplbmRzdHJlYW0KZW5kb2JqCgozIDAgb2JqCjI4CmVuZG9iagoKMSAwIG9iago8PC9UeXBlL0NhdGFsb2cvUGFnZXMgNCAwIFI+PgplbmRvYmoKCjQgMCBvYmoKPDwvVHlwZS9QYWdlcy9LaWRzWzUgMCBSXS9Db3VudCAxPj4KZW5kb2JqCgo1IDAgb2JqCjw8L1R5cGUvUGFnZS9QYXJlbnQgNCAwIFIvTWVkaWFCb3hbMCAwIDYxMiA3OTJdL0NvbnRlbnRzIDIgMCBSPj4KZW5kb2JqCgp4cmVmCjAgNgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAyOTQgMDAwMDAgbiAKMDAwMDAwMDAwOSAwMDAwMCBuIAowMDAwMDAwMjc0IDAwMDAwIG4gCjAwMDAwMDAzNDMgMDAwMDAgbiAKMDAwMDAwMDQwMCAwMDAwMCBuIAp0cmFpbGVyCjw8L1NpemUgNi9Sb290IDEgMCBSPj4Kc3RhcnR4cmVmCjUwMwolJUVPRg==';
|
|
488
|
+
return mockPdfData;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Export animation as frames (GEB-17 enhancement)
|
|
492
|
+
*/
|
|
493
|
+
async exportAnimation(options = {}) {
|
|
494
|
+
this.ensureInitialized();
|
|
495
|
+
this.updateActivity();
|
|
496
|
+
const { duration = 5000, // 5 seconds
|
|
497
|
+
frameRate = 10, // 10 fps
|
|
498
|
+
format = 'frames', width = 800, height = 600 } = options;
|
|
499
|
+
logger_1.default.debug(`Mock animation export from instance ${this.id}`, { duration, frameRate, format, width, height });
|
|
500
|
+
// Calculate number of frames
|
|
501
|
+
const totalFrames = Math.ceil((duration / 1000) * frameRate);
|
|
502
|
+
// Generate mock frame data
|
|
503
|
+
const frames = [];
|
|
504
|
+
for (let i = 0; i < totalFrames; i++) {
|
|
505
|
+
// Generate a simple mock PNG frame (base64 encoded)
|
|
506
|
+
const mockFrameData = `iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==_frame_${i}`;
|
|
507
|
+
frames.push(mockFrameData);
|
|
508
|
+
}
|
|
509
|
+
logger_1.default.debug(`Mock animation export completed: ${frames.length} frames generated`);
|
|
510
|
+
if (format === 'frames') {
|
|
511
|
+
return frames;
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
// For GIF format, return a mock GIF data string
|
|
515
|
+
return 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7_mock_gif';
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Cleanup resources
|
|
520
|
+
*/
|
|
521
|
+
async cleanup() {
|
|
522
|
+
logger_1.default.info(`Cleaning up Mock GeoGebra instance ${this.id}`);
|
|
523
|
+
this.objects.clear();
|
|
524
|
+
this.isInitialized = false;
|
|
525
|
+
logger_1.default.info(`Mock GeoGebra instance ${this.id} cleaned up successfully`);
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Get instance state
|
|
529
|
+
*/
|
|
530
|
+
getState() {
|
|
531
|
+
return {
|
|
532
|
+
id: this.id,
|
|
533
|
+
isReady: this.isInitialized,
|
|
534
|
+
lastActivity: this.lastActivity,
|
|
535
|
+
config: this.config
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Update last activity timestamp
|
|
540
|
+
*/
|
|
541
|
+
updateActivity() {
|
|
542
|
+
this.lastActivity = new Date();
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Ensure instance is initialized
|
|
546
|
+
*/
|
|
547
|
+
ensureInitialized() {
|
|
548
|
+
if (!this.isInitialized) {
|
|
549
|
+
throw new geogebra_1.GeoGebraConnectionError('Mock GeoGebra instance not initialized');
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Mock implementation of equation solving
|
|
554
|
+
*/
|
|
555
|
+
mockSolveEquation(equation, variable) {
|
|
556
|
+
logger_1.default.debug(`Mock solving equation: ${equation}${variable ? ` for ${variable}` : ''}`);
|
|
557
|
+
// Simple mock responses for common cases
|
|
558
|
+
if (equation.includes('x^2')) {
|
|
559
|
+
return variable ?
|
|
560
|
+
`{${variable} = -√(solution), ${variable} = √(solution)}` :
|
|
561
|
+
`Solutions: x = -√(solution), x = √(solution)`;
|
|
562
|
+
}
|
|
563
|
+
if (equation.includes('x =') || equation.includes('= x')) {
|
|
564
|
+
const match = equation.match(/(-?\d+(?:\.\d+)?)/);
|
|
565
|
+
const value = match ? match[1] : '0';
|
|
566
|
+
return variable ?
|
|
567
|
+
`{${variable} = ${value}}` :
|
|
568
|
+
`Solution: x = ${value}`;
|
|
569
|
+
}
|
|
570
|
+
// Linear equation pattern
|
|
571
|
+
if (equation.match(/\d*x\s*[+-]/)) {
|
|
572
|
+
return variable ?
|
|
573
|
+
`{${variable} = solution_value}` :
|
|
574
|
+
`Solution: x = solution_value`;
|
|
575
|
+
}
|
|
576
|
+
return `Mock solution for equation: ${equation}`;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Mock implementation of differentiation
|
|
580
|
+
*/
|
|
581
|
+
mockDifferentiate(expression, variable = 'x') {
|
|
582
|
+
logger_1.default.debug(`Mock differentiating: ${expression} with respect to ${variable}`);
|
|
583
|
+
// Simple mock responses for common cases
|
|
584
|
+
if (expression === variable) {
|
|
585
|
+
return '1';
|
|
586
|
+
}
|
|
587
|
+
if (expression.includes(`${variable}^2`)) {
|
|
588
|
+
return `2*${variable}`;
|
|
589
|
+
}
|
|
590
|
+
if (expression.includes(`${variable}^3`)) {
|
|
591
|
+
return `3*${variable}^2`;
|
|
592
|
+
}
|
|
593
|
+
if (expression.includes(`sin(${variable})`)) {
|
|
594
|
+
return `cos(${variable})`;
|
|
595
|
+
}
|
|
596
|
+
if (expression.includes(`cos(${variable})`)) {
|
|
597
|
+
return `-sin(${variable})`;
|
|
598
|
+
}
|
|
599
|
+
if (expression.includes(`e^${variable}`)) {
|
|
600
|
+
return `e^${variable}`;
|
|
601
|
+
}
|
|
602
|
+
if (!expression.includes(variable)) {
|
|
603
|
+
return '0';
|
|
604
|
+
}
|
|
605
|
+
return `d/d${variable}(${expression})`;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Mock implementation of integration
|
|
609
|
+
*/
|
|
610
|
+
mockIntegrate(expression, variable = 'x') {
|
|
611
|
+
logger_1.default.debug(`Mock integrating: ${expression} with respect to ${variable}`);
|
|
612
|
+
// Simple mock responses for common cases
|
|
613
|
+
if (expression === '1') {
|
|
614
|
+
return variable;
|
|
615
|
+
}
|
|
616
|
+
if (expression === variable) {
|
|
617
|
+
return `${variable}^2/2`;
|
|
618
|
+
}
|
|
619
|
+
if (expression.includes(`${variable}^2`)) {
|
|
620
|
+
return `${variable}^3/3`;
|
|
621
|
+
}
|
|
622
|
+
if (expression.includes(`${variable}^3`)) {
|
|
623
|
+
return `${variable}^4/4`;
|
|
624
|
+
}
|
|
625
|
+
if (expression.includes(`sin(${variable})`)) {
|
|
626
|
+
return `-cos(${variable})`;
|
|
627
|
+
}
|
|
628
|
+
if (expression.includes(`cos(${variable})`)) {
|
|
629
|
+
return `sin(${variable})`;
|
|
630
|
+
}
|
|
631
|
+
if (expression.includes(`e^${variable}`)) {
|
|
632
|
+
return `e^${variable}`;
|
|
633
|
+
}
|
|
634
|
+
return `∫(${expression}, ${variable})dx`;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Mock implementation of expression simplification
|
|
638
|
+
*/
|
|
639
|
+
mockSimplify(expression) {
|
|
640
|
+
logger_1.default.debug(`Mock simplifying: ${expression}`);
|
|
641
|
+
// Simple mock simplifications
|
|
642
|
+
let simplified = expression;
|
|
643
|
+
// Remove unnecessary parentheses and spaces
|
|
644
|
+
simplified = simplified.replace(/\s+/g, '');
|
|
645
|
+
simplified = simplified.replace(/\(([^()]+)\)/g, '$1');
|
|
646
|
+
// Combine like terms (very basic)
|
|
647
|
+
simplified = simplified.replace(/(\d+)\*x\+(\d+)\*x/g, (_match, a, b) => {
|
|
648
|
+
return `${parseInt(a) + parseInt(b)}*x`;
|
|
649
|
+
});
|
|
650
|
+
// Basic arithmetic
|
|
651
|
+
simplified = simplified.replace(/(\d+)\+(\d+)/g, (_match, a, b) => {
|
|
652
|
+
return `${parseInt(a) + parseInt(b)}`;
|
|
653
|
+
});
|
|
654
|
+
simplified = simplified.replace(/(\d+)\*1/g, '$1');
|
|
655
|
+
simplified = simplified.replace(/1\*(\d+)/g, '$1');
|
|
656
|
+
simplified = simplified.replace(/\+0/g, '');
|
|
657
|
+
simplified = simplified.replace(/0\+/g, '');
|
|
658
|
+
return simplified === expression ? expression : simplified;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Animation Methods
|
|
662
|
+
*/
|
|
663
|
+
async setAnimating(objName, animate) {
|
|
664
|
+
this.ensureInitialized();
|
|
665
|
+
this.updateActivity();
|
|
666
|
+
if (!this.objects.has(objName)) {
|
|
667
|
+
throw new Error(`Object ${objName} does not exist`);
|
|
668
|
+
}
|
|
669
|
+
if (animate) {
|
|
670
|
+
this.animatingObjects.add(objName);
|
|
671
|
+
if (!this.animationSpeeds.has(objName)) {
|
|
672
|
+
this.animationSpeeds.set(objName, 1); // Default speed
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
this.animatingObjects.delete(objName);
|
|
677
|
+
}
|
|
678
|
+
logger_1.default.debug(`Mock instance ${this.id}: Set animating for ${objName}: ${animate}`);
|
|
679
|
+
}
|
|
680
|
+
async setAnimationSpeed(objName, speed) {
|
|
681
|
+
this.ensureInitialized();
|
|
682
|
+
this.updateActivity();
|
|
683
|
+
if (!this.objects.has(objName)) {
|
|
684
|
+
throw new Error(`Object ${objName} does not exist`);
|
|
685
|
+
}
|
|
686
|
+
this.animationSpeeds.set(objName, speed);
|
|
687
|
+
logger_1.default.debug(`Mock instance ${this.id}: Set animation speed for ${objName}: ${speed}`);
|
|
688
|
+
}
|
|
689
|
+
async startAnimation() {
|
|
690
|
+
this.ensureInitialized();
|
|
691
|
+
this.updateActivity();
|
|
692
|
+
this.isAnimating = true;
|
|
693
|
+
logger_1.default.debug(`Mock instance ${this.id}: Started animation for ${this.animatingObjects.size} objects`);
|
|
694
|
+
}
|
|
695
|
+
async stopAnimation() {
|
|
696
|
+
this.ensureInitialized();
|
|
697
|
+
this.updateActivity();
|
|
698
|
+
this.isAnimating = false;
|
|
699
|
+
logger_1.default.debug(`Mock instance ${this.id}: Stopped animation`);
|
|
700
|
+
}
|
|
701
|
+
async isAnimationRunning() {
|
|
702
|
+
this.ensureInitialized();
|
|
703
|
+
this.updateActivity();
|
|
704
|
+
return this.isAnimating && this.animatingObjects.size > 0;
|
|
705
|
+
}
|
|
706
|
+
async setTrace(objName, flag) {
|
|
707
|
+
this.ensureInitialized();
|
|
708
|
+
this.updateActivity();
|
|
709
|
+
if (!this.objects.has(objName)) {
|
|
710
|
+
throw new Error(`Object ${objName} does not exist`);
|
|
711
|
+
}
|
|
712
|
+
if (flag) {
|
|
713
|
+
this.tracedObjects.add(objName);
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
this.tracedObjects.delete(objName);
|
|
717
|
+
}
|
|
718
|
+
logger_1.default.debug(`Mock instance ${this.id}: Set trace for ${objName}: ${flag}`);
|
|
719
|
+
}
|
|
720
|
+
async setValue(objName, value) {
|
|
721
|
+
this.ensureInitialized();
|
|
722
|
+
this.updateActivity();
|
|
723
|
+
const obj = this.objects.get(objName);
|
|
724
|
+
if (!obj) {
|
|
725
|
+
throw new Error(`Object ${objName} does not exist`);
|
|
726
|
+
}
|
|
727
|
+
obj.value = value;
|
|
728
|
+
logger_1.default.debug(`Mock instance ${this.id}: Set value for ${objName}: ${value}`);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
exports.MockGeoGebraInstance = MockGeoGebraInstance;
|
|
732
|
+
//# sourceMappingURL=geogebra-mock.js.map
|