diff --git a/simulasi-mk.html b/simulasi-mk.html index 72c3a58..2f4226c 100644 --- a/simulasi-mk.html +++ b/simulasi-mk.html @@ -25,6 +25,9 @@ .course-card.violation .cat-bar { background-color: #ef4444 !important; } .violation-badge { position: absolute; right: 0.5rem; bottom: 0.5rem; font-size: 0.65rem; color: #dc2626; font-weight: bold; display: flex; align-items: center; gap: 2px; } + /* Elective Styles (New) */ + .course-card.is-elective { background-color: #fffbeb; border-color: #fcd34d; } /* Yellow tint */ + /* Grade Badges */ .grade-badge { position: absolute; right: 0.5rem; top: 0.5rem; font-size: 0.7rem; font-weight: bold; padding: 0.1rem 0.4rem; border-radius: 0.25rem; } .grade-A { background: #dcfce7; color: #166534; border: 1px solid #bbf7d0; } @@ -131,7 +134,7 @@

Simulasi Studi Berbasis IPS

Simulasi nyata: IPS Semester lalu menentukan jatah SKS semester depan.
- Sistem Prasyarat Aktif: Anda tidak bisa mengambil mata kuliah lanjut jika prasyarat belum lulus. + Jalur UMUM (Campuran) sekarang menampilkan mata kuliah spesifik di semester akhir. Buka Katalog untuk mengganti sesuai minat Anda.

@@ -166,8 +169,8 @@
- - + + @@ -222,12 +225,6 @@ }; // --- Prerequisite Rules --- - // M7: Logika Komputasional - // M14: Dasar Pemrograman - // M19: Struktur Data - // M20: Jaringan Komputer - // M28: Pemrograman Jaringan - // M31: Manajemen Jaringan const prerequisites = { "M14": { reqId: "M7", reqName: "Logika Komputasional" }, "M19": { reqId: "M14", reqName: "Dasar Pemrograman" }, @@ -303,12 +300,13 @@ }; const electives = { + // General track now has specific courses as a "Sample Mix" general: [ - { id: "EL1", name: "MK Pilihan I", sks: 3, cat: "EL" }, - { id: "EL2", name: "MK Pilihan II", sks: 3, cat: "EL" }, - { id: "EL3", name: "MK Pilihan III", sks: 3, cat: "EL" }, - { id: "EL4", name: "MK Pilihan IV", sks: 3, cat: "EL" }, - { id: "EL5", name: "MK Pilihan V", sks: 3, cat: "EL" } + { id: "GEN1", name: "Cross-Platform Dev", sks: 3, cat: "EL" }, // RPL flavor + { id: "GEN2", name: "Data Mining", sks: 3, cat: "EL" }, // AI flavor + { id: "GEN3", name: "Cloud Computing", sks: 3, cat: "EL" }, // Net flavor + { id: "GEN4", name: "E-Business", sks: 3, cat: "EL" }, // SI flavor + { id: "GEN5", name: "Blockchain Tech", sks: 3, cat: "EL" } // Advanced ], ai: [ { id: "AI1", name: "Deep Learning", sks: 3, cat: "EL" }, @@ -359,11 +357,18 @@ } } - // Add Electives + // Add Electives with Flag const tr = electives[trackId] || electives['general']; const distribute = [[5,0], [6,1], [7,2], [7,3], [8,4]]; distribute.forEach(([sem, idx]) => { - if(tr[idx]) currentPlan[sem].push({...tr[idx], grade: 4, uuid: generateUUID()}); + if(tr[idx]) { + currentPlan[sem].push({ + ...tr[idx], + grade: 4, + uuid: generateUUID(), + isElective: true // Tag as elective + }); + } }); renderCatalog(); @@ -424,7 +429,6 @@ grid.innerHTML = ''; // First Pass: Check Violations (Prerequisites) - // Need to run this before rendering to mark cards for(let i=1; i<=8; i++) { currentPlan[i].forEach(course => { const check = checkPrerequisite(course.id, i); @@ -507,11 +511,12 @@ const isFailed = c.grade === 0; const isRetake = c.isRetake === true; const isViolation = c.violation === true; + const isElective = c.isElective === true; - // Add 'violation' class if prereq failed card.className = `course-card bg-white p-2 pl-4 rounded shadow-sm border border-slate-200 relative ${isFailed ? 'border-red-300 bg-red-50' : ''} - ${isViolation ? 'violation' : ''}`; + ${isViolation ? 'violation' : ''} + ${isElective ? 'is-elective' : ''}`; card.draggable = true; card.setAttribute('ondragstart', `dragSemester(event, ${semId}, ${index})`); @@ -530,6 +535,7 @@
${c.name} ${isRetake ? '' : ''} + ${isElective ? '' : ''}
${c.sks} SKS @@ -570,11 +576,10 @@ courseToAdd = currentPlan[dragSource.semId][dragSource.index]; } - // --- Prerequisite Check Before Dropping --- const check = checkPrerequisite(courseToAdd.id, targetSem); if (!check.allowed) { showToast("❌ " + check.msg); - return; // Block Action + return; } if(dragSource.type === 'catalog') { @@ -625,7 +630,7 @@ showToast("Mata kuliah Gagal (E). Klik kanan > 'Ulang di Tahun Depan' untuk memperbaiki."); } - renderAll(); // Will trigger re-validation of downstream courses + renderAll(); } hideContextMenu(); } @@ -644,7 +649,6 @@ if (exists) { showToast("Mata kuliah ini sudah ada di Semester " + targetSem + "."); } else { - // Check Prereq again for the target sem (just in case) const check = checkPrerequisite(course.id, targetSem); if (!check.allowed) { showToast("❌ Tidak bisa mengulang: " + check.msg); @@ -695,8 +699,18 @@ list.innerHTML = ''; let allCourses = []; + // Base Courses for(let i=1; i<=8; i++) if(baseCurriculum[i]) allCourses.push(...baseCurriculum[i]); - allCourses.push(...(electives[currentTrackId] || [])); + + // Logic Baru: Jika Track == 'general', TAMPILKAN SEMUA PILIHAN + if(currentTrackId === 'general') { + allCourses.push(...electives['ai']); + allCourses.push(...electives['rpl']); + allCourses.push(...electives['net']); + allCourses.push(...electives['si']); + } else { + allCourses.push(...(electives[currentTrackId] || [])); + } const unique = []; const seen = new Set(); @@ -738,6 +752,14 @@ btn.classList.remove('bg-white', 'text-slate-800'); btn.classList.add('bg-slate-800', 'text-white'); + // Notification + let trackName = "Umum"; + if(trackId === 'ai') trackName = "AI & Data"; + if(trackId === 'rpl') trackName = "RPL"; + if(trackId === 'net') trackName = "Jaringan"; + if(trackId === 'si') trackName = "SI & GIS"; + showToast(`Jalur diubah ke ${trackName}.`); + initPlan(trackId); }