92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
import { checkKeyText, missingKeyTextKeys, validateNodes } from '$services/exercise';
|
|
import type { LessonContent } from '$types/lesson';
|
|
import type { CircuitJSApi } from '$types/circuitjs';
|
|
|
|
export interface CircuitEvalResult {
|
|
pass: boolean;
|
|
output: string;
|
|
error?: string;
|
|
}
|
|
|
|
export function evaluateCircuitSubmission(
|
|
simApi: CircuitJSApi,
|
|
circuitText: string,
|
|
isHybrid: boolean,
|
|
data: LessonContent,
|
|
checkAllPassed: () => boolean
|
|
): CircuitEvalResult {
|
|
const circuitExpected = (isHybrid && data.expected_circuit_output)
|
|
? data.expected_circuit_output
|
|
: data.expected_output;
|
|
|
|
let expectedState: any = null;
|
|
try {
|
|
if (circuitExpected) expectedState = JSON.parse(circuitExpected);
|
|
} catch {
|
|
return { pass: false, output: '', error: "Format EXPECTED_OUTPUT tidak valid (Harus JSON)." };
|
|
}
|
|
|
|
if (!expectedState) {
|
|
return { pass: true, output: "Tidak ada kriteria evaluasi yang ditetapkan." };
|
|
}
|
|
|
|
let { allPassed, messages } = expectedState.nodes
|
|
? validateNodes(simApi, expectedState.nodes)
|
|
: { allPassed: true, messages: [] as string[] };
|
|
|
|
const circuitKeyText = (isHybrid && data.key_text_circuit) ? data.key_text_circuit : data.key_text;
|
|
if (!checkKeyText(circuitText, circuitKeyText ?? '')) {
|
|
allPassed = false;
|
|
messages.push(`❌ Komponen wajib belum lengkap (lihat instruksi).`);
|
|
}
|
|
|
|
let finalOutput = messages.join('\n');
|
|
|
|
if (allPassed && isHybrid) {
|
|
finalOutput += '\n✅ Rangkaian benar!';
|
|
if (!checkAllPassed()) {
|
|
finalOutput += '\n⏳ Selesaikan juga tantangan kode untuk menyelesaikan pelajaran ini.';
|
|
}
|
|
}
|
|
|
|
return { pass: allPassed, output: finalOutput };
|
|
}
|
|
|
|
export interface LanguageEvalResult {
|
|
isCorrect: boolean;
|
|
reason?: 'output-mismatch' | 'keytext-missing';
|
|
missingKeys?: string[];
|
|
}
|
|
|
|
export function processLanguageEvaluation(
|
|
compileOutput: string,
|
|
code: string,
|
|
lang: 'c' | 'python',
|
|
currentLanguage: string,
|
|
cCode: string,
|
|
pythonCode: string,
|
|
data: LessonContent
|
|
): LanguageEvalResult {
|
|
if (!data.expected_output && !data.expected_output_python) return { isCorrect: true };
|
|
|
|
const currentCCode = (currentLanguage === 'c') ? code : cCode;
|
|
const currentPythonCode = (currentLanguage === 'python') ? code : pythonCode;
|
|
const mergedCode = currentCCode + '\n' + currentPythonCode;
|
|
|
|
const expected = (lang === 'python' && data.expected_output_python)
|
|
? data.expected_output_python
|
|
: data.expected_output;
|
|
|
|
const outputMatches = compileOutput.trim() === (expected ?? '').trim();
|
|
if (!outputMatches) {
|
|
return { isCorrect: false, reason: 'output-mismatch' };
|
|
}
|
|
|
|
const missingKeys = missingKeyTextKeys(mergedCode, data.key_text ?? '');
|
|
if (missingKeys.length > 0) {
|
|
return { isCorrect: false, reason: 'keytext-missing', missingKeys };
|
|
}
|
|
|
|
return { isCorrect: true };
|
|
}
|