diff --git a/src/services/tools/codeAnalyzer.ts b/src/services/tools/codeAnalyzer.ts new file mode 100644 index 0000000..1db1e93 --- /dev/null +++ b/src/services/tools/codeAnalyzer.ts @@ -0,0 +1,107 @@ +/** + * 代码分析工具 + * 用于分析代码特征,判断执行方式 + * 可在服务端和客户端运行 + */ + +// 加载状态回调类型(定义在这里以便服务端使用) +export type LoadingCallback = (status: { + stage: 'loading' | 'ready' | 'error'; + message: string; + progress?: number; +}) => void; + +/** + * 检测代码是否包含图形绘制相关内容 + */ +export function detectGraphicsCode(code: string): boolean { + const graphicsKeywords = [ + // matplotlib + 'matplotlib', + 'pyplot', + 'plt.', + '.plot(', + '.scatter(', + '.bar(', + '.barh(', + '.hist(', + '.pie(', + '.boxplot(', + '.violinplot(', + '.heatmap(', + '.imshow(', + '.contour(', + '.fill(', + '.errorbar(', + '.stem(', + '.step(', + 'savefig', + 'show()', + '.figure(', + '.subplot(', + '.subplots(', + // seaborn + 'seaborn', + 'sns.', + // plotly + 'plotly', + 'px.', + 'go.Figure', + // 其他可视化库 + 'bokeh', + 'altair', + ]; + + const lowerCode = code.toLowerCase(); + return graphicsKeywords.some(keyword => lowerCode.includes(keyword.toLowerCase())); +} + +/** + * 判断是否应该使用 Pyodide(浏览器端)执行 + * @param code 代码内容 + * @param language 编程语言 + * @returns 是否需要浏览器端 Pyodide 执行 + */ +export function shouldUsePyodide(code: string, language: string): boolean { + // 只有 Python 代码才考虑使用 Pyodide + if (!['python', 'python3', 'py'].includes(language.toLowerCase())) { + return false; + } + + // 如果代码包含图形绘制,需要使用 Pyodide + return detectGraphicsCode(code); +} + +/** + * 分析代码类型 + */ +export interface CodeAnalysis { + language: string; + hasGraphics: boolean; + requiresPyodide: boolean; + estimatedComplexity: 'simple' | 'medium' | 'complex'; +} + +/** + * 分析代码特征 + */ +export function analyzeCode(code: string, language: string): CodeAnalysis { + const hasGraphics = detectGraphicsCode(code); + const requiresPyodide = shouldUsePyodide(code, language); + + // 估算复杂度 + const lines = code.split('\n').filter(l => l.trim()).length; + let complexity: 'simple' | 'medium' | 'complex' = 'simple'; + if (lines > 50 || hasGraphics) { + complexity = 'complex'; + } else if (lines > 20) { + complexity = 'medium'; + } + + return { + language: language.toLowerCase(), + hasGraphics, + requiresPyodide, + estimatedComplexity: complexity, + }; +}