Your IP : 216.73.216.79


Current Path : /var/www/html/onapp/alammanusiacontent/
Upload File :
Current File : /var/www/html/onapp/alammanusiacontent/alamdanmanusia.html

<!DOCTYPE html>
<html lang="ms" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Alam Dan Manusia</title>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<style>
  :root {
    --bg:      #fef9f0;
    --surface: #ffffff;
    --border:  #e8e0d0;
    --text:    #2d2416;
    --text2:   #6b5e48;
    --text3:   #b0a08a;
    --accent:  #e07b2a;
    --correct:        #15803d;
    --correct-bg:     #f0fdf4;
    --correct-border: #86efac;
    --wrong:          #b91c1c;
    --wrong-bg:       #fff1f2;
    --wrong-border:   #fca5a5;
    --opt-hover: #fff5eb;
    --font: 'Nunito', sans-serif;
  }
  [data-theme="dark"] {
    --bg:      #1a1410;
    --surface: #252015;
    --border:  #3a3020;
    --text:    #f5ead8;
    --text2:   #c4a87a;
    --text3:   #6b5a3a;
    --accent:  #f59e42;
    --correct:        #4ade80;
    --correct-bg:     #052e16;
    --correct-border: #166534;
    --wrong:          #f87171;
    --wrong-bg:       #1c0505;
    --wrong-border:   #7f1d1d;
    --opt-hover: #2a2010;
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }
  html, body {
    height: 100%;
    font-family: var(--font);
    background: var(--bg);
    color: var(--text);
    font-size: 15px;
  }
  body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 16px;
    min-height: 100vh;
    gap: 0;
  }

  /* ── Question view ─────────────────────────────── */
  #view-question {
    display: flex;
    flex-direction: column;
    gap: 13px;
    animation: fadeIn 0.25s ease;
  }

  @keyframes fadeIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
  }

  /* Topic pill */
  #q-topic {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.68rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
    padding: 3px 11px;
    border-radius: 20px;
    align-self: flex-start;
  }

  /* Media: image or video */
  #q-media {
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid var(--border);
    background: var(--border);
    display: none;
    max-height: 200px;
  }
  #q-media img {
    width: 100%;
    max-height: 200px;
    object-fit: cover;
    display: block;
  }
  #q-media iframe {
    width: 100%;
    height: 200px;
    border: none;
    display: block;
  }

  #q-text {
    font-size: 1.02rem;
    font-weight: 700;
    line-height: 1.65;
    color: var(--text);
  }

  /* Options */
  #options { display: flex; flex-direction: column; gap: 7px; }

  .opt {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 14px;
    border: 2px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    cursor: pointer;
    font-family: var(--font);
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text);
    text-align: left;
    transition: border-color 0.13s, background 0.13s, transform 0.1s;
    line-height: 1.4;
  }
  .opt:hover {
    border-color: var(--accent);
    background: var(--opt-hover);
    transform: translateX(4px);
  }
  .opt .ltr {
    min-width: 28px; height: 28px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--accent) 15%, transparent);
    color: var(--accent);
    font-size: 0.75rem;
    font-weight: 900;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
    transition: background 0.13s, color 0.13s;
  }

  /* ── Result view ───────────────────────────────── */
  #view-result {
    display: none;
    flex-direction: column;
    gap: 13px;
    animation: popIn 0.22s ease;
  }
  @keyframes popIn {
    from { opacity: 0; transform: scale(0.97); }
    to   { opacity: 1; transform: scale(1); }
  }

  .result-card {
    border-radius: 12px;
    padding: 18px;
    border: 2px solid;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .result-card.correct { background: var(--correct-bg); border-color: var(--correct-border); }
  .result-card.wrong   { background: var(--wrong-bg);   border-color: var(--wrong-border); }

  .result-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }
  .result-status {
    font-size: 1.05rem;
    font-weight: 900;
  }
  .result-status.c { color: var(--correct); }
  .result-status.w { color: var(--wrong); }

  .result-pts {
    font-size: 1.1rem;
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    padding: 3px 12px;
    border-radius: 20px;
  }
  .result-pts.pos { color: var(--correct); background: color-mix(in srgb, var(--correct) 15%, transparent); }
  .result-pts.neg { color: var(--wrong);   background: color-mix(in srgb, var(--wrong) 15%, transparent); }

  .result-score-row {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text3);
  }
  .result-score-row span {
    font-size: 0.92rem;
    font-weight: 900;
    color: var(--text2);
  }

  .result-divider {
    height: 1px;
    background: var(--border);
  }

  .result-answer {
    font-size: 0.83rem;
    font-weight: 700;
    color: var(--text2);
  }
  .result-answer strong { color: var(--text); font-weight: 800; }

  .result-exp {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text2);
    line-height: 1.65;
  }

  /* ── Loading ─────────────────────────────────── */
  #loading {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text3);
    font-size: 0.9rem;
    font-weight: 700;
    gap: 10px;
    padding: 40px 0;
  }
  .spin {
    width: 22px; height: 22px;
    border: 3px solid var(--border);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: sp 0.7s linear infinite;
  }
  @keyframes sp { to { transform: rotate(360deg); } }
</style>
</head>
<body>

<div id="loading"><div class="spin"></div>Memuatkan soalan...</div>

<!-- Question -->
<div id="view-question" style="display:none;">
  <span id="q-topic"></span>
  <div id="q-media"></div>
  <div id="q-text"></div>
  <div id="options"></div>
</div>

<!-- Result -->
<div id="view-result">
  <div class="result-card" id="result-card">
    <div class="result-top">
      <span class="result-status" id="result-status"></span>
      <span class="result-pts"    id="result-pts"></span>
    </div>
    <div class="result-score-row">Markah sesi: <span id="result-score">0</span></div>
    <div class="result-divider"></div>
    <div class="result-answer" id="result-answer" style="display:none;"></div>
    <div class="result-exp" id="result-exp"></div>
  </div>
</div>

<script>
// ── Config ──────────────────────────────────────────────────────
const PTS_CORRECT = 10, PTS_WRONG = -3;
const LETTERS = ['A','B','C','D','E'];

// ── State ───────────────────────────────────────────────────────
let qs = [], topicMap = {}, pool = [], used = new Set();
let cur = null, startedAt = 0, score = 0;

// ── URL params ──────────────────────────────────────────────────
const P      = new URLSearchParams(location.search);
const fTopic = P.get('topik') || P.get('topic') || null;
const fDiff  = P.get('tahap') || P.get('difficulty') || null;
const theme  = P.get('tema')  || P.get('theme') || null;
if (theme) document.documentElement.setAttribute('data-theme',
  theme === 'dark' ? 'dark' : 'light');

// ── Boot ────────────────────────────────────────────────────────
(async () => {
  try {
    const r = await fetch('alamdanmanusia.json');
    if (!r.ok) throw 0;
    const d = await r.json();
    qs = d.soalan || [];
    (d.topik || []).forEach(t => { topicMap[t.id] = t; });
  } catch {
    qs = FALLBACK; topicMap = FALLBACK_TOPICS;
  }

  pool = qs.filter(q => {
    const tok = fTopic ? fTopic.split(',').map(s=>s.trim()).includes(q.topik) : true;
    const dok = fDiff  ? fDiff.split(',').map(Number).includes(q.tahap)       : true;
    return tok && dok;
  });

  document.getElementById('loading').style.display = 'none';
  loadQuestion();
})();

// ── Load question ───────────────────────────────────────────────
function loadQuestion() {
  document.getElementById('view-result').style.display = 'none';
  document.getElementById('view-question').style.display = 'flex';

  if (!pool.length) {
    document.getElementById('q-text').textContent = 'Tiada soalan untuk penapis ini.';
    return;
  }

  let avail = pool.filter(q => !used.has(q.id));
  if (!avail.length) { used.clear(); avail = [...pool]; }
  cur = avail[Math.floor(Math.random() * avail.length)];
  used.add(cur.id);

  // Topic pill
  const tInfo = topicMap[cur.topik];
  const pill = document.getElementById('q-topic');
  pill.textContent = tInfo ? tInfo.nama : cur.topik;
  if (tInfo?.warna) {
    pill.style.color = tInfo.warna;
    pill.style.background = tInfo.warna + '22';
  }

  // Media: prefer image, fallback video
  const mediaEl = document.getElementById('q-media');
  mediaEl.innerHTML = '';
  mediaEl.style.display = 'none';

  if (cur.imej) {
    const img = document.createElement('img');
    img.src = cur.imej;
    img.alt = 'Gambar soalan';
    img.onerror = () => { mediaEl.style.display = 'none'; };
    mediaEl.appendChild(img);
    mediaEl.style.display = 'block';
  } else if (cur.video) {
    // Support YouTube URLs — convert to embed
    const ytId = extractYTId(cur.video);
    if (ytId) {
      const frame = document.createElement('iframe');
      frame.src = `https://www.youtube.com/embed/${ytId}?rel=0&modestbranding=1`;
      frame.allowFullscreen = true;
      frame.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope';
      mediaEl.appendChild(frame);
      mediaEl.style.display = 'block';
    }
  }

  // Question text
  document.getElementById('q-text').textContent = cur.soalan;

  // Options (shuffled)
  const opts = [...cur.pilihan].sort(() => Math.random() - 0.5);
  const con = document.getElementById('options');
  con.innerHTML = '';
  opts.forEach((o, i) => {
    const btn = document.createElement('button');
    btn.className = 'opt';
    btn.innerHTML = `<span class="ltr">${LETTERS[i]}</span>${o}`;
    btn.dataset.val = o;
    btn.onclick = () => pick(o);
    con.appendChild(btn);
  });

  startedAt = Date.now();
}

// ── Pick answer ─────────────────────────────────────────────────
function pick(choice) {
  const timeTaken = Math.round((Date.now() - startedAt) / 1000);
  const ok = choice === cur.jawapan;
  const delta = ok ? PTS_CORRECT : PTS_WRONG;
  score += delta;

  // Hide question, show result
  document.getElementById('view-question').style.display = 'none';
  document.getElementById('view-result').style.display = 'flex';

  // Card style
  const card = document.getElementById('result-card');
  card.className = 'result-card ' + (ok ? 'correct' : 'wrong');

  // Status
  const statusEl = document.getElementById('result-status');
  statusEl.textContent = ok ? '✅ Betul!' : '❌ Salah';
  statusEl.className = 'result-status ' + (ok ? 'c' : 'w');

  // Points flash
  const ptsEl = document.getElementById('result-pts');
  ptsEl.textContent = (delta > 0 ? '+' : '') + delta + ' mata';
  ptsEl.className = 'result-pts ' + (ok ? 'pos' : 'neg');

  // Running score
  document.getElementById('result-score').textContent =
    (score >= 0 ? '+' : '') + score;

  // Correct answer (only if wrong)
  const ansEl = document.getElementById('result-answer');
  if (!ok) {
    ansEl.innerHTML = `Jawapan betul: <strong>${cur.jawapan}</strong>`;
    ansEl.style.display = 'block';
  } else {
    ansEl.style.display = 'none';
  }

  // Explanation
  document.getElementById('result-exp').textContent = cur.penerangan;

  // postMessage to parent game
  try {
    parent.postMessage({
      type: 'adm_answer',
      correct: ok,
      delta,
      score,
      timeTaken,
      topik: cur.topik,
      tahap: cur.tahap
    }, '*');
  } catch(_) {}
}

// ── Helpers ─────────────────────────────────────────────────────
function extractYTId(url) {
  const m = url.match(/(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|shorts\/))([A-Za-z0-9_-]{11})/);
  return m ? m[1] : null;
}

// ── Expose for parent to call ───────────────────────────────────
window.loadNextQuestion = loadQuestion;

// ── Fallback data ────────────────────────────────────────────────
const FALLBACK_TOPICS = {
  diri_keluarga:  { id:'diri_keluarga',  nama:'Diri Saya dan Keluarga', warna:'#f97316' },
  segar_ceria:    { id:'segar_ceria',    nama:'Segar dan Ceria',        warna:'#22c55e' },
  jaga_diri:      { id:'jaga_diri',      nama:'Jaga Diri, Jaga Kita',  warna:'#3b82f6' },
  inspirasi_alam: { id:'inspirasi_alam', nama:'Inspirasi Alam',        warna:'#a855f7' },
  kraf_tangan:    { id:'kraf_tangan',    nama:'Kraf Tangan',           warna:'#ec4899' },
  mercu_tanda:    { id:'mercu_tanda',    nama:'Mercu Tanda',           warna:'#f59e0b' },
  pemikir_adiwira:{ id:'pemikir_adiwira',nama:'Pemikir Adiwira',       warna:'#06b6d4' },
  pentas_adiwira: { id:'pentas_adiwira', nama:'Pentas Adiwira',        warna:'#84cc16' }
};
const FALLBACK = [
  { id:1, topik:'segar_ceria', tahap:1,
    soalan:'Apakah yang perlu kamu lakukan setiap pagi supaya badan segar dan bersih?',
    pilihan:['Tidur semula','Mandi dan gosok gigi','Makan coklat','Menonton televisyen'],
    jawapan:'Mandi dan gosok gigi',
    penerangan:'Mandi setiap pagi dan menggosok gigi membantu menjaga kebersihan badan. Badan yang bersih menjadikan kita segar, ceria, dan bebas daripada kuman.',
    imej:null, video:null, masa:25 },
  { id:2, topik:'jaga_diri', tahap:1,
    soalan:'Bilakah masa yang paling penting untuk mencuci tangan?',
    pilihan:['Hanya semasa mandi','Sebelum makan dan selepas ke tandas','Hanya bila tangan kotor','Sekali seminggu sahaja'],
    jawapan:'Sebelum makan dan selepas ke tandas',
    penerangan:'Mencuci tangan sebelum makan dan selepas ke tandas adalah sangat penting untuk mengelakkan kuman masuk ke dalam badan.',
    imej:null, video:null, masa:25 },
  { id:3, topik:'mercu_tanda', tahap:1,
    soalan:'Apakah nama bangunan berkembar ikonik yang menjadi mercu tanda Malaysia?',
    pilihan:['Menara Eiffel','Menara Berkembar Petronas','Big Ben','Menara Pisa'],
    jawapan:'Menara Berkembar Petronas',
    penerangan:'Menara Berkembar Petronas di Kuala Lumpur adalah mercu tanda Malaysia yang terkenal di seluruh dunia.',
    imej:'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Petronas_Towers%2C_Kuala_Lumpur.jpg/213px-Petronas_Towers%2C_Kuala_Lumpur.jpg',
    video:null, masa:30 }
];
</script>
</body>
</html>