cpns / packages /ai /src /language-rules.ts
pramudya-yb
Rename project from Labas to Pram
2b62b0c
Raw
History Blame Contribute Delete
2.48 kB
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 [];
}