USER
why is the moving particulas not being shown : <?php
session_start();
if (!isset($_SESSION['user_id'])) {
header("Location: register.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>سیستم هدایت تحصیلی هوشمند</title>
<!-- Fonts & Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/font-store/badkhate2@latest/font.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
<!-- Tailwind CSS CDN for utility styles (optional, can remove if you prefer) -->
<script src="https://cdn.tailwindcss.com"></script>
<style>
@font-face {
font-family: 'IranSans';
src: url('IranSans.woff2') format('woff2'),
url('IranSans.woff') format('woff'),
url('IranSans.ttf') format('truetype');
font-weight: normal;
font-style: normal;
font-display: swap;
}
/* Global font */
body, input, button, select, textarea {
font-family: 'IranSans', cursive !important;
}
body {
margin: 0;
color: #2c3e50;
min-height: 100vh;
direction: rtl;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Header */
.dashboard-header {
background: linear-gradient(135deg,rgb(162, 162, 177), #4338ca);
color: white;
box-shadow: 0 4px 10px rgb(67 56 202 / 0.4);
position: sticky;
top: 0;
z-index: 1050;
padding: 0.875rem 2.5rem;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: bold;
font-size: 1.125rem;
letter-spacing: 0.05em;
}
.dashboard-header .username {
color: #dcd6f7;
font-weight: 700;
transition: color 0.3s ease;
}
.dashboard-header .username:hover {
color: #c7d2fe;
}
/* Logout Button */
.logout-btn {
background: #6366f1;
border: none;
padding: 0.5rem 1.25rem;
border-radius: 9999px;
color: white;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.1s ease;
box-shadow: 0 8px 15px rgba(99, 102, 241, 0.3);
font-size: 0.9rem;
user-select: none;
}
.logout-btn:hover {
background-color: #4f46e5;
box-shadow: 0 12px 20px rgba(79, 70, 229, 0.5);
transform: translateY(-2px);
}
.logout-btn:active {
transform: translateY(0);
box-shadow: none;
}
.logout-btn svg {
width: 18px;
height: 18px;
fill: white;
}
/* Main content */
.dashboard-content {
max-width: 900px;
margin: 40px auto 60px;
padding: 0 20px;
}
/* Card Style */
.card {
background: white;
border-radius: 1rem;
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
padding: 2.8rem 2rem;
margin-bottom: 3rem;
text-align: center;
position: relative;
animation: fadeInUp 0.9s ease both;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(40px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* School Branding */
.school-branding h1 {
font-size: 2.5rem;
color: #4f46e5;
font-weight: 900;
letter-spacing: 0.06em;
margin-bottom: 0.6rem;
text-shadow: 2px 2px 6px rgb(79 70 229 / 0.25);
}
.school-info h2 {
font-size: 1.5rem;
font-weight: 600;
color: #374151;
}
.divider-indigo {
width: 70px;
height: 4px;
margin: 1rem auto 0;
background: linear-gradient(90deg, #6366f1, #4338ca);
border-radius: 99px;
filter: drop-shadow(0 0 3px rgba(67, 56, 202, 0.4));
}
/* Upload Box */
#excelFile {
display: none;
}
.file-upload-label {
cursor: pointer;
display: inline-block;
padding: 1.6rem 1rem;
border: 2px dashed #6366f1;
border-radius: 1rem;
width: 100%;
max-width: 400px;
margin: 0 auto 1.8rem;
transition: background-color 0.3s ease, border-color 0.3s ease;
color: #4f46e5;
user-select: none;
}
.file-upload-label:hover {
background-color: #f3f4f6;
border-color: #4338ca;
}
.file-upload-label svg {
width: 72px;
height: 72px;
stroke: #4338ca;
margin-bottom: 0.6rem;
transition: stroke 0.3s ease;
}
.file-upload-label:hover svg {
stroke: #6366f1;
}
.file-upload-label span {
font-size: 1.2rem;
font-weight: 600;
letter-spacing: 0.02em;
color: #4b5563;
}
/* Buttons */
.action-buttons {
display: flex;
justify-content: center;
gap: 1.6rem;
flex-wrap: wrap;
}
button.primary-button {
background: linear-gradient(to left, #4f46e5, #4338ca);
box-shadow: 0 4px 15px rgb(67 56 202 / 0.4);
color: white;
font-weight: 700;
border-radius: 0.75rem;
padding: 0.85rem 2rem;
border: none;
cursor: pointer;
font-size: 1.1rem;
display: flex;
align-items: center;
gap: 0.6rem;
transition: transform 0.25s ease, box-shadow 0.25s ease;
user-select: none;
}
button.primary-button:hover {
transform: scale(1.06);
box-shadow: 0 8px 25px rgb(79 70 229 / 0.6);
}
button.primary-button svg {
height: 22px;
width: 22px;
stroke: white;
stroke-width: 2.5;
}
button.secondary-button {
background: white;
border: 2px solid #4f46e5;
padding: 0.85rem 2rem;
border-radius: 0.75rem;
font-weight: 700;
color: #4f46e5;
font-size: 1.1rem;
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
box-shadow: 0 4px 10px rgb(79 70 229 / 0.25);
transition: background-color 0.3s ease, color 0.3s ease;
user-select: none;
display: none; /* initially hidden */
}
button.secondary-button svg {
height: 20px;
width: 20px;
stroke: #4f46e5;
stroke-width: 2.2;
}
button.secondary-button:hover {
background-color: #4f46e5;
color: white;
box-shadow: 0 8px 20px rgb(67 56 202 / 0.5);
}
/* Loading Indicator */
#loadingIndicator {
position: fixed;
inset: 0;
background-color: rgba(255, 255, 255, 0.95);
z-index: 1500;
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
}
.loading-spinner {
border: 5px solid #c7d2fe;
border-top: 5px solid #4338ca;
border-radius: 50%;
width: 72px;
height: 72px;
animation: spin 1.2s linear infinite;
margin-bottom: 1rem;
}
@keyframes spin {
to { transform: rotate(360deg);}
}
#loadingIndicator p {
font-size: 1.3rem;
font-weight: 600;
color: #4338ca;
font-family: 'Badkhate 2', cursive;
}
/* Report container */
#report {
background: white;
border-radius: 1rem;
box-shadow: 0 4px 20px rgba(67, 56, 202, 0.2);
padding: 2rem;
min-height: 300px;
margin-top: 2rem;
overflow-x: auto;
font-size: 1rem;
color: #374151;
text-align: right;
font-weight: 500;
line-height: 1.5;
letter-spacing: 0.02em;
}
/* ===================
Student cards styles
===================== */
.print-form {
background: #fff;
border-radius: 1rem;
box-shadow: 0 10px 28px rgb(0 0 0 / 0.1);
margin-bottom: 2rem;
padding: 1.8rem 2rem;
direction: rtl;
color: #1e293b;
font-weight: 600;
font-size: 1rem;
line-height: 1.6;
transition: box-shadow 0.3s ease;
}
.print-form:hover {
box-shadow: 0 16px 40px rgb(0 0 0 / 0.15);
}
.info-row {
display: flex;
justify-content: space-between;
margin-bottom: 0.6rem;
}
.info-label {
font-weight: 700;
color: #4338ca;
}
/* Table */
.field-table {
width: 100%;
border-collapse: collapse;
margin-top: 1rem;
direction: rtl;
font-size: 0.95rem;
}
.field-table th, .field-table td {
border: 1px solid #ddd;
padding: 10px 14px;
text-align: center;
}
.field-table th {
background: #4338ca;
color: white;
font-weight: 700;
}
.eligible {
color: #059669;
font-weight: 700;
}
.ineligible {
color: #dc2626;
font-weight: 700;
}
/* Signature area */
.signature-area {
margin-top: 2rem;
display: flex;
justify-content: space-between;
gap: 2rem;
font-weight: 600;
font-size: 0.9rem;
}
.signature-line {
width: 150px;
height: 3px;
border-bottom: 2px solid #4338ca;
margin-bottom: 0.25rem;
}
/* Animations */
@keyframes fadeIn {
from {opacity: 0;transform: translateY(20px);}
to {opacity: 1;transform: translateY(0);}
}
.animate-fade-in {
animation: fadeIn 0.5s ease forwards;
}
/* Print styles */
@media print {
body {
background: white !important;
color: black !important;
margin: 0.5cm;
}
.no-print {
display: none !important;
}
.print-only {
display: block !important;
}
.print-header {
margin-bottom: 1rem;
font-weight: 700;
font-family: 'Badkhate 2', cursive;
}
.print-title {
font-size: 1.9rem;
color: black;
margin-bottom: 0.5rem;
}
.print-subtitle {
font-size: 1.25rem;
color: #444444;
}
.print-header .divider-indigo {
margin: 0.8rem auto;
background: #4338ca;
height: 3px;
width: 60px;
border-radius: 9999px;
}
#report {
box-shadow: none;
padding: 0;
font-size: 0.9rem;
line-height: 1.3;
letter-spacing: 0.02em;
}
.print-form {
page-break-inside: avoid; /* avoid splitting card */
/* Force one card per page */
page-break-after: always;
/* Optional: constrain card size */
max-height: 27cm; /* a bit less than A4 page height (29.7cm) */
box-shadow: none;
border-radius: 0;
padding: 1rem;
font-size: 0.95rem;
color: black;
}
.signature-area {
display: flex !important;
margin-top: 1.5rem;
font-weight: 600;
font-size: 0.9rem;
}
/* Reduce margins and padding inside cards */
.info-row {
margin-bottom: 0.3rem;
}
/* Smaller table font and spacing */
.field-table th,
.field-table td {
padding: 6px 8px;
font-size: 0.85rem;
}
/* Adjust headings */
h3 {
margin-top: 1rem;
margin-bottom: 0.5rem;
font-size: 1.1rem;
color: black;
}
</style>
<!-- XLSX library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
</head>
<body>
<div id="particles-js" style="position: fixed; width: 100%; height: 100%; top: 0; left: 0; z-index: -1;"></div>
<script>
particlesJS('particles-js',
{
"particles": {
"number": {
"value": 60,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle"
},
"opacity": {
"value": 0.5,
"random": false
},
"size": {
"value": 3,
"random": true
},
"line_linked": {
"enable": true,
"distance": 150,
"color": "#ffffff",
"opacity": 0.4,
"width": 1
},
"move": {
"enable": true,
"speed": 2,
"direction": "none",
"random": false,
"straight": false,
"out_mode": "out"
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": true,
"mode": "grab" /* 'grab' mode creates lines connecting to cursor */
},
"onclick": {
"enable": true,
"mode": "push"
},
"resize": true
},
"modes": {
"grab": {
"distance": 200,
"line_linked": {
"opacity": 1
}
},
"push": {
"particles_nb": 4
}
}
},
"retina_detect": true
});
</script>
<!-- دکمه فیدبک شناور -->
<a href="efeedback.html" aria-label="ارسال بازخورد"
style="
position: fixed;
bottom: 30px;
left: 30px;
background: #6366f1;
color: white;
padding: 14px 20px;
border-radius: 40px;
font-weight: 700;
font-family: Tahoma, Arial, sans-serif;
box-shadow: 0 6px 15px rgba(99,102,241,0.6);
text-decoration: none;
z-index: 1000;
transition: background-color 0.3s ease;
"
onmouseover="this.style.background='#7c3aed'"
onmouseout="this.style.background='#6366f1'"
>
💬 بازخورد دهید
</a>
<!-- Header/Nav -->
<header class="dashboard-header no-print" role="banner">
<div class="welcome-message" aria-live="polite" aria-atomic="true">
خوش آمدید،
<span class="username"><?php echo htmlspecialchars($_SESSION['full_name']); ?></span>!
</div>
<div>
<a href="logout.php" class="logout-link" aria-label="خارج شدن از حساب کاربری">
<button type="button" class="logout-btn">
<svg viewBox="0 0 512 512" aria-hidden="true" focusable="false">
<path d="M377.9 105.9L500.7 228.7c7.2 7.2 11.3 17.1 11.3 27.3s-4.1 20.1-11.3 27.3L377.9 406.1c-6.4 6.4-15 9.9-24 9.9c-18.7 0-33.9-15.2-33.9-33.9l0-62.1-128 0c-17.7 0-32-14.3-32-32l0-64c0-17.7 14.3-32 32-32l128 0 0-62.1c0-18.7 15.2-33.9 33.9-33.9c9 0 17.6 3.6 24 9.9zM160 96L96 96c-17.7 0-32 14.3-32 32l0 256c0 17.7 14.3 32 32 32l64 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-64 0c-53 0-96-43-96-96L0 128C0 75 43 32 96 32l64 0c17.7 0 32 14.3 32 32s-14.3 32-32 32z"></path>
</svg>
خروج
</button>
</a>
</div>
</header>
<!-- Main content -->
<main class="dashboard-content" role="main">
<!-- Branding Card -->
<section class="card no-print" aria-label="اطلاعات مدرسه">
<div class="school-branding">
<h1>صدور هدایت تحصیلی</h1>
<div class="school-info">
<h2>مدرسه امام علی بن ابیطالب (ع) آبادان</h2>
<div class="divider-indigo"></div>
</div>
</div>
</section>
<!-- Upload Section -->
<section class="card no-print" aria-label="آپلود فایل اکسل">
<label for="excelFile" class="file-upload-label" aria-describedby="upload-instructions" tabindex="0">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17 8 12 3 7 8"/>
<line x1="12" y1="3" x2="12" y2="15"/>
</svg>
<span id="upload-instructions">فایل اکسل دانش آموزان را انتخاب کنید</span>
<input type="file" id="excelFile" accept=".xlsx, .xls" aria-label="انتخاب فایل اکسل" />
</label>
<div class="action-buttons" role="group" aria-label="دکمههای عملیات فایل">
<button onclick="handleFile()" class="primary-button" id="processBtn" aria-live="polite" aria-busy="false">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
پردازش اطلاعات
</button>
<button onclick="window.print()" id="printBtn" class="secondary-button" style="display:none;">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true">
<polyline points="6 9 6 2 18 2 18 9"/>
<path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/>
<rect x="6" y="14" width="12" height="8"/>
</svg>
چاپ گزارشات
</button>
</div>
</section>
<!-- Loading -->
<div id="loadingIndicator" class="fixed z-50 flex hidden inset-0 flex-col items-center justify-center bg-white bg-opacity-95" role="alert" aria-live="assertive" aria-busy="true" aria-label="در حال پردازش اطلاعات">
<div class="loading-spinner"></div>
<p>در حال پردازش اطلاعات...</p>
</div>
<!-- Search Section -->
<section class="card no-print" aria-label="جستجو در دانشآموزان">
<input
type="search"
id="searchInput"
placeholder="نام، نام خانوادگی، کد ملی یا رشته را جستجو کنید..."
class="w-full p-3 rounded border border-indigo-500 text-right"
aria-label="جستجو در دانشآموزان"
/>
</section>
<!-- Report container -->
<section id="report" class="report-container" aria-live="polite" aria-atomic="true" tabindex="0" aria-label="گزارش پردازش شده">
<!-- JS inserts student cards here -->
</section>
<!-- Print Header -->
<section class="print-only" style="display:none;">
<div class="print-header text-center py-5">
<div class="print-title">فرم هدایت تحصیلی دانش آموزان</div>
<div class="print-subtitle mt-2">امیرارسلان ملکی</div>
<div class="divider-indigo" style="margin: 12px auto 0;"></div>
</div>
</section>
</main>
<script>
const fieldsOfStudy = {
"نظری": {
"ریاضی و فیزیک": {
'ریاضی': 14,
'علوم': 13,
'توضیحات': 'نمره ریاضی ≥ ۱۴ و علوم ≥ ۱۳'
},
"علوم تجربی": {
'ریاضی': 13,
'علوم': 14,
'توضیحات': 'نمره علوم ≥ ۱۴ و ریاضی ≥ ۱۳'
},
"علوم انسانی": {
'ادبیات فارسی': 14,
'مطالعات اجتماعی': 12,
'توضیحات': 'نمره ادبیات ≥ ۱۴ و مطالعات ≥ ۱۲'
},
"معارف اسلامی": {
'ادبیات فارسی': 14,
'معارف اسلامی': 14,
'توضیحات': 'نمره ادبیات و معارف ≥ ۱۴'
}
},
"فنی و حرفهای": {
"صنعت": {
'ریاضی': 10,
'کار و فناوری': 12,
'توضیحات': 'نمره ریاضی ≥ ۱۰ و کاروفناوری ≥ ۱۲'
},
"خدمات": {
'کار و فناوری': 12,
'فرهنگ و هنر': 12,
'توضیحات': 'نمره کاروفناوری ≥ ۱۲ و فرهنگ و هنر ≥ ۱۲'
},
"کشاورزی": {
'علوم': 10,
'کار و فناوری': 12,
'توضیحات': 'نمره علوم ≥ ۱۰ و کاروفناوری ≥ ۱۲'
},
"هنر": {
'فرهنگ و هنر': 12,
'کار و فناوری': 12,
'توضیحات': 'نمره فرهنگ و هنر ≥ ۱۲ و کاروفناوری ≥ ۱۲'
}
},
"کار و دانش": {
"صنعت": {
'ریاضی': 10,
'کار و فناوری': 12,
'توضیحات': 'نمره ریاضی ≥ ۱۰ و کاروفناوری ≥ ۱۲'
},
"خدمات": {
'فرهنگ و هنر': 10,
'کار و فناوری': 12,
'توضیحات': 'نمره فرهنگ و هنر ≥ ۱۰ و کاروفناوری ≥ ۱۲'
},
"کشاورزی": {
'علوم': 10,
'کار و فناوری': 12,
'توضیحات': 'نمره علوم ≥ ۱۰ و کاروفناوری ≥ ۱۲'
},
"هنر": {
'فرهنگ و هنر': 10,
'کار و فناوری': 12,
'توضیحات': 'نمره فرهنگ و هنر ≥ ۱۰ و کاروفناوری ≥ ۱۲'
}
}
};
function handleFile() {
const loadingIndicator = document.getElementById('loadingIndicator');
const reportContainer = document.getElementById('report');
const processBtn = document.getElementById('processBtn');
const printBtn = document.getElementById('printBtn');
try {
loadingIndicator.style.display = 'flex';
reportContainer.innerHTML = '';
processBtn.setAttribute('aria-busy', 'true');
processBtn.disabled = true;
printBtn.style.display = 'none';
const file = document.getElementById('excelFile').files[0];
if (!file) throw new Error("لطفاً یک فایل اکسل انتخاب کنید");
const reader = new FileReader();
reader.onload = function(e) {
try {
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: 'array' });
if (workbook.SheetNames.length === 0) throw new Error("فایل انتخابی حاوی هیچ صفحهای نیست");
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet, { defval: null });
if (jsonData.length === 0) throw new Error("صفحه انتخابی حاوی دادهای نیست");
const students = jsonData.map(row => processStudent(row));
const reportHTML = students.map(student => generatePrintForm(student)).join("");
loadingIndicator.style.display = 'none';
reportContainer.innerHTML = reportHTML;
// Animate fade-in for each student card
document.querySelectorAll('.print-form').forEach((el, i) => {
el.classList.add('animate-fade-in');
el.style.animationDelay = `${i * 0.1}s`;
});
printBtn.style.display = 'inline-flex';
processBtn.setAttribute('aria-busy', 'false');
processBtn.disabled = false;
reportContainer.scrollIntoView({ behavior: 'smooth' });
} catch (error) {
loadingIndicator.style.display = 'none';
handleError(error);
}
};
reader.onerror = function() {
loadingIndicator.style.display = 'none';
handleError(new Error("خطا در خواندن فایل"));
};
reader.readAsArrayBuffer(file);
} catch (error) {
loadingIndicator.style.display = 'none';
handleError(error);
}
}
function handleError(error) {
console.error("Error:", error);
alert(error.message || "خطایی رخ داده است. لطفاً دوباره تلاش کنید.");
}
function processStudent(row) {
const gradeFields = {
'ریاضی': ['ریاضی7', 'ریاضی8', 'ریاضی9'],
'علوم': ['علوم7', 'علوم8', 'علوم9'],
'ادبیات فارسی': ['ادبیات7', 'ادبیات8', 'ادبیات9'],
'مطالعات اجتماعی': ['مطالعات7', 'مطالعات8', 'مطالعات9'],
'عربی': ['عربی7', 'عربی8', 'عربی9'],
'معارف اسلامی': ['معارف7', 'معارف8', 'معارف9'],
'کار و فناوری': ['کاروفناوری7', 'کاروفناوری8', 'کاروفناوری9'],
'فرهنگ و هنر': ['فرهنگ و هنر7', 'فرهنگ و هنر8', 'فرهنگ و هنر9']
};
const grades = {};
const averages = {};
for (const [subject, fields] of Object.entries(gradeFields)) {
const gradeData = {
g7: parseFloat(row[fields[0]]) || 0,
g8: parseFloat(row[fields[1]]) || 0,
g9: parseFloat(row[fields[2]]) || 0
};
grades[subject] = gradeData;
const weightedSum = (gradeData.g7 * 1) + (gradeData.g8 * 1) + (gradeData.g9 * 3);
const weight = 5;
averages[subject] = (weightedSum / weight).toFixed(2);
}
const student = {
name: row['نام'] || 'نامشخص',
family: row['نام خانوادگی'] || 'نامشخص',
nationalCode: row['کدملی'] || 'نامشخص',
school: row['مدرسه'] || 'مدرسه امام علی بن ابیطالب (ع)',
grades,
averages,
strengths: [],
weaknesses: []
};
determineFieldAndBranch(student);
analyzeStudentPerformance(student);
return student;
}
function determineFieldAndBranch(student) {
const avg = student.averages;
const math = parseFloat(avg['ریاضی']);
const sci = parseFloat(avg['علوم']);
const per = parseFloat(avg['ادبیات فارسی']);
const art = parseFloat(avg['فرهنگ و هنر']);
const tech = parseFloat(avg['کار و فناوری']);
const rel = parseFloat(avg['معارف اسلامی']);
const soc = parseFloat(avg['مطالعات اجتماعی']);
if (math >= 14 && sci >= 13) {
student.branch = "نظری";
student.field = "ریاضی و فیزیک";
}
else if (sci >= 14 && math >= 13) {
student.branch = "نظری";
student.field = "علوم تجربی";
}
else if (per >= 14 && rel >= 14) {
student.branch = "نظری";
student.field = "معارف اسلامی";
}
else if (per >= 14 && soc >= 12) {
student.branch = "نظری";
student.field = "علوم انسانی";
}
else if (art >= 12 && tech >= 12) {
student.branch = "فنی و حرفهای";
student.field = "هنر";
}
else if (tech >= 12) {
if (math >= 10) {
student.branch = "فنی و حرفهای";
student.field = "صنعت";
}
else if (sci >= 10) {
student.branch = "فنی و حرفهای";
student.field = "کشاورزی";
}
else {
student.branch = "فنی و حرفهای";
student.field = "خدمات";
}
}
else {
student.branch = "کار و دانش";
if (art >= 10) {
student.field = "هنر";
} else if (math >= 10) {
student.field = "صنعت";
} else if (sci >= 10) {
student.field = "کشاورزی";
} else {
student.field = "خدمات";
}
}
student.eligibleFields = {};
for (const branch in fieldsOfStudy) {
student.eligibleFields[branch] = {};
for (const field in fieldsOfStudy[branch]) {
const conditions = fieldsOfStudy[branch][field];
let isEligible = true;
for (const subject in conditions) {
if (subject !== 'توضیحات') {
const studentGrade = parseFloat(avg[subject]) || 0;
if (studentGrade < conditions[subject]) {
isEligible = false;
break;
}
}
}
student.eligibleFields[branch][field] = isEligible;
}
}
}
function analyzeStudentPerformance(student) {
const avg = student.averages;
if (parseFloat(avg['ریاضی']) >= 14) student.strengths.push('ریاضیات');
if (parseFloat(avg['علوم']) >= 14) student.strengths.push('علوم');
if (parseFloat(avg['ادبیات فارسی']) >= 14) student.strengths.push('ادبیات فارسی');
if (parseFloat(avg['فرهنگ و هنر']) >= 14) student.strengths.push('فرهنگ و هنر');
if (parseFloat(avg['کار و فناوری']) >= 14) student.strengths.push('کار و فناوری');
if (parseFloat(avg['ریاضی']) < 10) student.weaknesses.push('ریاضیات');
if (parseFloat(avg['علوم']) < 10) student.weaknesses.push('علوم');
if (parseFloat(avg['ادبیات فارسی']) < 10) student.weaknesses.push('ادبیات فارسی');
if (parseFloat(avg['کار و فناوری']) < 10) student.weaknesses.push('کار و فناوری');
if (student.strengths.length === 0) {
student.strengths.push('نیاز به بررسی بیشتر توسط مشاور');
}
}
function generatePrintForm(student) {
return `
<div class="print-form student-report" tabindex="0">
<div class="student-info">
<div class="info-row">
<span class="info-label">نام و نام خانوادگی:</span>
<span class="student-name">${student.name} ${student.family}</span>
</div>
<div class="info-row">
<span class="info-label">کد ملی:</span>
<span class="student-nationalCode">${student.nationalCode}</span>
</div>
<div class="info-row">
<span class="info-label">مدرسه:</span>
<span>${student.school}</span>
</div>
<div class="info-row">
<span class="info-label">شاخه پیشنهادی:</span>
<span class="student-branch"><strong>${student.branch}</strong></span>
</div>
<div class="info-row">
<span class="info-label">رشته پیشنهادی:</span>
<span class="student-field"><strong>${student.field}</strong></span>
</div>
</div>
<h3 style="margin-top: 1rem; margin-bottom: 0.6rem; color: #4338ca;">وضعیت مجاز بودن رشتهها</h3>
<table class="field-table" role="table" aria-label="وضعیت مجاز بودن رشته ها">
<thead>
<tr>
<th>شاخه</th>
<th>رشته</th>
<th>وضعیت</th>
<th>شرایط</th>
</tr>
</thead>
<tbody>
${Object.entries(student.eligibleFields).map(([branch, fields]) =>
Object.entries(fields).map(([field, isEligible]) => `
<tr>
<td>${branch}</td>
<td>${field}</td>
<td class="${isEligible ? 'eligible' : 'ineligible'}">${isEligible ? 'مجاز' : 'غیرمجاز'}</td>
<td>${fieldsOfStudy[branch][field]['توضیحات']}</td>
</tr>`
).join('')
).join('')}
</tbody>
</table>
<div style="margin-top: 20px;">
<!-- You can add strengths/weaknesses display here -->
</div>
<div class="signature-area print-only" style="display:none;">
<div>
<div class="signature-line"></div>
<p>امضاء و مهر مشاور</p>
</div>
<div>
<div class="signature-line"></div>
<p>امضاء و مهر مدیر</p>
</div>
<div>
<p>تاریخ: ______________</p>
</div>
</div>
</div>`;
}
// Accessibility: allow label keyboard interaction
document.querySelector('.file-upload-label').addEventListener('keydown', e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
document.getElementById('excelFile').click();
}
});
document.addEventListener('DOMContentLoaded', () => {
const searchInput = document.getElementById('searchInput');
const reportContainer = document.getElementById('report');
searchInput.addEventListener('input', () => {
const query = searchInput.value.trim().toLowerCase();
const cards = reportContainer.querySelectorAll('.print-form');
cards.forEach(card => {
const name = card.querySelector('.student-name')?.textContent.toLowerCase() || '';
const nationalCode = card.querySelector('.student-nationalCode')?.textContent.toLowerCase() || '';
const field = card.querySelector('.student-field')?.textContent.toLowerCase() || '';
const branch = card.querySelector('.student-branch')?.textContent.toLowerCase() || '';
if (
name.includes(query) ||
nationalCode.includes(query) ||
field.includes(query) ||
branch.includes(query)
) {
card.style.display = '';
} else {
card.style.display = 'none';
}
});
});
});
</script>
</body>
</html>ASSISTANT
The reason the moving particles are not being shown is that the **particles.js** library itself is missing from your code.
In your code, you call the `particlesJS()` function, which belongs to the **particles.js** library, but you never included it via a `<script>` tag. Without the library being loaded, the `particlesJS()` function is undefined and no particles appear.
---
### How to fix
Add the particles.js library CDN script before your script that calls `particlesJS()`:
Add this inside your `<head>` or just before your inline `<script>` that initializes particles:
```html
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
```
---
### Example placement in your `<body>` or `<head>`:
```html
<body>
<div id="particles-js" style="position: fixed; width: 100%; height: 100%; top: 0; left: 0; z-index: -1;"></div>
<!-- Load particles.js library -->
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
<script>
particlesJS('particles-js',
{
"particles": {
"number": {
"value": 60,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle"
},
"opacity": {
"value": 0.5,
"random": false
},
"size": {
"value": 3,
"random": true
},
"line_linked": {
"enable": true,
"distance": 150,
"color": "#ffffff",
"opacity": 0.4,
"width": 1
},
"move": {
"enable": true,
"speed": 2,
"direction": "none",
"random": false,
"straight": false,
"out_mode": "out"
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": true,
"mode": "grab"
},
"onclick": {
"enable": true,
"mode": "push"
},
"resize": true
},
"modes": {
"grab": {
"distance": 200,
"line_linked": {
"opacity": 1
}
},
"push": {
"particles_nb": 4
}
}
},
"retina_detect": true
});
</script>
...
</body>
```
---
### Why this is necessary
- The `particlesJS()` function is defined by the **particles.js** library.
- Without including the library, you get an error (check your browser console for errors like `particlesJS is not defined`).
- Adding the script ensures the function is loaded and your particles effect will work.
---
**Bonus: Check browser console**
Open your browser devtools console and you may see errors like:
```
Uncaught ReferenceError: particlesJS is not defined
```
This confirms the missing library problem.
---
**Summary**:
**Add this script:**
```html
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
```
before the script block where you call `particlesJS()` to make the moving particles appear.