DU C Unit 2023-24
✕
🎓
FAS Academy
এক্সাম শুরু করতে আপনার তথ্য দিন
আপনার তথ্য শুধুমাত্র ফলাফল ও লিডারবোর্ডের জন্য ব্যবহার হবে।
FAS Academy Quiz
কুইজ মডেল – JSON লোডার
JSON ডেটা ইনপুটের মাধ্যমে স্বয়ংক্রিয়ভাবে লোড করা প্রশ্ন
DU C Unit 2023-24
প্রশ্নের অপশনে ক্লিক করে উত্তর এবং ব্যাখ্যা দেখুন। কঠিন প্রশ্নে Hints এর সহায়তা নিতে পারেন।
পরীক্ষার অবশিষ্ট সময়
45:00
সঠিক উত্তর: ' + attempt.correctAnswer; } else { feedbackHTML += 'সঠিক উত্তর: ' + item.সঠিক_উত্তর; } if (item["ব্যাখ্যা"] && item["ব্যাখ্যা"].trim().length > 0) feedbackHTML += '
ব্যাখ্যা: ' + item["ব্যাখ্যা"] + '
'; feedbackElement.innerHTML = feedbackHTML; feedbackElement.style.display = 'block'; feedbackElement.className = 'feedback ' + (isAttempted ? (attempt.isCorrect ? 'correct-feedback' : 'wrong-feedback') : 'correct-feedback'); options.forEach(opt => { opt.style.pointerEvents = 'none'; opt.classList.remove('correct-option', 'wrong-feedback'); if (stripTags(opt.innerHTML) === stripTags(item.সঠিক_উত্তর)) opt.classList.add('correct-option'); else if (isAttempted && stripTags(opt.innerHTML) === stripTags(attempt.userAnswer) && !attempt.isCorrect) opt.classList.add('wrong-feedback'); }); } else { feedbackElement.style.display = 'none'; options.forEach(opt => opt.classList.remove('correct-option', 'wrong-feedback')); } }); } window.downloadMyAnswersPDF = function() { if (totalQuestions === 0) { alert("আপনি এখনও কোনো প্রশ্নের উত্তর দেননি বা কোনো প্রশ্ন লোড করা হয়নি।"); return; } generatePdfContent(true, true); setTimeout(() => { window.print(); const notice = document.createElement('div'); notice.innerHTML = '✅ PDF সেভ হয়ে গেলে, নতুন করে কুইজ দিতে পেজটি রিফ্রেশ (Reload) করুন।'; notice.style.cssText = 'background:#d4edda; color:#155724; padding:15px; text-align:center; margin:15px 0; border:1px solid #c3e6cb; border-radius:8px; font-size:1.1rem;'; document.getElementById('download-all-container').insertAdjacentElement('afterend', notice); }, 800); } window.downloadAllQuestionsPDF = function() { if (totalQuestions === 0) { alert("প্রশ্নব্যাংক ডাউনলোড করার জন্য কোনো প্রশ্ন লোড করা হয়নি।"); return; } generatePdfContent(true, false); setTimeout(() => { window.print(); const notice = document.createElement('div'); notice.innerHTML = '✅ PDF সেভ হয়ে গেলে, কুইজ দিতে পেজটি রিফ্রেশ (Reload) করুন।'; notice.style.cssText = 'background:#d4edda; color:#155724; padding:15px; text-align:center; margin:15px 0; border:1px solid #c3e6cb; border-radius:8px; font-size:1.1rem;'; document.getElementById('download-all-container').insertAdjacentElement('afterend', notice); }, 800); }// ════════════════════════════════════════════════════════ // FQ SYNC SYSTEM — Full Implementation // ফিচার: ১) নিবন্ধন ২) লিডারবোর্ড ৩) উন্নতি ট্র্যাকার // ৪) অফলাইন ইতিহাস ৫) সার্ভার সিঙ্ক // ════════════════════════════════════════════════════════// ── ⚙️ CONFIGURATION ──────────────────────────────────── const FQ_SERVER_URL_BASE = 'https://script.google.com/macros/s/AKfycbz5CDpAgD38v5dpRZafTncDMWmDmk0_g_w-8H_YmAqa--5FHvPNpEUCj-ds6t8y58PG/exec'; let FQ_SERVER_URL = FQ_SERVER_URL_BASE; // সরাসরি সেট — sync-এ try/catch আছে (function detectInternet() { // fetch দিয়ে চেক — file:// ও mobile উভয় ক্ষেত্রে নির্ভরযোগ্য var controller = new AbortController(); var timer = setTimeout(function() { controller.abort(); }, 5000); fetch(FQ_SERVER_URL_BASE + '?action=ping&_=' + Date.now(), { method: 'GET', signal: controller.signal, cache: 'no-store' }) .then(function() { clearTimeout(timer); FQ_SERVER_URL = FQ_SERVER_URL_BASE; }) .catch(function() { clearTimeout(timer); FQ_SERVER_URL = FQ_SERVER_URL_BASE; }); })(); // ─────────────────────────────────────────────────────────const FQ_QUIZ_NAME = document.title || 'FAS Quiz'; const FQ_KEY = 'fq_' + btoa(unescape(encodeURIComponent(FQ_QUIZ_NAME))).replace(/[^a-z0-9]/gi,'').slice(0,18); let fqName = '', fqId = '';// ── ১. নিবন্ধন ──────────────────────────────────────────── function fqStartQuiz() { var nameEl = document.getElementById('fq-name'); var idEl = document.getElementById('fq-id'); const n = (nameEl ? nameEl.value : '').trim(); const i = (idEl ? idEl.value : '').trim(); if (!n) { alert('অনুগ্রহ করে আপনার নাম লিখুন।'); if(nameEl) nameEl.focus(); return; } if (!i) { alert('অনুগ্রহ করে আপনার মোবাইল নম্বর লিখুন।'); if(idEl) idEl.focus(); return; } fqName = n; fqId = i; document.getElementById('fq-overlay').style.display = 'none'; // Registration শেষে timer শুরু startTimer(); // আগের ইতিহাস দেখাই (quiz শুরুর আগে motivate করতে) fqShowHistory(); }// Enter key দিয়েও start করা যাবে document.addEventListener('keydown', function(e) { if (e.key === 'Enter' && document.getElementById('fq-overlay').style.display !== 'none') fqStartQuiz(); });// ── ৪. localStorage — ইতিহাস ───────────────────────────── function fqGetHistory() { try { return JSON.parse(localStorage.getItem(FQ_KEY) || '[]'); } catch(e) { return []; } }function fqSaveHistory(score, total, correct, incorrect, timeUsed) { const all = fqGetHistory(); all.unshift({ date: new Date().toLocaleString('bn-BD'), name: fqName, id: fqId, score: score, total: total, correct: correct, incorrect: incorrect, pct: total > 0 ? ((correct / total) * 100).toFixed(1) : '0.0', timeUsed: timeUsed }); try { localStorage.setItem(FQ_KEY, JSON.stringify(all.slice(0, 20))); } catch(e) {} }function fqShowHistory() { const all = fqGetHistory().filter(function(h) { return h.id === fqId || h.name === fqName; }); const el = document.getElementById('fq-history'); const content = document.getElementById('fq-hist-content'); if (all.length === 0) { el.style.display = 'none'; return; } el.style.display = 'block'; content.innerHTML = all.map(function(h, i) { const prev = all[i + 1]; let badge = ''; if (prev) { const diff = parseFloat(h.pct) - parseFloat(prev.pct); if (diff > 0) badge = '↑ উন্নতি'; else if (diff < 0) badge = '↓ পতন'; else badge = '→ সমান'; } const m = Math.floor(h.timeUsed / 60), s = h.timeUsed % 60; return ''
+ '
';
}).join('');
}// ── ৩. উন্নতি ট্র্যাকার ──────────────────────────────────
function fqShowProgress(correct, total, score) {
const all = fqGetHistory().filter(function(h) { return h.id === fqId || h.name === fqName; });
const el = document.getElementById('fq-progress');
const content = document.getElementById('fq-progress-content');
const currPct = total > 0 ? (correct / total * 100) : 0;el.style.display = 'block';if (all.length === 0) {
content.innerHTML = ''
+ '
'
+ '' + h.date + ' — ' + (h.name || '') + ' (' + (h.id || '') + ')' + badge + '
'
+ '' + h.correct + '/' + h.total + ' সঠিক | স্কোর: ' + h.score + ' | সময়: ' + m + 'মি ' + s + 'সে
'
+ '' + h.pct + '%
'
+ '🎉 এটি আপনার প্রথম পরীক্ষা! ফলাফল সংরক্ষিত হয়েছে।
' + '' + 'বর্তমান: ' + correct + '/' + total + ' সঠিক (' + currPct.toFixed(1) + '%)
'; return; }const prev = all[0]; const prevPct = parseFloat(prev.pct); const diff = (currPct - prevPct); const arrow = diff > 0.05 ? '↑' : (diff < -0.05 ? '↓' : '→'); const arrowColor = diff > 0.05 ? '#28a745' : (diff < -0.05 ? '#dc3545' : '#ffc107'); const barColor = diff > 0.05 ? 'linear-gradient(90deg,#4caf50,#81c784)' : (diff < -0.05 ? 'linear-gradient(90deg,#f44336,#ef9a9a)' : 'linear-gradient(90deg,#ffc107,#ffe082)');content.innerHTML = ''
+ arrow + ' ' + Math.abs(diff).toFixed(1) + '% '
+ (diff > 0.05 ? 'উন্নতি হয়েছে! 🎉' : (diff < -0.05 ? 'একটু কমেছে।' : 'আগের মতোই।'))
+ '
'
+ ''
+ ''
+ ''
+ ''
+ '
'
+ ''
+ 'আগের পরীক্ষা
' + prevPct.toFixed(1) + '%
এই পরীক্ষা
' + currPct.toFixed(1) + '%
স্কোর
' + score + '
' + correct + '/' + total + ' সঠিক — সর্বোচ্চ ছিল: ' + Math.max(prevPct, currPct).toFixed(1) + '%
';// Animate bar setTimeout(function() { var bar = document.getElementById('fq-pg-bar-el'); if (bar) bar.style.width = currPct.toFixed(1) + '%'; }, 200); }// ── ২. সার্ভার সিঙ্ক ──────────────────────────────────── function fqSetStatus(msg, color) { var st = document.getElementById('fq-sync-st'); if (!st) return; st.textContent = msg; st.style.display = 'block'; st.style.background = color || '#f8f9fa'; }// ── Manual Submit (file:// CORS workaround) ────────────── var _fqPendingPayload = null;function fqShowSubmitButton(payload) { _fqPendingPayload = payload; var wrap = document.getElementById('fq-submit-btn-wrap'); if (wrap) wrap.style.display = 'block'; }function fqManualSubmit() { if (!_fqPendingPayload) return; var btn = document.getElementById('fq-manual-submit-btn'); if (btn) { btn.disabled = true; btn.textContent = '⏳ নাম তোলা হচ্ছে...'; }// GET parameter হিসেবে পাঠাও — browser redirect, CORS নেই var p = _fqPendingPayload; var url = FQ_SERVER_URL_BASE + '?name=' + encodeURIComponent(p.name) + '&id=' + encodeURIComponent(p.id) + '&quiz=' + encodeURIComponent(p.quiz) + '&score=' + encodeURIComponent(p.score) + '&total=' + encodeURIComponent(p.total) + '&correct=' + encodeURIComponent(p.correct) + '&incorrect=' + encodeURIComponent(p.incorrect) + '&timeUsed=' + encodeURIComponent(p.timeUsed) + '&pct=' + encodeURIComponent(p.pct) + '&is_premium=' + encodeURIComponent(p.is_premium !== undefined ? p.is_premium : (window._isPremium ? 1 : 0)) + '&ts=' + encodeURIComponent(p.ts);// নতুন tab-এ খুলবে — result দেখাবে + leaderboard window.open(url, '_blank');if (btn) { btn.disabled = false; btn.textContent = '✅ নাম উঠেছে — তালিকা দেখুন'; } } const FQ_QUEUE_KEY = 'fq_pending_sync_' + FQ_KEY;function fqSaveToQueue(payload) { try { var q = JSON.parse(localStorage.getItem(FQ_QUEUE_KEY) || '[]'); // একই quiz-এর পুরানো entry সরিয়ে নতুনটা রাখো (সর্বশেষ ফলাফল) q = q.filter(function(p) { return p.quiz !== payload.quiz || p.id !== payload.id; }); q.push(payload); localStorage.setItem(FQ_QUEUE_KEY, JSON.stringify(q)); } catch(e) {} }function fqRemoveFromQueue(payload) { try { var q = JSON.parse(localStorage.getItem(FQ_QUEUE_KEY) || '[]'); q = q.filter(function(p) { return !(p.quiz === payload.quiz && p.id === payload.id); }); localStorage.setItem(FQ_QUEUE_KEY, JSON.stringify(q)); } catch(e) {} }async function fqPostPayload(payload) { var ctrl = new AbortController(); var tout = setTimeout(function() { ctrl.abort(); }, 10000); // Google Apps Script doPost: JSON body পাঠাও // mode:'no-cors' → CORS pre-flight নেই, response opaque হয় কিন্তু data পৌঁছায় await fetch(FQ_SERVER_URL_BASE, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify(payload), signal: ctrl.signal, credentials: 'omit', mode: 'no-cors' }); clearTimeout(tout); return true; }// ── অনলাইন হলে queue পাঠিয়ে দাও ──────────────────────── async function fqFlushQueue() { try { var q = JSON.parse(localStorage.getItem(FQ_QUEUE_KEY) || '[]'); if (q.length === 0) return; for (var i = 0; i < q.length; i++) { try { await fqPostPayload(q[i]); fqRemoveFromQueue(q[i]); fqSetStatus('✅ আপনার মেরিট তালিকায় যুক্ত হয়েছে!', '#d4edda'); fqFetchLeaderboard(); } catch(e) { /* এখনও অফলাইন, পরে আবার চেষ্টা হবে */ } } } catch(e) {} }// ব্রাউজার অনলাইন হলেই auto-flush window.addEventListener('online', function() { setTimeout(fqFlushQueue, 1000); });// পেজ লোডেও চেক করো (আগের session-এর pending থাকতে পারে) window.addEventListener('load', function() { if (navigator.onLine) setTimeout(fqFlushQueue, 3000); });async function fqSyncToServer(score, total, correct, incorrect, timeUsed) { fqSetStatus('⏳ আপনার ফলাফল প্রক্রিয়া করা হচ্ছে...', '#e3f2fd'); // ফ্রি ও প্রিমিয়াম উভয় ইউজারের স্কোর সার্ভারে স্টোর হবে // is_premium flag পাঠানো হচ্ছে যাতে admin panel-এ ফিল্টার করা যায় const payload = { action: 'submit', name: fqName, id: fqId, quiz: FQ_QUIZ_NAME, score: score, total: total, correct: correct, incorrect: incorrect, timeUsed: timeUsed, pct: total > 0 ? (correct / total * 100).toFixed(1) : '0.0', is_premium: window._isPremium ? 1 : 0, ts: new Date().toISOString() };// ২ বার চেষ্টা করবে for (var attempt = 1; attempt <= 2; attempt++) { try { await fqPostPayload(payload); fqRemoveFromQueue(payload); // সফল হলে queue থেকে মুছো fqSetStatus('✅ আপনার মেরিট তালিকায় যুক্ত হয়েছে!', '#d4edda'); fqFetchLeaderboard(); return; } catch(e) { if (attempt === 1) { fqSetStatus('🔄 আবার চেষ্টা করা হচ্ছে...', '#fff3cd'); await new Promise(function(r){ setTimeout(r, 2000); }); } else { // Queue-এ সেভ করো — অনলাইন হলে স্বয়ংক্রিয়ভাবে পাঠাবে fqSaveToQueue(payload); fqSetStatus('📶 ইন্টারনেট সংযোগ পেলেই স্বয়ংক্রিয়ভাবে মেরিট তালিকায় যুক্ত হবে। ফলাফল সংরক্ষিত আছে।', '#fff3cd'); // Manual submit button দেখাও fqShowSubmitButton(payload); } } } }// ── ২. লিডারবোর্ড ফেচ ─────────────────────────────────── async function fqFetchLeaderboard() { var el = document.getElementById('fq-leaderboard'); var content = document.getElementById('fq-lb-content'); el.style.display = 'block'; try { var url = FQ_SERVER_URL_BASE + '?action=getLeaderboard&quiz=' + encodeURIComponent(FQ_QUIZ_NAME); var res = await fetch(url); var data = await res.json(); if (!data || data.length === 0) { content.innerHTML = 'এখনও কেউ অংশগ্রহণ করেননি।
';
return;
}
content.innerHTML = data.slice(0, 10).map(function(r, i) {
var medal = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : '#' + (i + 1);
var isMe = r.id === fqId;
return ''
+ '
';
}).join('');// ── মেরিট লিস্টে আমার অবস্থান (বাটনের নিচে) ──
var myIdx = data.findIndex(function(r) { return r.id === fqId; });
var meritBox = document.getElementById('fq-merit-position-top');
var meritText = document.getElementById('fq-merit-pos-text');
if (meritBox && meritText) {
meritBox.style.display = 'block';
if (myIdx >= 0) {
var myData = data[myIdx];
var pos = myIdx + 1;
var posLabel = pos === 1 ? '🥇 ১ম' : pos === 2 ? '🥈 ২য়' : pos === 3 ? '🥉 ৩য়' : '#' + pos + ' তম';
meritText.innerHTML = '' + myData.name + ' — অবস্থান: ' + posLabel + ''
+ ' | স্কোর: ' + myData.pct + '%'
+ ' | মোট অংশগ্রহণকারী: ' + data.length + ' জন';
} else {
meritText.innerHTML = '📶 ইন্টারনেট সংযোগ থাকলে আপনার অবস্থান দেখা যাবে।';
}
}
} catch(e) {
content.innerHTML = '' + medal + '
'
+ '' + r.name + '(' + r.id + ')'
+ (isMe ? ' ← আপনি' : '') + '
'
+ '' + r.pct + '%
'
+ '📶 ইন্টারনেট সংযোগ পেলেই মেরিট তালিকা দেখা যাবে।
';
var meritBox2 = document.getElementById('fq-merit-position-top');
var meritText2 = document.getElementById('fq-merit-pos-text');
if (meritBox2 && meritText2) {
meritBox2.style.display = 'block';
meritText2.innerHTML = '📶 ইন্টারনেট সংযোগ পেলেই মেরিট লিস্টে আপনার অবস্থান দেখা যাবে।';
}
}
}// ── মেরিট বাটনে ক্লিক করলে শুধু অবস্থান দেখাবে ──────────
function fqShowMeritOnly() {
// final-summary দেখাই কিন্তু summary-content ফাঁকা রাখি (বিস্তারিত না)
var fs = document.getElementById('final-summary');
if (fs) fs.style.display = 'block';// merit position box দেখাই
var meritBox = document.getElementById('fq-merit-position-top');
if (meritBox) meritBox.style.display = 'block';// leaderboard দেখাই
var lb = document.getElementById('fq-leaderboard');
if (lb) lb.style.display = 'block';// সার্ভারে ডেটা পাঠাও + মেরিট লোড করো
fqOnComplete();// স্ক্রোল করে merit section-এ নিয়ে যাই
if (meritBox) {
setTimeout(function() {
meritBox.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 500);
}
}// ── Master: quiz শেষে সব ডাকা হয় ───────────────────────
function fqOnComplete() {
const score = calculateScore();
const correct = correctCount;
const incorrect = userAttempts.filter(function(a) { return !a.isCorrect; }).length;
const timeUsed = totalTime - timeLeft;
// ক্রমানুসারে: প্রথমে progress দেখাই, তারপর save করি, তারপর history দেখাই, তারপর sync
fqShowProgress(correct, totalQuestions, score);
fqSaveHistory(score, totalQuestions, correct, incorrect, timeUsed);
fqShowHistory();
fqSyncToServer(score, totalQuestions, correct, incorrect, timeUsed);
}function fqShowMeritOnly() {
var fs = document.getElementById('final-summary');
if (fs) fs.style.display = 'block';
var meritBox = document.getElementById('fq-merit-position-top');
if (meritBox) meritBox.style.display = 'block';
var lb = document.getElementById('fq-leaderboard');
if (lb) lb.style.display = 'block';
fqOnComplete();
if (meritBox) {
setTimeout(function() {
meritBox.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 500);
}
}document.addEventListener('DOMContentLoaded', function() {
configureWatermark();
var ot = document.getElementById('fq-overlay-subtitle');
if (ot) { var mt = document.getElementById('main-title'); if (mt) ot.textContent = mt.textContent; }
// fasInitQuiz() decrypt করবে, তারপর quiz start হবে
fasInitQuiz().then(function() {
quizData = embeddedQuizData;
totalQuestions = quizData.length;
correctCount = 0; incorrectCount = 0; answeredCount = 0; userAttempts = [];
clearInterval(timerInterval); timeLeft = totalTime; updateTimerDisplay(); loadQuiz(); /* timer starts after fqStartQuiz() */
});
});