@exercode/problem-utils 1.5.4 → 1.6.0

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.
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("../_virtual/_rollupPluginBabelHelpers.cjs"),r=require("node:fs"),n=require("node:path"),a=require("../types/decisionCode.cjs"),t=require("./findLanguageDefinitionByPath.cjs"),c=require("./removeCommentsInSourceCode.cjs");function o(){return(o=e.asyncToGenerator(e.regenerator().m(function o(s,i){var u,f,p,d,l,h,g,b,m,k,v,R,C,I,y,E,O,_,w,D,F,j,q,x,S,T,H,P,B,N,A,L,M,G;return e.regenerator().w(function(o){for(;;)switch(o.p=o.n){case 0:return f=[],A=e.createForOfIteratorHelper,o.n=1,r.promises.readdir(s,{withFileTypes:!0,recursive:!0});case 1:p=A(o.v),o.p=2,p.s();case 3:if((d=p.n()).done){o.n=9;break}if((l=d.value).isFile()){o.n=4;break}return o.a(3,8);case 4:return o.n=5,r.promises.readFile(n.join(l.parentPath,l.name),"utf8");case 5:if(h=o.v,!h.includes("�")){o.n=6;break}return o.a(3,8);case 6:if(g=t.findLanguageDefinitionByPath(l.name)){o.n=7;break}return o.a(3,8);case 7:f.push({path:l.name,data:g.grammer?c.removeCommentsInSourceCode(g.grammer,h):h});case 8:o.n=3;break;case 9:o.n=11;break;case 10:o.p=10,L=o.v,p.e(L);case 11:return o.p=11,p.f(),o.f(11);case 12:b=[],m=0,k=f;case 13:if(!(m<k.length)){o.n=23;break}C=k[m],I=e.createForOfIteratorHelper(null!=(v=i.forbiddenRegExpsInCode)?v:[]);try{for(I.s();!(y=I.n()).done;){E=y.value,O=new RegExp(E,"g"),_=C.data.matchAll(O),w=e.createForOfIteratorHelper(_);try{for(w.s();!(D=w.n()).done;)F=D.value,b.push({pattern:O.toString(),path:C.path,match:F[0]})}catch(e){w.e(e)}finally{w.f()}}}catch(e){I.e(e)}finally{I.f()}j=e.createForOfIteratorHelper(null!=(R=i.forbiddenTextsInCode)?R:[]),o.p=14,j.s();case 15:if((q=j.n()).done){o.n=19;break}x=q.value,S=0;case 16:if(!(S<C.data.length)){o.n=18;break}if(-1!==(T=C.data.indexOf(x,S))){o.n=17;break}return o.a(3,18);case 17:b.push({pattern:x,path:C.path,match:x}),S=T+x.length,o.n=16;break;case 18:o.n=15;break;case 19:o.n=21;break;case 20:o.p=20,M=o.v,j.e(M);case 21:return o.p=21,j.f(),o.f(21);case 22:m++,o.n=13;break;case 23:if(!(b.length>0)){o.n=24;break}return o.a(2,{decisionCode:a.DecisionCode.FORBIDDEN_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n".concat(b.map(function(e){return"| `".concat(e.path,"` | `").concat(e.pattern,"` | `").concat(e.match,"` |")}).join("\n"),"\n")});case 24:H=[],P=e.createForOfIteratorHelper(null!=(u=i.requiredRegExpsInCode)?u:[]),o.p=25,N=e.regenerator().m(function r(){var n,a;return e.regenerator().w(function(e){for(;;)switch(e.n){case 0:n=B.value,a=new RegExp(n),f.some(function(e){return a.test(e.data)})||H.push(a.toString());case 1:return e.a(2)}},r)}),P.s();case 26:if((B=P.n()).done){o.n=28;break}return o.d(e.regeneratorValues(N()),27);case 27:o.n=26;break;case 28:o.n=30;break;case 29:o.p=29,G=o.v,P.e(G);case 30:return o.p=30,P.f(),o.f(30);case 31:if(!(H.length>0)){o.n=32;break}return o.a(2,{decisionCode:a.DecisionCode.REQUIRED_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n".concat(H.map(function(e){return"- `".concat(e,"`")}).join("\n"),"\n")});case 32:return o.a(2)}},o,null,[[25,29,30,31],[14,20,21,22],[2,10,11,12]])}))).apply(this,arguments)}exports.judgeByStaticAnalysis=function(e,r){return o.apply(this,arguments)};
1
+ "use strict";var e=require("../_virtual/_rollupPluginBabelHelpers.cjs"),n=require("node:fs"),r=require("node:path"),a=require("../types/decisionCode.cjs"),t=require("./findLanguageDefinitionByPath.cjs"),c=require("./removeCommentsInSourceCode.cjs");function o(){return(o=e.asyncToGenerator(e.regenerator().m(function o(i,s){var u,f,d,p,l,h,b,m,k,g,I,R,v,E,C,S,_,y,O,F,w,D,j,q,P,x,N,T,B,H,M,A,L,U,G,Q,V;return e.regenerator().w(function(o){for(;;)switch(o.p=o.n){case 0:return f=new Set,d=[],U=e.createForOfIteratorHelper,o.n=1,n.promises.readdir(i,{withFileTypes:!0,recursive:!0});case 1:p=U(o.v),o.p=2,p.s();case 3:if((l=p.n()).done){o.n=9;break}if((h=l.value).isFile()){o.n=4;break}return o.a(3,8);case 4:return b=r.relative(i,r.join(h.parentPath,h.name)),f.add(b),o.n=5,n.promises.readFile(r.join(h.parentPath,h.name),"utf8");case 5:if(m=o.v,!m.includes("�")){o.n=6;break}return o.a(3,8);case 6:if(k=t.findLanguageDefinitionByPath(h.name)){o.n=7;break}return o.a(3,8);case 7:d.push({path:h.name,data:k.grammer?c.removeCommentsInSourceCode(k.grammer,m):m});case 8:o.n=3;break;case 9:o.n=11;break;case 10:o.p=10,G=o.v,p.e(G);case 11:return o.p=11,p.f(),o.f(11);case 12:if(!s.requiredSubmissionFilePaths){o.n=13;break}if(g=s.requiredSubmissionFilePaths.filter(function(e){return!f.has(e)}).toSorted(),!(g.length>0)){o.n=13;break}return o.a(2,{decisionCode:a.DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,feedbackMarkdown:"ファイルが不足しています。\n次のファイルを追加してから再度提出してください。\n\n".concat(g.map(function(e){return"- `".concat(e,"`")}).join("\n"),"\n")});case 13:I=[],R=0,v=d;case 14:if(!(R<v.length)){o.n=24;break}S=v[R],_=e.createForOfIteratorHelper(null!=(E=s.forbiddenRegExpsInCode)?E:[]);try{for(_.s();!(y=_.n()).done;){O=y.value,F=new RegExp(O,"g"),w=S.data.matchAll(F),D=e.createForOfIteratorHelper(w);try{for(D.s();!(j=D.n()).done;)q=j.value,I.push({pattern:F.toString(),path:S.path,match:q[0]})}catch(e){D.e(e)}finally{D.f()}}}catch(e){_.e(e)}finally{_.f()}P=e.createForOfIteratorHelper(null!=(C=s.forbiddenTextsInCode)?C:[]),o.p=15,P.s();case 16:if((x=P.n()).done){o.n=20;break}N=x.value,T=0;case 17:if(!(T<S.data.length)){o.n=19;break}if(-1!==(B=S.data.indexOf(N,T))){o.n=18;break}return o.a(3,19);case 18:I.push({pattern:N,path:S.path,match:N}),T=B+N.length,o.n=17;break;case 19:o.n=16;break;case 20:o.n=22;break;case 21:o.p=21,Q=o.v,P.e(Q);case 22:return o.p=22,P.f(),o.f(22);case 23:R++,o.n=14;break;case 24:if(!(I.length>0)){o.n=25;break}return o.a(2,{decisionCode:a.DecisionCode.FORBIDDEN_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n".concat(I.map(function(e){return"| `".concat(e.path,"` | `").concat(e.pattern,"` | `").concat(e.match,"` |")}).join("\n"),"\n")});case 25:H=[],M=e.createForOfIteratorHelper(null!=(u=s.requiredRegExpsInCode)?u:[]),o.p=26,L=e.regenerator().m(function n(){var r,a;return e.regenerator().w(function(e){for(;;)switch(e.n){case 0:r=A.value,a=new RegExp(r),d.some(function(e){return a.test(e.data)})||H.push(a.toString());case 1:return e.a(2)}},n)}),M.s();case 27:if((A=M.n()).done){o.n=29;break}return o.d(e.regeneratorValues(L()),28);case 28:o.n=27;break;case 29:o.n=31;break;case 30:o.p=30,V=o.v,M.e(V);case 31:return o.p=31,M.f(),o.f(31);case 32:if(!(H.length>0)){o.n=33;break}return o.a(2,{decisionCode:a.DecisionCode.REQUIRED_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n".concat(H.map(function(e){return"- `".concat(e,"`")}).join("\n"),"\n")});case 33:return o.a(2)}},o,null,[[26,30,31,32],[15,21,22,23],[2,10,11,12]])}))).apply(this,arguments)}exports.judgeByStaticAnalysis=function(e,n){return o.apply(this,arguments)};
2
2
  //# sourceMappingURL=judgeByStaticAnalysis.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"judgeByStaticAnalysis.cjs","sources":["../../src/helpers/judgeByStaticAnalysis.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { findLanguageDefinitionByPath } from './findLanguageDefinitionByPath.js';\nimport { removeCommentsInSourceCode } from './removeCommentsInSourceCode.js';\n\nexport async function judgeByStaticAnalysis(\n cwd: string,\n problemMarkdownFrontMatterLike: Pick<\n ProblemMarkdownFrontMatter,\n 'forbiddenRegExpsInCode' | 'forbiddenTextsInCode' | 'requiredRegExpsInCode'\n >\n): Promise<Pick<TestCaseResult, 'decisionCode' | 'feedbackMarkdown'> | undefined> {\n const sourceCodeWithoutCommentFiles: { path: string; data: string }[] = [];\n\n for (const dirent of await fs.promises.readdir(cwd, { withFileTypes: true, recursive: true })) {\n if (!dirent.isFile()) continue;\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n const isBinary = text.includes('\\uFFFD');\n if (isBinary) continue;\n\n const languageDefinition = findLanguageDefinitionByPath(dirent.name);\n if (!languageDefinition) continue;\n\n sourceCodeWithoutCommentFiles.push({\n path: dirent.name,\n data: languageDefinition.grammer ? removeCommentsInSourceCode(languageDefinition.grammer, text) : text,\n });\n }\n\n const forbiddenFounds: { pattern: string; path: string; match: string }[] = [];\n\n for (const file of sourceCodeWithoutCommentFiles) {\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenRegExpsInCode ?? []) {\n const re = new RegExp(pattern, 'g');\n const mathces = file.data.matchAll(re);\n for (const match of mathces) forbiddenFounds.push({ pattern: re.toString(), path: file.path, match: match[0] });\n }\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenTextsInCode ?? []) {\n let p = 0;\n while (p < file.data.length) {\n const index = file.data.indexOf(pattern, p);\n if (index === -1) break;\n forbiddenFounds.push({ pattern, path: file.path, match: pattern });\n p = index + pattern.length;\n }\n }\n }\n\n if (forbiddenFounds.length > 0) {\n return {\n decisionCode: DecisionCode.FORBIDDEN_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n${forbiddenFounds.map((f) => `| \\`${f.path}\\` | \\`${f.pattern}\\` | \\`${f.match}\\` |`).join('\\n')}\n`,\n };\n }\n\n const missingRequiredPatterns: string[] = [];\n\n for (const pattern of problemMarkdownFrontMatterLike.requiredRegExpsInCode ?? []) {\n const re = new RegExp(pattern);\n const isFound = sourceCodeWithoutCommentFiles.some((f) => re.test(f.data));\n if (!isFound) missingRequiredPatterns.push(re.toString());\n }\n\n if (missingRequiredPatterns.length > 0) {\n return {\n decisionCode: DecisionCode.REQUIRED_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n${missingRequiredPatterns.map((p) => `- \\`${p}\\``).join('\\n')}\n`,\n };\n }\n\n return;\n}\n"],"names":["_judgeByStaticAnalysis","_asyncToGenerator","_regenerator","m","_callee","cwd","problemMarkdownFrontMatterLike","_problemMarkdownFront3","sourceCodeWithoutCommentFiles","_iterator","_step","dirent","text","languageDefinition","forbiddenFounds","_i","_sourceCodeWithoutCom","_problemMarkdownFront","_problemMarkdownFront2","file","_iterator2","_step2","pattern","re","mathces","_iterator4","_step4","match","_iterator3","_step3","_pattern","p","index","missingRequiredPatterns","_iterator5","_step5","_loop","_t","_t2","_t3","_t4","w","_context2","n","_createForOfIteratorHelper","fs","promises","readdir","withFileTypes","recursive","v","s","done","value","isFile","a","readFile","path","join","parentPath","name","includes","findLanguageDefinitionByPath","push","data","grammer","removeCommentsInSourceCode","e","f","length","forbiddenRegExpsInCode","RegExp","matchAll","toString","err","forbiddenTextsInCode","indexOf","decisionCode","DecisionCode","FORBIDDEN_PATTERNS_IN_CODE_ERROR","feedbackMarkdown","concat","map","requiredRegExpsInCode","_context","some","test","d","_regeneratorValues","REQUIRED_PATTERNS_IN_CODE_ERROR","apply","this","arguments","_x","_x2"],"mappings":"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"}
1
+ {"version":3,"file":"judgeByStaticAnalysis.cjs","sources":["../../src/helpers/judgeByStaticAnalysis.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { findLanguageDefinitionByPath } from './findLanguageDefinitionByPath.js';\nimport { removeCommentsInSourceCode } from './removeCommentsInSourceCode.js';\n\nexport async function judgeByStaticAnalysis(\n cwd: string,\n problemMarkdownFrontMatterLike: Pick<\n ProblemMarkdownFrontMatter,\n 'forbiddenRegExpsInCode' | 'forbiddenTextsInCode' | 'requiredRegExpsInCode' | 'requiredSubmissionFilePaths'\n >\n): Promise<Pick<TestCaseResult, 'decisionCode' | 'feedbackMarkdown'> | undefined> {\n const filePathSet = new Set<string>();\n const sourceCodeWithoutCommentFiles: { path: string; data: string }[] = [];\n\n for (const dirent of await fs.promises.readdir(cwd, { withFileTypes: true, recursive: true })) {\n if (!dirent.isFile()) continue;\n\n const relativePath = path.relative(cwd, path.join(dirent.parentPath, dirent.name));\n filePathSet.add(relativePath);\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n const isBinary = text.includes('\\uFFFD');\n if (isBinary) continue;\n\n const languageDefinition = findLanguageDefinitionByPath(dirent.name);\n if (!languageDefinition) continue;\n\n sourceCodeWithoutCommentFiles.push({\n path: dirent.name,\n data: languageDefinition.grammer ? removeCommentsInSourceCode(languageDefinition.grammer, text) : text,\n });\n }\n\n if (problemMarkdownFrontMatterLike.requiredSubmissionFilePaths) {\n const missingFilePaths = problemMarkdownFrontMatterLike.requiredSubmissionFilePaths\n .filter((p) => !filePathSet.has(p))\n .toSorted();\n\n if (missingFilePaths.length > 0) {\n return {\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n feedbackMarkdown: `ファイルが不足しています。\n次のファイルを追加してから再度提出してください。\n\n${missingFilePaths.map((p) => `- \\`${p}\\``).join('\\n')}\n`,\n };\n }\n }\n\n const forbiddenFounds: { pattern: string; path: string; match: string }[] = [];\n\n for (const file of sourceCodeWithoutCommentFiles) {\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenRegExpsInCode ?? []) {\n const re = new RegExp(pattern, 'g');\n const mathces = file.data.matchAll(re);\n for (const match of mathces) forbiddenFounds.push({ pattern: re.toString(), path: file.path, match: match[0] });\n }\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenTextsInCode ?? []) {\n let p = 0;\n while (p < file.data.length) {\n const index = file.data.indexOf(pattern, p);\n if (index === -1) break;\n forbiddenFounds.push({ pattern, path: file.path, match: pattern });\n p = index + pattern.length;\n }\n }\n }\n\n if (forbiddenFounds.length > 0) {\n return {\n decisionCode: DecisionCode.FORBIDDEN_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n${forbiddenFounds.map((f) => `| \\`${f.path}\\` | \\`${f.pattern}\\` | \\`${f.match}\\` |`).join('\\n')}\n`,\n };\n }\n\n const missingRequiredPatterns: string[] = [];\n\n for (const pattern of problemMarkdownFrontMatterLike.requiredRegExpsInCode ?? []) {\n const re = new RegExp(pattern);\n const isFound = sourceCodeWithoutCommentFiles.some((f) => re.test(f.data));\n if (!isFound) missingRequiredPatterns.push(re.toString());\n }\n\n if (missingRequiredPatterns.length > 0) {\n return {\n decisionCode: DecisionCode.REQUIRED_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n${missingRequiredPatterns.map((p) => `- \\`${p}\\``).join('\\n')}\n`,\n };\n }\n\n return;\n}\n"],"names":["_judgeByStaticAnalysis","_asyncToGenerator","_regenerator","m","_callee","cwd","problemMarkdownFrontMatterLike","_problemMarkdownFront3","filePathSet","sourceCodeWithoutCommentFiles","_iterator","_step","dirent","relativePath","text","languageDefinition","missingFilePaths","forbiddenFounds","_i","_sourceCodeWithoutCom","_problemMarkdownFront","_problemMarkdownFront2","file","_iterator2","_step2","pattern","re","mathces","_iterator4","_step4","match","_iterator3","_step3","_pattern","p","index","missingRequiredPatterns","_iterator5","_step5","_loop","_t","_t2","_t3","_t4","w","_context2","n","Set","_createForOfIteratorHelper","fs","promises","readdir","withFileTypes","recursive","v","s","done","value","isFile","a","path","relative","join","parentPath","name","add","readFile","includes","findLanguageDefinitionByPath","push","data","grammer","removeCommentsInSourceCode","e","f","requiredSubmissionFilePaths","filter","has","toSorted","length","decisionCode","DecisionCode","MISSING_REQUIRED_SUBMISSION_FILE_ERROR","feedbackMarkdown","concat","map","forbiddenRegExpsInCode","RegExp","matchAll","toString","err","forbiddenTextsInCode","indexOf","FORBIDDEN_PATTERNS_IN_CODE_ERROR","requiredRegExpsInCode","_context","some","test","d","_regeneratorValues","REQUIRED_PATTERNS_IN_CODE_ERROR","apply","this","arguments","_x","_x2"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  import type { ProblemMarkdownFrontMatter } from '../types/problem.js';
2
2
  import type { TestCaseResult } from '../types/testCaseResult.js';
3
- export declare function judgeByStaticAnalysis(cwd: string, problemMarkdownFrontMatterLike: Pick<ProblemMarkdownFrontMatter, 'forbiddenRegExpsInCode' | 'forbiddenTextsInCode' | 'requiredRegExpsInCode'>): Promise<Pick<TestCaseResult, 'decisionCode' | 'feedbackMarkdown'> | undefined>;
3
+ export declare function judgeByStaticAnalysis(cwd: string, problemMarkdownFrontMatterLike: Pick<ProblemMarkdownFrontMatter, 'forbiddenRegExpsInCode' | 'forbiddenTextsInCode' | 'requiredRegExpsInCode' | 'requiredSubmissionFilePaths'>): Promise<Pick<TestCaseResult, 'decisionCode' | 'feedbackMarkdown'> | undefined>;
@@ -1,2 +1,2 @@
1
- import{asyncToGenerator as e,regenerator as n,regeneratorValues as a,createForOfIteratorHelper as r}from"../_virtual/_rollupPluginBabelHelpers.js";import t from"node:fs";import s from"node:path";import{DecisionCode as c}from"../types/decisionCode.js";import{findLanguageDefinitionByPath as o}from"./findLanguageDefinitionByPath.js";import{removeCommentsInSourceCode as i}from"./removeCommentsInSourceCode.js";function u(e,n){return f.apply(this,arguments)}function f(){return(f=e(n().m(function e(u,f){var p,d,l,m,h,b,k,g,v,R,E,y,C,_,w,I,j,x,O,T,D,F,N,P,S,A,B,H,M,q,G,L,Q,U;return n().w(function(e){for(;;)switch(e.p=e.n){case 0:return d=[],G=r,e.n=1,t.promises.readdir(u,{withFileTypes:!0,recursive:!0});case 1:l=G(e.v),e.p=2,l.s();case 3:if((m=l.n()).done){e.n=9;break}if((h=m.value).isFile()){e.n=4;break}return e.a(3,8);case 4:return e.n=5,t.promises.readFile(s.join(h.parentPath,h.name),"utf8");case 5:if(b=e.v,!b.includes("�")){e.n=6;break}return e.a(3,8);case 6:if(k=o(h.name)){e.n=7;break}return e.a(3,8);case 7:d.push({path:h.name,data:k.grammer?i(k.grammer,b):b});case 8:e.n=3;break;case 9:e.n=11;break;case 10:e.p=10,L=e.v,l.e(L);case 11:return e.p=11,l.f(),e.f(11);case 12:g=[],v=0,R=d;case 13:if(!(v<R.length)){e.n=23;break}C=R[v],_=r(null!=(E=f.forbiddenRegExpsInCode)?E:[]);try{for(_.s();!(w=_.n()).done;){I=w.value,j=new RegExp(I,"g"),x=C.data.matchAll(j),O=r(x);try{for(O.s();!(T=O.n()).done;)D=T.value,g.push({pattern:j.toString(),path:C.path,match:D[0]})}catch(e){O.e(e)}finally{O.f()}}}catch(e){_.e(e)}finally{_.f()}F=r(null!=(y=f.forbiddenTextsInCode)?y:[]),e.p=14,F.s();case 15:if((N=F.n()).done){e.n=19;break}P=N.value,S=0;case 16:if(!(S<C.data.length)){e.n=18;break}if(-1!==(A=C.data.indexOf(P,S))){e.n=17;break}return e.a(3,18);case 17:g.push({pattern:P,path:C.path,match:P}),S=A+P.length,e.n=16;break;case 18:e.n=15;break;case 19:e.n=21;break;case 20:e.p=20,Q=e.v,F.e(Q);case 21:return e.p=21,F.f(),e.f(21);case 22:v++,e.n=13;break;case 23:if(!(g.length>0)){e.n=24;break}return e.a(2,{decisionCode:c.FORBIDDEN_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n".concat(g.map(function(e){return"| `".concat(e.path,"` | `").concat(e.pattern,"` | `").concat(e.match,"` |")}).join("\n"),"\n")});case 24:B=[],H=r(null!=(p=f.requiredRegExpsInCode)?p:[]),e.p=25,q=n().m(function e(){var a,r;return n().w(function(e){for(;;)switch(e.n){case 0:a=M.value,r=new RegExp(a),d.some(function(e){return r.test(e.data)})||B.push(r.toString());case 1:return e.a(2)}},e)}),H.s();case 26:if((M=H.n()).done){e.n=28;break}return e.d(a(q()),27);case 27:e.n=26;break;case 28:e.n=30;break;case 29:e.p=29,U=e.v,H.e(U);case 30:return e.p=30,H.f(),e.f(30);case 31:if(!(B.length>0)){e.n=32;break}return e.a(2,{decisionCode:c.REQUIRED_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n".concat(B.map(function(e){return"- `".concat(e,"`")}).join("\n"),"\n")});case 32:return e.a(2)}},e,null,[[25,29,30,31],[14,20,21,22],[2,10,11,12]])}))).apply(this,arguments)}export{u as judgeByStaticAnalysis};
1
+ import{asyncToGenerator as e,regenerator as n,regeneratorValues as a,createForOfIteratorHelper as r}from"../_virtual/_rollupPluginBabelHelpers.js";import t from"node:fs";import o from"node:path";import{DecisionCode as s}from"../types/decisionCode.js";import{findLanguageDefinitionByPath as c}from"./findLanguageDefinitionByPath.js";import{removeCommentsInSourceCode as i}from"./removeCommentsInSourceCode.js";function u(e,n){return f.apply(this,arguments)}function f(){return(f=e(n().m(function e(u,f){var p,d,l,m,h,b,k,g,R,E,v,I,S,_,w,C,y,j,O,F,P,x,D,N,T,M,B,q,A,U,G,H,L,Q,V,z,J;return n().w(function(e){for(;;)switch(e.p=e.n){case 0:return d=new Set,l=[],Q=r,e.n=1,t.promises.readdir(u,{withFileTypes:!0,recursive:!0});case 1:m=Q(e.v),e.p=2,m.s();case 3:if((h=m.n()).done){e.n=9;break}if((b=h.value).isFile()){e.n=4;break}return e.a(3,8);case 4:return k=o.relative(u,o.join(b.parentPath,b.name)),d.add(k),e.n=5,t.promises.readFile(o.join(b.parentPath,b.name),"utf8");case 5:if(g=e.v,!g.includes("�")){e.n=6;break}return e.a(3,8);case 6:if(R=c(b.name)){e.n=7;break}return e.a(3,8);case 7:l.push({path:b.name,data:R.grammer?i(R.grammer,g):g});case 8:e.n=3;break;case 9:e.n=11;break;case 10:e.p=10,V=e.v,m.e(V);case 11:return e.p=11,m.f(),e.f(11);case 12:if(!f.requiredSubmissionFilePaths){e.n=13;break}if(E=f.requiredSubmissionFilePaths.filter(function(e){return!d.has(e)}).toSorted(),!(E.length>0)){e.n=13;break}return e.a(2,{decisionCode:s.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,feedbackMarkdown:"ファイルが不足しています。\n次のファイルを追加してから再度提出してください。\n\n".concat(E.map(function(e){return"- `".concat(e,"`")}).join("\n"),"\n")});case 13:v=[],I=0,S=l;case 14:if(!(I<S.length)){e.n=24;break}C=S[I],y=r(null!=(_=f.forbiddenRegExpsInCode)?_:[]);try{for(y.s();!(j=y.n()).done;){O=j.value,F=new RegExp(O,"g"),P=C.data.matchAll(F),x=r(P);try{for(x.s();!(D=x.n()).done;)N=D.value,v.push({pattern:F.toString(),path:C.path,match:N[0]})}catch(e){x.e(e)}finally{x.f()}}}catch(e){y.e(e)}finally{y.f()}T=r(null!=(w=f.forbiddenTextsInCode)?w:[]),e.p=15,T.s();case 16:if((M=T.n()).done){e.n=20;break}B=M.value,q=0;case 17:if(!(q<C.data.length)){e.n=19;break}if(-1!==(A=C.data.indexOf(B,q))){e.n=18;break}return e.a(3,19);case 18:v.push({pattern:B,path:C.path,match:B}),q=A+B.length,e.n=17;break;case 19:e.n=16;break;case 20:e.n=22;break;case 21:e.p=21,z=e.v,T.e(z);case 22:return e.p=22,T.f(),e.f(22);case 23:I++,e.n=14;break;case 24:if(!(v.length>0)){e.n=25;break}return e.a(2,{decisionCode:s.FORBIDDEN_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n".concat(v.map(function(e){return"| `".concat(e.path,"` | `").concat(e.pattern,"` | `").concat(e.match,"` |")}).join("\n"),"\n")});case 25:U=[],G=r(null!=(p=f.requiredRegExpsInCode)?p:[]),e.p=26,L=n().m(function e(){var a,r;return n().w(function(e){for(;;)switch(e.n){case 0:a=H.value,r=new RegExp(a),l.some(function(e){return r.test(e.data)})||U.push(r.toString());case 1:return e.a(2)}},e)}),G.s();case 27:if((H=G.n()).done){e.n=29;break}return e.d(a(L()),28);case 28:e.n=27;break;case 29:e.n=31;break;case 30:e.p=30,J=e.v,G.e(J);case 31:return e.p=31,G.f(),e.f(31);case 32:if(!(U.length>0)){e.n=33;break}return e.a(2,{decisionCode:s.REQUIRED_PATTERNS_IN_CODE_ERROR,feedbackMarkdown:"ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n".concat(U.map(function(e){return"- `".concat(e,"`")}).join("\n"),"\n")});case 33:return e.a(2)}},e,null,[[26,30,31,32],[15,21,22,23],[2,10,11,12]])}))).apply(this,arguments)}export{u as judgeByStaticAnalysis};
2
2
  //# sourceMappingURL=judgeByStaticAnalysis.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"judgeByStaticAnalysis.js","sources":["../../src/helpers/judgeByStaticAnalysis.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { findLanguageDefinitionByPath } from './findLanguageDefinitionByPath.js';\nimport { removeCommentsInSourceCode } from './removeCommentsInSourceCode.js';\n\nexport async function judgeByStaticAnalysis(\n cwd: string,\n problemMarkdownFrontMatterLike: Pick<\n ProblemMarkdownFrontMatter,\n 'forbiddenRegExpsInCode' | 'forbiddenTextsInCode' | 'requiredRegExpsInCode'\n >\n): Promise<Pick<TestCaseResult, 'decisionCode' | 'feedbackMarkdown'> | undefined> {\n const sourceCodeWithoutCommentFiles: { path: string; data: string }[] = [];\n\n for (const dirent of await fs.promises.readdir(cwd, { withFileTypes: true, recursive: true })) {\n if (!dirent.isFile()) continue;\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n const isBinary = text.includes('\\uFFFD');\n if (isBinary) continue;\n\n const languageDefinition = findLanguageDefinitionByPath(dirent.name);\n if (!languageDefinition) continue;\n\n sourceCodeWithoutCommentFiles.push({\n path: dirent.name,\n data: languageDefinition.grammer ? removeCommentsInSourceCode(languageDefinition.grammer, text) : text,\n });\n }\n\n const forbiddenFounds: { pattern: string; path: string; match: string }[] = [];\n\n for (const file of sourceCodeWithoutCommentFiles) {\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenRegExpsInCode ?? []) {\n const re = new RegExp(pattern, 'g');\n const mathces = file.data.matchAll(re);\n for (const match of mathces) forbiddenFounds.push({ pattern: re.toString(), path: file.path, match: match[0] });\n }\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenTextsInCode ?? []) {\n let p = 0;\n while (p < file.data.length) {\n const index = file.data.indexOf(pattern, p);\n if (index === -1) break;\n forbiddenFounds.push({ pattern, path: file.path, match: pattern });\n p = index + pattern.length;\n }\n }\n }\n\n if (forbiddenFounds.length > 0) {\n return {\n decisionCode: DecisionCode.FORBIDDEN_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n${forbiddenFounds.map((f) => `| \\`${f.path}\\` | \\`${f.pattern}\\` | \\`${f.match}\\` |`).join('\\n')}\n`,\n };\n }\n\n const missingRequiredPatterns: string[] = [];\n\n for (const pattern of problemMarkdownFrontMatterLike.requiredRegExpsInCode ?? []) {\n const re = new RegExp(pattern);\n const isFound = sourceCodeWithoutCommentFiles.some((f) => re.test(f.data));\n if (!isFound) missingRequiredPatterns.push(re.toString());\n }\n\n if (missingRequiredPatterns.length > 0) {\n return {\n decisionCode: DecisionCode.REQUIRED_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n${missingRequiredPatterns.map((p) => `- \\`${p}\\``).join('\\n')}\n`,\n };\n }\n\n return;\n}\n"],"names":["judgeByStaticAnalysis","_x","_x2","_judgeByStaticAnalysis","apply","this","arguments","_asyncToGenerator","_regenerator","m","_callee","cwd","problemMarkdownFrontMatterLike","_problemMarkdownFront3","sourceCodeWithoutCommentFiles","_iterator","_step","dirent","text","languageDefinition","forbiddenFounds","_i","_sourceCodeWithoutCom","_problemMarkdownFront","_problemMarkdownFront2","file","_iterator2","_step2","pattern","re","mathces","_iterator4","_step4","match","_iterator3","_step3","_pattern","p","index","missingRequiredPatterns","_iterator5","_step5","_loop","_t","_t2","_t3","_t4","w","_context2","n","_createForOfIteratorHelper","fs","promises","readdir","withFileTypes","recursive","v","s","done","value","isFile","a","readFile","path","join","parentPath","name","includes","findLanguageDefinitionByPath","push","data","grammer","removeCommentsInSourceCode","e","f","length","forbiddenRegExpsInCode","RegExp","matchAll","toString","err","forbiddenTextsInCode","indexOf","decisionCode","DecisionCode","FORBIDDEN_PATTERNS_IN_CODE_ERROR","feedbackMarkdown","concat","map","requiredRegExpsInCode","_context","some","test","d","_regeneratorValues","REQUIRED_PATTERNS_IN_CODE_ERROR"],"mappings":"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"}
1
+ {"version":3,"file":"judgeByStaticAnalysis.js","sources":["../../src/helpers/judgeByStaticAnalysis.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { findLanguageDefinitionByPath } from './findLanguageDefinitionByPath.js';\nimport { removeCommentsInSourceCode } from './removeCommentsInSourceCode.js';\n\nexport async function judgeByStaticAnalysis(\n cwd: string,\n problemMarkdownFrontMatterLike: Pick<\n ProblemMarkdownFrontMatter,\n 'forbiddenRegExpsInCode' | 'forbiddenTextsInCode' | 'requiredRegExpsInCode' | 'requiredSubmissionFilePaths'\n >\n): Promise<Pick<TestCaseResult, 'decisionCode' | 'feedbackMarkdown'> | undefined> {\n const filePathSet = new Set<string>();\n const sourceCodeWithoutCommentFiles: { path: string; data: string }[] = [];\n\n for (const dirent of await fs.promises.readdir(cwd, { withFileTypes: true, recursive: true })) {\n if (!dirent.isFile()) continue;\n\n const relativePath = path.relative(cwd, path.join(dirent.parentPath, dirent.name));\n filePathSet.add(relativePath);\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n const isBinary = text.includes('\\uFFFD');\n if (isBinary) continue;\n\n const languageDefinition = findLanguageDefinitionByPath(dirent.name);\n if (!languageDefinition) continue;\n\n sourceCodeWithoutCommentFiles.push({\n path: dirent.name,\n data: languageDefinition.grammer ? removeCommentsInSourceCode(languageDefinition.grammer, text) : text,\n });\n }\n\n if (problemMarkdownFrontMatterLike.requiredSubmissionFilePaths) {\n const missingFilePaths = problemMarkdownFrontMatterLike.requiredSubmissionFilePaths\n .filter((p) => !filePathSet.has(p))\n .toSorted();\n\n if (missingFilePaths.length > 0) {\n return {\n decisionCode: DecisionCode.MISSING_REQUIRED_SUBMISSION_FILE_ERROR,\n feedbackMarkdown: `ファイルが不足しています。\n次のファイルを追加してから再度提出してください。\n\n${missingFilePaths.map((p) => `- \\`${p}\\``).join('\\n')}\n`,\n };\n }\n }\n\n const forbiddenFounds: { pattern: string; path: string; match: string }[] = [];\n\n for (const file of sourceCodeWithoutCommentFiles) {\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenRegExpsInCode ?? []) {\n const re = new RegExp(pattern, 'g');\n const mathces = file.data.matchAll(re);\n for (const match of mathces) forbiddenFounds.push({ pattern: re.toString(), path: file.path, match: match[0] });\n }\n for (const pattern of problemMarkdownFrontMatterLike.forbiddenTextsInCode ?? []) {\n let p = 0;\n while (p < file.data.length) {\n const index = file.data.indexOf(pattern, p);\n if (index === -1) break;\n forbiddenFounds.push({ pattern, path: file.path, match: pattern });\n p = index + pattern.length;\n }\n }\n }\n\n if (forbiddenFounds.length > 0) {\n return {\n decisionCode: DecisionCode.FORBIDDEN_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に禁止された文字列が含まれています。\nソースコードを修正してから再度提出してください。\n\n| ファイル | 禁止パターン | 文字列 |\n| -------- | ------------ | ------ |\n${forbiddenFounds.map((f) => `| \\`${f.path}\\` | \\`${f.pattern}\\` | \\`${f.match}\\` |`).join('\\n')}\n`,\n };\n }\n\n const missingRequiredPatterns: string[] = [];\n\n for (const pattern of problemMarkdownFrontMatterLike.requiredRegExpsInCode ?? []) {\n const re = new RegExp(pattern);\n const isFound = sourceCodeWithoutCommentFiles.some((f) => re.test(f.data));\n if (!isFound) missingRequiredPatterns.push(re.toString());\n }\n\n if (missingRequiredPatterns.length > 0) {\n return {\n decisionCode: DecisionCode.REQUIRED_PATTERNS_IN_CODE_ERROR,\n feedbackMarkdown: `ソースコード中に必要な文字列が含まれていません。\nソースコードを修正してから再度提出してください。\n\n${missingRequiredPatterns.map((p) => `- \\`${p}\\``).join('\\n')}\n`,\n };\n }\n\n return;\n}\n"],"names":["judgeByStaticAnalysis","_x","_x2","_judgeByStaticAnalysis","apply","this","arguments","_asyncToGenerator","_regenerator","m","_callee","cwd","problemMarkdownFrontMatterLike","_problemMarkdownFront3","filePathSet","sourceCodeWithoutCommentFiles","_iterator","_step","dirent","relativePath","text","languageDefinition","missingFilePaths","forbiddenFounds","_i","_sourceCodeWithoutCom","_problemMarkdownFront","_problemMarkdownFront2","file","_iterator2","_step2","pattern","re","mathces","_iterator4","_step4","match","_iterator3","_step3","_pattern","p","index","missingRequiredPatterns","_iterator5","_step5","_loop","_t","_t2","_t3","_t4","w","_context2","n","Set","_createForOfIteratorHelper","fs","promises","readdir","withFileTypes","recursive","v","s","done","value","isFile","a","path","relative","join","parentPath","name","add","readFile","includes","findLanguageDefinitionByPath","push","data","grammer","removeCommentsInSourceCode","e","f","requiredSubmissionFilePaths","filter","has","toSorted","length","decisionCode","DecisionCode","MISSING_REQUIRED_SUBMISSION_FILE_ERROR","feedbackMarkdown","concat","map","forbiddenRegExpsInCode","RegExp","matchAll","toString","err","forbiddenTextsInCode","indexOf","FORBIDDEN_PATTERNS_IN_CODE_ERROR","requiredRegExpsInCode","_context","some","test","d","_regeneratorValues","REQUIRED_PATTERNS_IN_CODE_ERROR"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("../_virtual/_rollupPluginBabelHelpers.cjs"),r=require("node:fs"),s=require("node:path"),t=require("@ai-sdk/google"),n=require("ai"),a=require("zod"),i=require("../helpers/parseArgs.cjs"),o=require("../helpers/printTestCaseResult.cjs"),u=require("../helpers/readTestCases.cjs"),c=require("../types/decisionCode.cjs"),p=a.z.object({model:a.z.enum(["google/gemini-2.5-flash-lite"])});function l(){return(l=e.asyncToGenerator(e.regenerator().m(function a(l,d){var C,g,f,m,v,q,T,j,b,h,D,E,R,k,w,A,x,y;return e.regenerator().w(function(a){for(;;)switch(a.p=a.n){case 0:return C=i.parseArgs(process.argv),g=p.parse(C.params),a.n=1,u.readTestCases(s.join(l,"test_cases"));case 1:return f=a.v,a.n=2,r.promises.readFile(s.join(C.cwd,"prompt.txt"),"utf8");case 2:m=a.v,v=e.createForOfIteratorHelper(f),a.p=3,v.s();case 4:if((q=v.n()).done){a.n=11;break}return T=q.value,j=Date.now(),a.p=5,a.n=6,n.generateText({model:t.google(g.model.slice(7)),prompt:m.replaceAll("{input}",null!=(b=T.input)?b:"")});case 6:return h=a.v,D=h.text,E=Date.now(),w=e.objectSpread2,A={testCaseId:T.id,decisionCode:c.DecisionCode.ACCEPTED,stdin:T.input,stdout:D,timeSeconds:(E-j)/1e3},a.n=7,d.test({testCase:T,result:{output:D}});case 7:if(R=w(A,a.v),o.printTestCaseResult(R),R.decisionCode===c.DecisionCode.ACCEPTED){a.n=8;break}return a.a(3,11);case 8:a.n=10;break;case 9:return a.p=9,x=a.v,k=Date.now(),o.printTestCaseResult({testCaseId:T.id,decisionCode:c.DecisionCode.RUNTIME_ERROR,stdin:T.input,stderr:x instanceof Error?x.message:String(x),timeSeconds:(k-j)/1e3}),a.a(3,11);case 10:a.n=4;break;case 11:a.n=13;break;case 12:a.p=12,y=a.v,v.e(y);case 13:return a.p=13,v.f(),a.f(13);case 14:return a.a(2)}},a,null,[[5,9],[3,12,13,14]])}))).apply(this,arguments)}exports.llmJudgePreset=function(e,r){return l.apply(this,arguments)};
1
+ "use strict";var e=require("../_virtual/_rollupPluginBabelHelpers.cjs"),r=require("node:fs"),s=require("node:path"),t=require("@ai-sdk/google"),n=require("ai"),a=require("zod"),i=require("../helpers/parseArgs.cjs"),o=require("../helpers/printTestCaseResult.cjs"),u=require("../helpers/readTestCases.cjs"),c=require("../types/decisionCode.cjs"),l=a.z.object({model:a.z.enum(["google/gemini-2.5-flash-lite"])});function p(){return(p=e.asyncToGenerator(e.regenerator().m(function a(p,d){var C,g,m,f,v,q,T,b,j,h,D,E,R,k,w,A,P,x,y,I;return e.regenerator().w(function(a){for(;;)switch(a.p=a.n){case 0:return C=i.parseArgs(process.argv),g=l.parse(C.params),a.n=1,u.readTestCases(s.join(p,"test_cases"));case 1:return m=a.v,a.n=2,r.promises.readFile(s.join(C.cwd,"prompt.txt"),"utf8");case 2:f=a.v,v=e.createForOfIteratorHelper(m),a.p=3,v.s();case 4:if((q=v.n()).done){a.n=11;break}return T=q.value,b=Date.now(),a.p=5,a.n=6,n.generateText({model:t.google(g.model.slice(7)),prompt:null!=(j=null==(h=d.buildPrompt)?void 0:h.call(d,{prompt:f,testCase:T}))?j:f.replaceAll("{input}",null!=(D=T.input)?D:"")});case 6:return E=a.v,R=E.text,k=Date.now(),P=e.objectSpread2,x={testCaseId:T.id,decisionCode:c.DecisionCode.ACCEPTED,stdin:T.input,stdout:R,timeSeconds:(k-b)/1e3},a.n=7,d.test({testCase:T,result:{output:R}});case 7:if(w=P(x,a.v),o.printTestCaseResult(w),w.decisionCode===c.DecisionCode.ACCEPTED){a.n=8;break}return a.a(3,11);case 8:a.n=10;break;case 9:return a.p=9,y=a.v,A=Date.now(),o.printTestCaseResult({testCaseId:T.id,decisionCode:c.DecisionCode.RUNTIME_ERROR,stdin:T.input,stderr:y instanceof Error?y.message:String(y),timeSeconds:(A-b)/1e3}),a.a(3,11);case 10:a.n=4;break;case 11:a.n=13;break;case 12:a.p=12,I=a.v,v.e(I);case 13:return a.p=13,v.f(),a.f(13);case 14:return a.a(2)}},a,null,[[5,9],[3,12,13,14]])}))).apply(this,arguments)}exports.llmJudgePreset=function(e,r){return p.apply(this,arguments)};
2
2
  //# sourceMappingURL=llm.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"llm.cjs","sources":["../../src/presets/llm.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { google } from '@ai-sdk/google';\nimport { generateText } from 'ai';\nimport { z } from 'zod';\n\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nconst PROMPT_FILENAME = 'prompt.txt';\n\nconst judgeParamsSchema = z.object({\n model: z.enum(['google/gemini-2.5-flash-lite']),\n});\n\ninterface LlmJudgePresetOptions {\n test: (context: {\n testCase: { id: string; input?: string; output?: string };\n result: { output: string };\n }) => Partial<TestCaseResult> | Promise<Partial<TestCaseResult>>;\n}\n\n/**\n * A preset judge function for running and testing a user prompt in LLM.\n *\n * @example\n * Create `judge.ts`:\n * ```ts\n * import { llmJudgePreset } from '@exercode/problem-utils/presets/llm';\n * import { DecisionCode } from '@exercode/problem-utils';\n *\n * await llmJudgePreset(import.meta.dirname, {\n * test: (context) {\n * return { decisionCode: context.result.output ? DecisionCode.ACCEPTED : DecisionCode.WRONG_ANSWER };\n * }\n * });\n * ```\n *\n * Run with the required parameters:\n * ```bash\n * bun judge.ts model_answers/java '{ \"model\": \"gemini-2.5-flash-lite\" }'\n * ```\n */\nexport async function llmJudgePreset(problemDir: string, options: LlmJudgePresetOptions): Promise<void> {\n const args = parseArgs(process.argv);\n const params = judgeParamsSchema.parse(args.params);\n\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n const prompt = await fs.promises.readFile(path.join(args.cwd, PROMPT_FILENAME), 'utf8');\n\n for (const testCase of testCases) {\n const startTimeMilliseconds = Date.now();\n try {\n // requires `GOOGLE_GENERATIVE_AI_API_KEY`\n const { text } = await generateText({\n model: google(params.model.slice('google/'.length)),\n prompt: prompt.replaceAll('{input}', testCase.input ?? ''),\n });\n\n const stopTimeMilliseconds = Date.now();\n\n const testCaseResult = {\n testCaseId: testCase.id,\n decisionCode: DecisionCode.ACCEPTED,\n stdin: testCase.input,\n stdout: text,\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n ...(await options.test({ testCase, result: { output: text } })),\n };\n\n printTestCaseResult(testCaseResult);\n\n if (testCaseResult.decisionCode !== DecisionCode.ACCEPTED) break;\n } catch (error) {\n const stopTimeMilliseconds = Date.now();\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode: DecisionCode.RUNTIME_ERROR,\n stdin: testCase.input,\n stderr: error instanceof Error ? error.message : String(error),\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n });\n\n break;\n }\n }\n}\n"],"names":["judgeParamsSchema","z","object","model","_llmJudgePreset","_asyncToGenerator","_regenerator","m","_callee","problemDir","options","args","params","testCases","prompt","_iterator","_step","testCase","startTimeMilliseconds","_testCase$input","_yield$generateText","text","stopTimeMilliseconds","testCaseResult","_stopTimeMilliseconds","_t","_t2","_t3","_t4","w","_context","p","n","parseArgs","process","argv","parse","readTestCases","path","join","v","fs","promises","readFile","cwd","_createForOfIteratorHelper","s","done","value","Date","now","generateText","google","slice","replaceAll","input","_objectSpread","testCaseId","id","decisionCode","DecisionCode","ACCEPTED","stdin","stdout","timeSeconds","test","result","output","printTestCaseResult","a","RUNTIME_ERROR","stderr","Error","message","String","e","f","apply","this","arguments","_x","_x2"],"mappings":"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"}
1
+ {"version":3,"file":"llm.cjs","sources":["../../src/presets/llm.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { google } from '@ai-sdk/google';\nimport type { ModelMessage } from 'ai';\nimport { generateText } from 'ai';\nimport { z } from 'zod';\n\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nconst PROMPT_FILENAME = 'prompt.txt';\n\nconst judgeParamsSchema = z.object({\n model: z.enum(['google/gemini-2.5-flash-lite']),\n});\n\ninterface LlmJudgePresetOptions {\n buildPrompt?: (context: {\n prompt: string;\n testCase: { id: string; input?: string; output?: string };\n }) => string | ModelMessage[];\n test: (context: {\n testCase: { id: string; input?: string; output?: string };\n result: { output: string };\n }) => Partial<TestCaseResult> | Promise<Partial<TestCaseResult>>;\n}\n\n/**\n * A preset judge function for running and testing a user prompt in LLM.\n *\n * @example\n * Create `judge.ts`:\n * ```ts\n * import { llmJudgePreset } from '@exercode/problem-utils/presets/llm';\n * import { DecisionCode } from '@exercode/problem-utils';\n *\n * await llmJudgePreset(import.meta.dirname, {\n * test: (context) {\n * return { decisionCode: context.result.output ? DecisionCode.ACCEPTED : DecisionCode.WRONG_ANSWER };\n * }\n * });\n * ```\n *\n * Run with the required parameters:\n * ```bash\n * bun judge.ts model_answers/java '{ \"model\": \"gemini-2.5-flash-lite\" }'\n * ```\n */\nexport async function llmJudgePreset(problemDir: string, options: LlmJudgePresetOptions): Promise<void> {\n const args = parseArgs(process.argv);\n const params = judgeParamsSchema.parse(args.params);\n\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n const prompt = await fs.promises.readFile(path.join(args.cwd, PROMPT_FILENAME), 'utf8');\n\n for (const testCase of testCases) {\n const startTimeMilliseconds = Date.now();\n try {\n // requires `GOOGLE_GENERATIVE_AI_API_KEY`\n const { text } = await generateText({\n model: google(params.model.slice('google/'.length)),\n prompt: options.buildPrompt?.({ prompt, testCase }) ?? prompt.replaceAll('{input}', testCase.input ?? ''),\n });\n\n const stopTimeMilliseconds = Date.now();\n\n const testCaseResult = {\n testCaseId: testCase.id,\n decisionCode: DecisionCode.ACCEPTED,\n stdin: testCase.input,\n stdout: text,\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n ...(await options.test({ testCase, result: { output: text } })),\n };\n\n printTestCaseResult(testCaseResult);\n\n if (testCaseResult.decisionCode !== DecisionCode.ACCEPTED) break;\n } catch (error) {\n const stopTimeMilliseconds = Date.now();\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode: DecisionCode.RUNTIME_ERROR,\n stdin: testCase.input,\n stderr: error instanceof Error ? error.message : String(error),\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n });\n\n break;\n }\n }\n}\n"],"names":["judgeParamsSchema","z","object","model","_llmJudgePreset","_asyncToGenerator","_regenerator","m","_callee","problemDir","options","args","params","testCases","prompt","_iterator","_step","testCase","startTimeMilliseconds","_options$buildPrompt","_options$buildPrompt2","_testCase$input","_yield$generateText","text","stopTimeMilliseconds","testCaseResult","_stopTimeMilliseconds","_t","_t2","_t3","_t4","w","_context","p","n","parseArgs","process","argv","parse","readTestCases","path","join","v","fs","promises","readFile","cwd","_createForOfIteratorHelper","s","done","value","Date","now","generateText","google","slice","buildPrompt","call","replaceAll","input","_objectSpread","testCaseId","id","decisionCode","DecisionCode","ACCEPTED","stdin","stdout","timeSeconds","test","result","output","printTestCaseResult","a","RUNTIME_ERROR","stderr","Error","message","String","e","f","apply","this","arguments","_x","_x2"],"mappings":"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"}
@@ -1,5 +1,14 @@
1
+ import type { ModelMessage } from 'ai';
1
2
  import type { TestCaseResult } from '../types/testCaseResult.js';
2
3
  interface LlmJudgePresetOptions {
4
+ buildPrompt?: (context: {
5
+ prompt: string;
6
+ testCase: {
7
+ id: string;
8
+ input?: string;
9
+ output?: string;
10
+ };
11
+ }) => string | ModelMessage[];
3
12
  test: (context: {
4
13
  testCase: {
5
14
  id: string;
@@ -1,2 +1,2 @@
1
- import{asyncToGenerator as e,regenerator as r,objectSpread2 as t,createForOfIteratorHelper as s}from"../_virtual/_rollupPluginBabelHelpers.js";import o from"node:fs";import n from"node:path";import{google as a}from"@ai-sdk/google";import{generateText as i}from"ai";import{z as p}from"zod";import{parseArgs as c}from"../helpers/parseArgs.js";import{printTestCaseResult as m}from"../helpers/printTestCaseResult.js";import{readTestCases as u}from"../helpers/readTestCases.js";import{DecisionCode as l}from"../types/decisionCode.js";var d=p.object({model:p.enum(["google/gemini-2.5-flash-lite"])});function f(e,r){return C.apply(this,arguments)}function C(){return(C=e(r().m(function e(p,f){var C,g,v,j,b,h,E,k,w,T,D,R,y,A,I,S,_,x;return r().w(function(e){for(;;)switch(e.p=e.n){case 0:return C=c(process.argv),g=d.parse(C.params),e.n=1,u(n.join(p,"test_cases"));case 1:return v=e.v,e.n=2,o.promises.readFile(n.join(C.cwd,"prompt.txt"),"utf8");case 2:j=e.v,b=s(v),e.p=3,b.s();case 4:if((h=b.n()).done){e.n=11;break}return E=h.value,k=Date.now(),e.p=5,e.n=6,i({model:a(g.model.slice(7)),prompt:j.replaceAll("{input}",null!=(w=E.input)?w:"")});case 6:return T=e.v,D=T.text,R=Date.now(),I=t,S={testCaseId:E.id,decisionCode:l.ACCEPTED,stdin:E.input,stdout:D,timeSeconds:(R-k)/1e3},e.n=7,f.test({testCase:E,result:{output:D}});case 7:if(y=I(S,e.v),m(y),y.decisionCode===l.ACCEPTED){e.n=8;break}return e.a(3,11);case 8:e.n=10;break;case 9:return e.p=9,_=e.v,A=Date.now(),m({testCaseId:E.id,decisionCode:l.RUNTIME_ERROR,stdin:E.input,stderr:_ instanceof Error?_.message:String(_),timeSeconds:(A-k)/1e3}),e.a(3,11);case 10:e.n=4;break;case 11:e.n=13;break;case 12:e.p=12,x=e.v,b.e(x);case 13:return e.p=13,b.f(),e.f(13);case 14:return e.a(2)}},e,null,[[5,9],[3,12,13,14]])}))).apply(this,arguments)}export{f as llmJudgePreset};
1
+ import{asyncToGenerator as e,regenerator as r,objectSpread2 as t,createForOfIteratorHelper as s}from"../_virtual/_rollupPluginBabelHelpers.js";import o from"node:fs";import n from"node:path";import{google as a}from"@ai-sdk/google";import{generateText as i}from"ai";import{z as p}from"zod";import{parseArgs as l}from"../helpers/parseArgs.js";import{printTestCaseResult as c}from"../helpers/printTestCaseResult.js";import{readTestCases as m}from"../helpers/readTestCases.js";import{DecisionCode as u}from"../types/decisionCode.js";var d=p.object({model:p.enum(["google/gemini-2.5-flash-lite"])});function f(e,r){return C.apply(this,arguments)}function C(){return(C=e(r().m(function e(p,f){var C,v,g,b,j,h,E,k,w,T,D,R,y,A,I,P,S,_,x,F;return r().w(function(e){for(;;)switch(e.p=e.n){case 0:return C=l(process.argv),v=d.parse(C.params),e.n=1,m(n.join(p,"test_cases"));case 1:return g=e.v,e.n=2,o.promises.readFile(n.join(C.cwd,"prompt.txt"),"utf8");case 2:b=e.v,j=s(g),e.p=3,j.s();case 4:if((h=j.n()).done){e.n=11;break}return E=h.value,k=Date.now(),e.p=5,e.n=6,i({model:a(v.model.slice(7)),prompt:null!=(w=null==(T=f.buildPrompt)?void 0:T.call(f,{prompt:b,testCase:E}))?w:b.replaceAll("{input}",null!=(D=E.input)?D:"")});case 6:return R=e.v,y=R.text,A=Date.now(),S=t,_={testCaseId:E.id,decisionCode:u.ACCEPTED,stdin:E.input,stdout:y,timeSeconds:(A-k)/1e3},e.n=7,f.test({testCase:E,result:{output:y}});case 7:if(I=S(_,e.v),c(I),I.decisionCode===u.ACCEPTED){e.n=8;break}return e.a(3,11);case 8:e.n=10;break;case 9:return e.p=9,x=e.v,P=Date.now(),c({testCaseId:E.id,decisionCode:u.RUNTIME_ERROR,stdin:E.input,stderr:x instanceof Error?x.message:String(x),timeSeconds:(P-k)/1e3}),e.a(3,11);case 10:e.n=4;break;case 11:e.n=13;break;case 12:e.p=12,F=e.v,j.e(F);case 13:return e.p=13,j.f(),e.f(13);case 14:return e.a(2)}},e,null,[[5,9],[3,12,13,14]])}))).apply(this,arguments)}export{f as llmJudgePreset};
2
2
  //# sourceMappingURL=llm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"llm.js","sources":["../../src/presets/llm.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { google } from '@ai-sdk/google';\nimport { generateText } from 'ai';\nimport { z } from 'zod';\n\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nconst PROMPT_FILENAME = 'prompt.txt';\n\nconst judgeParamsSchema = z.object({\n model: z.enum(['google/gemini-2.5-flash-lite']),\n});\n\ninterface LlmJudgePresetOptions {\n test: (context: {\n testCase: { id: string; input?: string; output?: string };\n result: { output: string };\n }) => Partial<TestCaseResult> | Promise<Partial<TestCaseResult>>;\n}\n\n/**\n * A preset judge function for running and testing a user prompt in LLM.\n *\n * @example\n * Create `judge.ts`:\n * ```ts\n * import { llmJudgePreset } from '@exercode/problem-utils/presets/llm';\n * import { DecisionCode } from '@exercode/problem-utils';\n *\n * await llmJudgePreset(import.meta.dirname, {\n * test: (context) {\n * return { decisionCode: context.result.output ? DecisionCode.ACCEPTED : DecisionCode.WRONG_ANSWER };\n * }\n * });\n * ```\n *\n * Run with the required parameters:\n * ```bash\n * bun judge.ts model_answers/java '{ \"model\": \"gemini-2.5-flash-lite\" }'\n * ```\n */\nexport async function llmJudgePreset(problemDir: string, options: LlmJudgePresetOptions): Promise<void> {\n const args = parseArgs(process.argv);\n const params = judgeParamsSchema.parse(args.params);\n\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n const prompt = await fs.promises.readFile(path.join(args.cwd, PROMPT_FILENAME), 'utf8');\n\n for (const testCase of testCases) {\n const startTimeMilliseconds = Date.now();\n try {\n // requires `GOOGLE_GENERATIVE_AI_API_KEY`\n const { text } = await generateText({\n model: google(params.model.slice('google/'.length)),\n prompt: prompt.replaceAll('{input}', testCase.input ?? ''),\n });\n\n const stopTimeMilliseconds = Date.now();\n\n const testCaseResult = {\n testCaseId: testCase.id,\n decisionCode: DecisionCode.ACCEPTED,\n stdin: testCase.input,\n stdout: text,\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n ...(await options.test({ testCase, result: { output: text } })),\n };\n\n printTestCaseResult(testCaseResult);\n\n if (testCaseResult.decisionCode !== DecisionCode.ACCEPTED) break;\n } catch (error) {\n const stopTimeMilliseconds = Date.now();\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode: DecisionCode.RUNTIME_ERROR,\n stdin: testCase.input,\n stderr: error instanceof Error ? error.message : String(error),\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n });\n\n break;\n }\n }\n}\n"],"names":["judgeParamsSchema","z","object","model","llmJudgePreset","_x","_x2","_llmJudgePreset","apply","this","arguments","_asyncToGenerator","_regenerator","m","_callee","problemDir","options","args","params","testCases","prompt","_iterator","_step","testCase","startTimeMilliseconds","_testCase$input","_yield$generateText","text","stopTimeMilliseconds","testCaseResult","_stopTimeMilliseconds","_t","_t2","_t3","_t4","w","_context","p","n","parseArgs","process","argv","parse","readTestCases","path","join","v","fs","promises","readFile","cwd","_createForOfIteratorHelper","s","done","value","Date","now","generateText","google","slice","replaceAll","input","_objectSpread","testCaseId","id","decisionCode","DecisionCode","ACCEPTED","stdin","stdout","timeSeconds","test","result","output","printTestCaseResult","a","RUNTIME_ERROR","stderr","Error","message","String","e","f"],"mappings":"ihBAaA,IAEMA,EAAoBC,EAAEC,OAAO,CACjCC,MAAOF,EAAC,KAAM,CAAC,mCA+BjB,SAAsBG,EAAcC,EAAAC,GAAA,OAAAC,EAAAC,MAAAC,KAAAC,UAAA,CA6CnC,SAAAH,IAAA,OAAAA,EAAAI,EAAAC,IAAAC,EA7CM,SAAAC,EAA8BC,EAAoBC,GAA8B,IAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAA,OAAAtB,IAAAuB,EAAA,SAAAC,GAAA,cAAAA,EAAAC,EAAAD,EAAAE,GAAA,KAAA,EAElC,OAD7CrB,EAAOsB,EAAUC,QAAQC,MACzBvB,EAASlB,EAAkB0C,MAAMzB,EAAKC,QAAOkB,EAAAE,EAAA,EAE3BK,EAAcC,EAAKC,KAAK9B,EAAY,eAAc,KAAA,EAA3D,OAATI,EAASiB,EAAAU,EAAAV,EAAAE,EAAA,EAEMS,EAAGC,SAASC,SAASL,EAAKC,KAAK5B,EAAKiC,IAxCnC,cAwC0D,QAAO,KAAA,EAAjF9B,EAAMgB,EAAAU,EAAAzB,EAAA8B,EAEWhC,GAASiB,EAAAC,EAAA,EAAAhB,EAAA+B,IAAA,KAAA,EAAA,IAAA9B,EAAAD,EAAAiB,KAAAe,KAAA,CAAAjB,EAAAE,EAAA,GAAA,KAAA,CACU,OAD/Bf,EAAQD,EAAAgC,MACX9B,EAAwB+B,KAAKC,MAAKpB,EAAAC,EAAA,EAAAD,EAAAE,EAAA,EAGfmB,EAAa,CAClCtD,MAAOuD,EAAOxC,EAAOf,MAAMwD,MAAM,IACjCvC,OAAQA,EAAOwC,WAAW,UAAyB,OAAhBnC,EAAEF,EAASsC,OAAKpC,EAAI,MACvD,KAAA,EASkE,OATlEC,EAAAU,EAAAU,EAHMnB,EAAID,EAAJC,KAKFC,EAAuB2B,KAAKC,MAAKzB,EAAA+B,EAAA9B,EAAA,CAGrC+B,WAAYxC,EAASyC,GACrBC,aAAcC,EAAaC,SAC3BC,MAAO7C,EAASsC,MAChBQ,OAAQ1C,EACR2C,aAAc1C,EAAuBJ,GAAyB,KAAIY,EAAAE,EAAA,EACxDtB,EAAQuD,KAAK,CAAEhD,SAAAA,EAAUiD,OAAQ,CAAEC,OAAQ9C,KAAS,KAAA,EAG5B,GAT9BE,EAAcE,EAAAC,EAAAI,EAAAU,GASpB4B,EAAoB7C,GAEhBA,EAAeoC,eAAiBC,EAAaC,SAAQ,CAAA/B,EAAAE,EAAA,EAAA,KAAA,CAAA,OAAAF,EAAAuC,EAAA,EAAA,IAAA,KAAA,EAAAvC,EAAAE,EAAA,GAAA,MAAA,KAAA,EAUtD,OAVsDF,EAAAC,EAAA,EAAAJ,EAAAG,EAAAU,EAEnDlB,EAAuB2B,KAAKC,MAElCkB,EAAoB,CAClBX,WAAYxC,EAASyC,GACrBC,aAAcC,EAAaU,cAC3BR,MAAO7C,EAASsC,MAChBgB,OAAQ5C,aAAiB6C,MAAQ7C,EAAM8C,QAAUC,OAAM/C,GACvDqC,aAAc1C,EAAuBJ,GAAyB,MAC7DY,EAAAuC,EAAA,EAAA,IAAA,KAAA,GAAAvC,EAAAE,EAAA,EAAA,MAAA,KAAA,GAAAF,EAAAE,EAAA,GAAA,MAAA,KAAA,GAAAF,EAAAC,EAAA,GAAAH,EAAAE,EAAAU,EAAAzB,EAAA4D,EAAA/C,GAAA,KAAA,GAAA,OAAAE,EAAAC,EAAA,GAAAhB,EAAA6D,IAAA9C,EAAA8C,EAAA,IAAA,KAAA,GAAA,OAAA9C,EAAAuC,EAAA,GAAA,EAAA7D,EAAA,KAAA,CAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,GAAA,KAAA,KAKRN,MAAAC,KAAAC,UAAA"}
1
+ {"version":3,"file":"llm.js","sources":["../../src/presets/llm.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { google } from '@ai-sdk/google';\nimport type { ModelMessage } from 'ai';\nimport { generateText } from 'ai';\nimport { z } from 'zod';\n\nimport { parseArgs } from '../helpers/parseArgs.js';\nimport { printTestCaseResult } from '../helpers/printTestCaseResult.js';\nimport { readTestCases } from '../helpers/readTestCases.js';\nimport { DecisionCode } from '../types/decisionCode.js';\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nconst PROMPT_FILENAME = 'prompt.txt';\n\nconst judgeParamsSchema = z.object({\n model: z.enum(['google/gemini-2.5-flash-lite']),\n});\n\ninterface LlmJudgePresetOptions {\n buildPrompt?: (context: {\n prompt: string;\n testCase: { id: string; input?: string; output?: string };\n }) => string | ModelMessage[];\n test: (context: {\n testCase: { id: string; input?: string; output?: string };\n result: { output: string };\n }) => Partial<TestCaseResult> | Promise<Partial<TestCaseResult>>;\n}\n\n/**\n * A preset judge function for running and testing a user prompt in LLM.\n *\n * @example\n * Create `judge.ts`:\n * ```ts\n * import { llmJudgePreset } from '@exercode/problem-utils/presets/llm';\n * import { DecisionCode } from '@exercode/problem-utils';\n *\n * await llmJudgePreset(import.meta.dirname, {\n * test: (context) {\n * return { decisionCode: context.result.output ? DecisionCode.ACCEPTED : DecisionCode.WRONG_ANSWER };\n * }\n * });\n * ```\n *\n * Run with the required parameters:\n * ```bash\n * bun judge.ts model_answers/java '{ \"model\": \"gemini-2.5-flash-lite\" }'\n * ```\n */\nexport async function llmJudgePreset(problemDir: string, options: LlmJudgePresetOptions): Promise<void> {\n const args = parseArgs(process.argv);\n const params = judgeParamsSchema.parse(args.params);\n\n const testCases = await readTestCases(path.join(problemDir, 'test_cases'));\n\n const prompt = await fs.promises.readFile(path.join(args.cwd, PROMPT_FILENAME), 'utf8');\n\n for (const testCase of testCases) {\n const startTimeMilliseconds = Date.now();\n try {\n // requires `GOOGLE_GENERATIVE_AI_API_KEY`\n const { text } = await generateText({\n model: google(params.model.slice('google/'.length)),\n prompt: options.buildPrompt?.({ prompt, testCase }) ?? prompt.replaceAll('{input}', testCase.input ?? ''),\n });\n\n const stopTimeMilliseconds = Date.now();\n\n const testCaseResult = {\n testCaseId: testCase.id,\n decisionCode: DecisionCode.ACCEPTED,\n stdin: testCase.input,\n stdout: text,\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n ...(await options.test({ testCase, result: { output: text } })),\n };\n\n printTestCaseResult(testCaseResult);\n\n if (testCaseResult.decisionCode !== DecisionCode.ACCEPTED) break;\n } catch (error) {\n const stopTimeMilliseconds = Date.now();\n\n printTestCaseResult({\n testCaseId: testCase.id,\n decisionCode: DecisionCode.RUNTIME_ERROR,\n stdin: testCase.input,\n stderr: error instanceof Error ? error.message : String(error),\n timeSeconds: (stopTimeMilliseconds - startTimeMilliseconds) / 1000,\n });\n\n break;\n }\n }\n}\n"],"names":["judgeParamsSchema","z","object","model","llmJudgePreset","_x","_x2","_llmJudgePreset","apply","this","arguments","_asyncToGenerator","_regenerator","m","_callee","problemDir","options","args","params","testCases","prompt","_iterator","_step","testCase","startTimeMilliseconds","_options$buildPrompt","_options$buildPrompt2","_testCase$input","_yield$generateText","text","stopTimeMilliseconds","testCaseResult","_stopTimeMilliseconds","_t","_t2","_t3","_t4","w","_context","p","n","parseArgs","process","argv","parse","readTestCases","path","join","v","fs","promises","readFile","cwd","_createForOfIteratorHelper","s","done","value","Date","now","generateText","google","slice","buildPrompt","call","replaceAll","input","_objectSpread","testCaseId","id","decisionCode","DecisionCode","ACCEPTED","stdin","stdout","timeSeconds","test","result","output","printTestCaseResult","a","RUNTIME_ERROR","stderr","Error","message","String","e","f"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exercode/problem-utils",
3
- "version": "1.5.4",
3
+ "version": "1.6.0",
4
4
  "description": ":100: A set of utilities for judging programs on Exercode (https://exercode.willbooster.com/).",
5
5
  "keywords": [
6
6
  "exercode",