/** * Is a work/ file a real solution or just a scaffolded stub? * * `bun run pick` writes a statement header plus an empty function body, so * file existence alone means nothing: close-solved.ts must not close an issue * on a stub, and work.ts must not ask for the spaced-repetition re-solve of a * problem that was never solved in the first place. * * sync.ts keeps its own copy of the header split — it runs its whole pipeline * on import, so it cannot be imported from. Don't "deduplicate" that one. * * Library: side-effect-free on import. */ /** Placeholder bodies that leetcode-cli / a human leaves behind. */ const PLACEHOLDERS: Record = { pass: true, "...": true, TODO: true }; /** * Decide whether a work/ file contains an implementation. * * The header comment is dropped the same way sync.ts splitSource() does it. * Comments must go before any brace analysis: the scaffold's JSDoc carries * `@param {number[]}`, whose braces would otherwise read as a body. * * A brace-language file counts as implemented when at least one *innermost* * brace pair holds real content. That distinguishes a bare stub * (`function(nums) {}`) and a class-shaped design stub (every method body * empty) from any genuine solution, whose innermost block always has code. * Every non-Python language the campaign has ever used is brace-shaped, so * "not .py" is the only branch that matters. */ export function isImplemented(src: string, lang: "js" | "py"): boolean { if (lang === "py") { const open = src.indexOf('"""'); const close = src.indexOf('"""', open + 3); const code = open === -1 || close === -1 ? src : src.slice(close + 3); for (const raw of code.split("\n")) { const line = raw.replace(/#.*$/, "").trim(); if (!line || PLACEHOLDERS[line]) continue; if (/^(?:@|def\s|class\s)/.test(line)) continue; return true; // a statement inside some def body } return false; } const headerEnd = src.indexOf("*/"); const body = headerEnd === -1 ? src : src.slice(headerEnd + 2); const code = body.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/.*$/gm, " "); let innermost = -1; for (let i = 0; i < code.length; i++) { if (code[i] === "{") { innermost = i; } else if (code[i] === "}" && innermost !== -1) { const inner = code.slice(innermost + 1, i).replace(/[\s;]/g, ""); if (inner && !PLACEHOLDERS[inner]) return true; innermost = -1; // measured; the enclosing pair is not innermost } } return false; }