File size: 2,484 Bytes
72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 2b62b0c 72e7de2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | interface QuestionLanguageFields {
questionText: string;
options?: Array<{ key: string; text: string }>;
}
/** Target language for exam content (passage, question, options). */
export function getTargetLanguage(_examType: string): string {
return "Bahasa Indonesia";
}
const INDONESIAN_PROSE_MARKERS =
/\b(yang|dari|pada|Apakah|Menurut|paragraf|bacaan|teks|judul|penulis|artikel|soal|pilihan|jawaban|berikut|manakah|bagian|kalimat|isinya|topik|gagasan|benar|karena|merujuk|sesuai|artinya|makna|kata|terdapat|disebutkan|dijelaskan|adalah|jadi|oleh|opsi|pilihan|jawabannya|penjelasan|Pancasila|UUD|NKRI|Bhinneka|Nasionalisme|Integritas|Negara|TIU|TWK|TKP)\b/i;
/** Strip foreign characters (heuristics) if needed, but for CPNS we mostly deal with Latin script. */
export function stripExamScriptForAnalysis(text: string): string {
return text.trim();
}
/** Latin prose looks like Bahasa Indonesia. */
export function hasIndonesianProse(text: string): boolean {
const t = text.trim();
if (!t) return false;
if (INDONESIAN_PROSE_MARKERS.test(t)) return true;
return t.length >= 15;
}
export function buildContentLanguageRules(_examType: string): string {
return `- LANGUAGE RULE (critical):
* passageText, questionText, and every option "text" MUST be written in Bahasa Indonesia — the authentic exam language for CPNS.
* explanation: tulis dalam Bahasa Indonesia yang mendalam dan mudah dimengerti.`;
}
export function buildExplanationLanguageRule(_examType?: string): string {
return `- explanation — WAJIB ditulis dalam Bahasa Indonesia sebagai penjelasan utama.`;
}
export function getQuestionLanguageErrors(
q: QuestionLanguageFields,
_examType: string,
): string[] {
const errors: string[] = [];
if (!hasIndonesianProse(q.questionText)) {
errors.push("questionText must be in Bahasa Indonesia");
}
for (const opt of q.options ?? []) {
if (!hasIndonesianProse(opt.text) && opt.text.length > 5) {
errors.push(`option ${opt.key} must be in Bahasa Indonesia`);
}
}
return errors;
}
export function getExplanationLanguageErrors(explanation: string): string[] {
const t = explanation.trim();
if (!t) return [];
const latinPart = stripExamScriptForAnalysis(t);
if (latinPart.length === 0) {
return ["explanation must include Bahasa Indonesia prose, not only foreign script"];
}
if (!hasIndonesianProse(latinPart)) {
return ["explanation prose must be in Bahasa Indonesia"];
}
return [];
}
|