Working analytics

This commit is contained in:
2025-08-06 15:08:57 -05:00
parent 7877651ab0
commit fd01ccf8af
3 changed files with 101 additions and 11 deletions
+20 -1
View File
@@ -27,7 +27,26 @@
"key": "shift+enter", "key": "shift+enter",
"when": "editorTextFocus" "when": "editorTextFocus"
} }
] ],
"viewsContainers": {
"panel": [
{
"id": "myCustomPanel",
"title": "My Custom Panel",
"icon": "$(file-code)"
}
]
},
"views": {
"myCustomPanel": [
{
"type": "tree",
"id": "myCustomTab",
"name": "My Tab",
"icon": "$(file-code)"
}
]
}
}, },
"scripts": { "scripts": {
"vscode:prepublish": "tsc -p ./", "vscode:prepublish": "tsc -p ./",
+23 -10
View File
@@ -2,8 +2,9 @@ import * as vscode from 'vscode';
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import testCode from './tester'; import testCode, { TestResult } from './tester';
import * as utils from './utils'; import * as utils from './utils';
import { MyTreeDataProvider } from './resultViewer';
let resetTimer = () => {} let resetTimer = () => {}
@@ -30,7 +31,7 @@ export function activate(context: vscode.ExtensionContext) {
statusBarItem.text = "No active Speedrun"; statusBarItem.text = "No active Speedrun";
statusBarItem.show(); statusBarItem.show();
let run: undefined | { path: string, elapsed: number, timer: NodeJS.Timeout }; let run: undefined | { path: string, elapsed: number, timer: NodeJS.Timeout, blunders: [number, TestResult[]][] };
resetTimer = () => { resetTimer = () => {
if (run) { if (run) {
@@ -42,18 +43,29 @@ export function activate(context: vscode.ExtensionContext) {
resetTimer(); resetTimer();
const treeDataProvider = new MyTreeDataProvider();
vscode.window.registerTreeDataProvider('myCustomTab', treeDataProvider);
context.subscriptions.push(vscode.commands.registerCommand('speed-code.submitSpeedRun', () => { context.subscriptions.push(vscode.commands.registerCommand('speed-code.submitSpeedRun', () => {
if (run) { if (run) {
const [isValid, res] = testCode(fs.readFileSync(run.path).toString(), [ try {
{ input: ["racecar"], expected: true }, const [isValid, res] = testCode(fs.readFileSync(run.path).toString(), [
{ input: ["hello"], expected: true }, { input: ["racecar"], expected: true },
{ input: ["madam"], expected: true }, { input: ["hello"], expected: false },
]); { input: ["madam"], expected: true },
]);
vscode.window.showInformationMessage('Time: ' + run.elapsed); treeDataProvider.testResults = res;
treeDataProvider.testSummary = { elapsed: run.elapsed, valid: isValid };
treeDataProvider.blunders = run.blunders;
treeDataProvider.refresh();
if (isValid) { if (isValid) {
resetTimer(); resetTimer();
}
} catch {
// TODO: blunders
} }
} }
})); }));
@@ -68,6 +80,7 @@ export function activate(context: vscode.ExtensionContext) {
run = { run = {
path: runFilePath, path: runFilePath,
elapsed: 0, elapsed: 0,
blunders: [],
timer: setInterval(() => { timer: setInterval(() => {
if (!run) return; if (!run) return;
const currentTime = Date.now(); const currentTime = Date.now();
+58
View File
@@ -0,0 +1,58 @@
import * as vscode from 'vscode';
import { TestResult } from './tester';
import { format } from './utils';
class RunTreeItem extends vscode.TreeItem {
children?: RunTreeItem[];
constructor(label: string | vscode.TreeItemLabel, description?: string, children?: RunTreeItem[], expanded?: boolean) {
super(label, children ? (expanded ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.Collapsed) : vscode.TreeItemCollapsibleState.None)
this.children = children;
this.description = description;
}
}
export class MyTreeDataProvider implements vscode.TreeDataProvider<RunTreeItem> {
private _onDidChangeTreeData: vscode.EventEmitter<RunTreeItem | undefined | void> = new vscode.EventEmitter();
readonly onDidChangeTreeData: vscode.Event<RunTreeItem | undefined | void> = this._onDidChangeTreeData.event;
testResults: TestResult[] = [];
testSummary: undefined | { elapsed: number, valid: boolean };
blunders: [number, TestResult[]][] = [];
refresh(): void {
this._onDidChangeTreeData.fire();
}
getTreeItem(element: RunTreeItem): RunTreeItem {
return element;
}
getChildren(element?: RunTreeItem): Thenable<RunTreeItem[]> {
if (!element) {
const items: RunTreeItem[] = [];
if (this.testSummary) {
items.push(new RunTreeItem(`Speedrun Summary`, undefined, [
new RunTreeItem("Time Elapsed", format(this.testSummary.elapsed)),
new RunTreeItem("Test Passed", this.testSummary.valid ? '✅ Passed' : '❌ Failed'),
], true));
}
// TODO: blunders
this.testResults.forEach(t => {
const item = new RunTreeItem(`(${JSON.stringify(t.input)})`, undefined, [
new RunTreeItem('Output', `${t.result}`),
new RunTreeItem('Expected Output', `${t.expected}`),
]);
item.description = t.valid ? '✅ Passed' : '❌ Failed';
items.push(item);
});
return Promise.resolve(items);
} else {
return Promise.resolve(element.children || []);
}
}
}