Created
March 23, 2026 08:28
-
-
Save 0xD8C4A475/9edbbe5b56cefba09ef10fe5600aef66 to your computer and use it in GitHub Desktop.
KRESZ Gyakorló - Magyar közlekedési táblák kvíz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="hu"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>KRESZ Gyakorló</title> | |
| <style> | |
| *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} | |
| :root{ | |
| --bg:#f1f5f9;--card:#ffffff;--primary:#4f46e5;--primary-light:#818cf8; | |
| --correct:#16a34a;--correct-bg:#dcfce7;--wrong:#dc2626;--wrong-bg:#fee2e2; | |
| --text:#1e293b;--text-light:#64748b;--border:#e2e8f0; | |
| --red:#C1121C;--blue:#003DA5;--warn-yellow:#FCBF16;--sign-white:#FFFFFF; | |
| --cat-tilto:#ef4444;--cat-figy:#f59e0b;--cat-utas:#3b82f6;--cat-taj:#06b6d4; | |
| --radius:12px;--shadow:0 1px 3px rgba(0,0,0,.08),0 4px 12px rgba(0,0,0,.04); | |
| } | |
| body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; | |
| background:var(--bg);color:var(--text);min-height:100vh;line-height:1.5} | |
| .container{max-width:640px;margin:0 auto;padding:16px} | |
| h1{font-size:1.6rem;text-align:center;margin:12px 0 4px} | |
| .subtitle{text-align:center;color:var(--text-light);font-size:.95rem;margin-bottom:20px} | |
| /* Start Screen */ | |
| #startScreen .logo{text-align:center;margin:20px 0 8px} | |
| #startScreen .logo svg{width:80px;height:80px} | |
| .section-title{font-size:.85rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--text-light);margin:20px 0 8px} | |
| .cat-pills{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px} | |
| .cat-pill{padding:8px 16px;border-radius:20px;border:2px solid var(--border);background:var(--card); | |
| cursor:pointer;font-size:.9rem;font-weight:500;transition:all .2s;user-select:none} | |
| .cat-pill:hover{border-color:var(--primary-light);background:#eef2ff} | |
| .cat-pill.active{color:#fff;border-color:transparent} | |
| .cat-pill[data-cat="all"].active{background:var(--primary)} | |
| .cat-pill[data-cat="tilto"].active{background:var(--cat-tilto)} | |
| .cat-pill[data-cat="figyelmez"].active{background:var(--cat-figy)} | |
| .cat-pill[data-cat="utasito"].active{background:var(--cat-utas)} | |
| .cat-pill[data-cat="taj"].active{background:var(--cat-taj)} | |
| .count-btns{display:flex;gap:8px;margin-bottom:24px} | |
| .count-btn{flex:1;padding:10px;border-radius:var(--radius);border:2px solid var(--border);background:var(--card); | |
| cursor:pointer;font-size:1rem;font-weight:600;transition:all .2s;text-align:center} | |
| .count-btn:hover{border-color:var(--primary-light)} | |
| .count-btn.active{background:var(--primary);color:#fff;border-color:var(--primary)} | |
| .start-btn{width:100%;padding:14px;border:none;border-radius:var(--radius); | |
| background:linear-gradient(135deg,var(--primary),var(--primary-light)); | |
| color:#fff;font-size:1.1rem;font-weight:600;cursor:pointer;transition:transform .15s,box-shadow .15s} | |
| .start-btn:hover{transform:translateY(-1px);box-shadow:0 4px 16px rgba(79,70,229,.35)} | |
| .start-btn:active{transform:translateY(0)} | |
| /* Quiz Screen */ | |
| #quizScreen{display:none} | |
| .progress-wrap{background:var(--border);border-radius:8px;height:8px;margin-bottom:16px;overflow:hidden} | |
| .progress-bar{height:100%;border-radius:8px;background:linear-gradient(90deg,var(--primary),var(--primary-light));transition:width .4s ease} | |
| .quiz-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;font-size:.9rem;color:var(--text-light)} | |
| .quiz-header .score{font-weight:600;color:var(--correct)} | |
| .sign-card{background:var(--card);border-radius:var(--radius);box-shadow:var(--shadow);padding:24px;text-align:center;margin-bottom:16px; | |
| transition:opacity .3s,transform .3s} | |
| .sign-card.fade-out{opacity:0;transform:translateY(-10px)} | |
| .sign-card.fade-in{opacity:0;transform:translateY(10px)} | |
| .sign-card svg{width:140px;height:140px;margin:0 auto 12px} | |
| .sign-category{display:inline-block;padding:3px 10px;border-radius:10px;font-size:.75rem;font-weight:600;color:#fff;margin-bottom:8px} | |
| .sign-category.tilto{background:var(--cat-tilto)} | |
| .sign-category.figyelmez{background:var(--cat-figy);color:var(--text)} | |
| .sign-category.utasito{background:var(--cat-utas)} | |
| .sign-category.taj{background:var(--cat-taj)} | |
| .answers{display:flex;flex-direction:column;gap:10px;margin-bottom:16px} | |
| .answer-btn{padding:14px 18px;border:2px solid var(--border);border-radius:var(--radius);background:var(--card); | |
| cursor:pointer;font-size:.95rem;text-align:left;transition:all .2s;min-height:48px;display:flex;align-items:center;gap:10px} | |
| .answer-btn:hover:not(.disabled){border-color:var(--primary-light);background:#f8fafc} | |
| .answer-btn .letter{width:28px;height:28px;border-radius:50%;background:var(--bg);display:flex;align-items:center;justify-content:center; | |
| font-weight:700;font-size:.85rem;flex-shrink:0;transition:all .2s} | |
| .answer-btn.correct{border-color:var(--correct);background:var(--correct-bg)} | |
| .answer-btn.correct .letter{background:var(--correct);color:#fff} | |
| .answer-btn.wrong{border-color:var(--wrong);background:var(--wrong-bg)} | |
| .answer-btn.wrong .letter{background:var(--wrong);color:#fff} | |
| .answer-btn.disabled{pointer-events:none} | |
| .answer-btn.reveal-correct{border-color:var(--correct);background:var(--correct-bg)} | |
| .answer-btn.reveal-correct .letter{background:var(--correct);color:#fff} | |
| .next-btn{width:100%;padding:12px;border:none;border-radius:var(--radius);background:var(--primary); | |
| color:#fff;font-size:1rem;font-weight:600;cursor:pointer;transition:transform .1s;display:none} | |
| .next-btn:hover{background:var(--primary-light)} | |
| .next-btn.visible{display:block} | |
| /* Result Screen */ | |
| #resultScreen{display:none} | |
| .result-card{background:var(--card);border-radius:var(--radius);box-shadow:var(--shadow);padding:32px 24px;text-align:center;margin-bottom:20px} | |
| .donut-wrap{position:relative;width:160px;height:160px;margin:0 auto 16px} | |
| .donut{width:160px;height:160px;border-radius:50%} | |
| .donut-center{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%); | |
| width:100px;height:100px;border-radius:50%;background:var(--card);display:flex;flex-direction:column;align-items:center;justify-content:center} | |
| .donut-pct{font-size:2rem;font-weight:800;line-height:1} | |
| .donut-label{font-size:.8rem;color:var(--text-light)} | |
| .result-msg{font-size:1.2rem;font-weight:600;margin:12px 0 4px} | |
| .result-sub{color:var(--text-light);font-size:.9rem;margin-bottom:16px} | |
| .result-stats{display:flex;justify-content:center;gap:24px;margin-bottom:20px} | |
| .stat{text-align:center} | |
| .stat-val{font-size:1.4rem;font-weight:700} | |
| .stat-label{font-size:.75rem;color:var(--text-light)} | |
| .stat-correct .stat-val{color:var(--correct)} | |
| .stat-wrong .stat-val{color:var(--wrong)} | |
| .wrong-review{margin-top:16px;text-align:left} | |
| .wrong-review h3{font-size:1rem;margin-bottom:12px} | |
| .wrong-item{display:flex;gap:12px;align-items:center;padding:12px;background:var(--wrong-bg);border-radius:var(--radius);margin-bottom:8px} | |
| .wrong-item svg{width:56px;height:56px;flex-shrink:0} | |
| .wrong-detail{flex:1} | |
| .wrong-detail .your-ans{color:var(--wrong);font-size:.85rem;text-decoration:line-through} | |
| .wrong-detail .correct-ans{color:var(--correct);font-size:.85rem;font-weight:600} | |
| .restart-btn{width:100%;padding:14px;border:none;border-radius:var(--radius); | |
| background:linear-gradient(135deg,var(--primary),var(--primary-light)); | |
| color:#fff;font-size:1.1rem;font-weight:600;cursor:pointer;margin-top:16px;transition:transform .15s} | |
| .restart-btn:hover{transform:translateY(-1px)} | |
| @media(max-width:480px){ | |
| .container{padding:12px} | |
| h1{font-size:1.3rem} | |
| .sign-card svg{width:120px;height:120px} | |
| .cat-pills{gap:6px} | |
| .cat-pill{padding:6px 12px;font-size:.82rem} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <!-- ============ START SCREEN ============ --> | |
| <div id="startScreen"> | |
| <div class="logo"> | |
| <svg viewBox="0 0 80 80" fill="none"> | |
| <rect x="4" y="4" width="72" height="72" rx="16" fill="#4f46e5"/> | |
| <path d="M40 18 L58 56 H22Z" fill="none" stroke="#fff" stroke-width="3.5" stroke-linejoin="round"/> | |
| <circle cx="40" cy="48" r="3" fill="#fff"/> | |
| <rect x="38" y="30" width="4" height="12" rx="2" fill="#fff"/> | |
| </svg> | |
| </div> | |
| <h1>KRESZ Gyakorló</h1> | |
| <p class="subtitle">Ismerd meg a közlekedési táblákat!</p> | |
| <div class="section-title">Kategória</div> | |
| <div class="cat-pills"> | |
| <div class="cat-pill active" data-cat="all" onclick="selectCat(this)">Összes</div> | |
| <div class="cat-pill" data-cat="tilto" onclick="selectCat(this)">Tiltó táblák</div> | |
| <div class="cat-pill" data-cat="figyelmez" onclick="selectCat(this)">Figyelmeztető</div> | |
| <div class="cat-pill" data-cat="utasito" onclick="selectCat(this)">Utasító táblák</div> | |
| <div class="cat-pill" data-cat="taj" onclick="selectCat(this)">Tájékoztató</div> | |
| </div> | |
| <div class="section-title">Kérdések száma</div> | |
| <div class="count-btns"> | |
| <div class="count-btn active" data-count="10" onclick="selectCount(this)">10</div> | |
| <div class="count-btn" data-count="20" onclick="selectCount(this)">20</div> | |
| <div class="count-btn" data-count="0" onclick="selectCount(this)">Összes</div> | |
| </div> | |
| <button class="start-btn" onclick="startQuiz()">Indítás</button> | |
| </div> | |
| <!-- ============ QUIZ SCREEN ============ --> | |
| <div id="quizScreen"> | |
| <div class="progress-wrap"><div class="progress-bar" id="progressBar"></div></div> | |
| <div class="quiz-header"> | |
| <span id="questionNum">1 / 10</span> | |
| <span class="score" id="scoreDisplay">0 pont</span> | |
| </div> | |
| <div class="sign-card" id="signCard"> | |
| <div id="signSvg"></div> | |
| <span class="sign-category" id="signCat"></span> | |
| </div> | |
| <div class="answers" id="answersDiv"></div> | |
| <button class="next-btn" id="nextBtn" onclick="nextQuestion()">Következő</button> | |
| </div> | |
| <!-- ============ RESULT SCREEN ============ --> | |
| <div id="resultScreen"> | |
| <div class="result-card"> | |
| <div class="donut-wrap"> | |
| <div class="donut" id="donutChart"></div> | |
| <div class="donut-center"> | |
| <span class="donut-pct" id="pctText">0%</span> | |
| <span class="donut-label">pontosság</span> | |
| </div> | |
| </div> | |
| <div class="result-msg" id="resultMsg"></div> | |
| <div class="result-sub" id="resultSub"></div> | |
| <div class="result-stats"> | |
| <div class="stat stat-correct"><div class="stat-val" id="statCorrect">0</div><div class="stat-label">Helyes</div></div> | |
| <div class="stat"><div class="stat-val" id="statTotal">0</div><div class="stat-label">Kérdés</div></div> | |
| <div class="stat stat-wrong"><div class="stat-val" id="statWrong">0</div><div class="stat-label">Hibás</div></div> | |
| </div> | |
| </div> | |
| <div class="wrong-review" id="wrongReview"></div> | |
| <button class="restart-btn" onclick="restartQuiz()">Újrakezdés</button> | |
| </div> | |
| </div> | |
| <script> | |
| // ===== SVG SIGN DRAWING SYSTEM ===== | |
| // Base shape builders | |
| function svgWrap(inner, vb='0 0 120 120'){return `<svg viewBox="${vb}" xmlns="http://www.w3.org/2000/svg">${inner}</svg>`} | |
| function prohibCircle(inner){ | |
| return svgWrap(`<circle cx="60" cy="60" r="52" fill="#C1121C"/><circle cx="60" cy="60" r="42" fill="#fff"/>${inner}`); | |
| } | |
| function blueCircle(inner){ | |
| return svgWrap(`<circle cx="60" cy="60" r="52" fill="#003DA5"/>${inner}`); | |
| } | |
| function warnTriangle(inner){ | |
| return svgWrap(`<path d="M60 10 L110 100 H10Z" fill="#C1121C" stroke="#C1121C" stroke-width="2" stroke-linejoin="round"/> | |
| <path d="M60 20 L104 96 H16Z" fill="#FCBF16" stroke="#FCBF16" stroke-width="1" stroke-linejoin="round"/>${inner}`); | |
| } | |
| function blueSquare(inner){ | |
| return svgWrap(`<rect x="8" y="8" width="104" height="104" rx="8" fill="#003DA5"/>${inner}`); | |
| } | |
| function blueRect(inner){ | |
| return svgWrap(`<rect x="4" y="16" width="112" height="88" rx="8" fill="#003DA5"/>${inner}`); | |
| } | |
| // Prohibitory signs with red border on blue background | |
| function prohibBlueCircle(inner){ | |
| return svgWrap(`<circle cx="60" cy="60" r="52" fill="#C1121C"/><circle cx="60" cy="60" r="46" fill="#003DA5"/>${inner}`); | |
| } | |
| // ===== SIGN DEFINITIONS ===== | |
| const signs = [ | |
| // ===== TILTÓ TÁBLÁK (9) ===== | |
| { | |
| id:'tilto_behajtani',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Behajtani tilos', | |
| svg: svgWrap(`<circle cx="60" cy="60" r="52" fill="#C1121C"/><rect x="24" y="50" width="72" height="20" rx="4" fill="#fff"/>`) | |
| }, | |
| { | |
| id:'tilto_mindket',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Mindkét irányból behajtani tilos', | |
| svg: prohibCircle(``) | |
| }, | |
| { | |
| id:'tilto_kerekpar',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Kerékpárral behajtani tilos', | |
| svg: prohibCircle(`<g transform="translate(60,62) scale(0.75)"><circle cx="0" cy="12" r="10" fill="none" stroke="#1e293b" stroke-width="4"/><circle cx="0" cy="-14" r="10" fill="none" stroke="#1e293b" stroke-width="4"/><line x1="0" y1="12" x2="0" y2="-14" stroke="#1e293b" stroke-width="3.5"/><line x1="0" y1="-14" x2="-8" y2="-24" stroke="#1e293b" stroke-width="3"/><line x1="0" y1="-14" x2="8" y2="-24" stroke="#1e293b" stroke-width="3"/><line x1="0" y1="-4" x2="10" y2="-10" stroke="#1e293b" stroke-width="3"/></g>`) | |
| }, | |
| { | |
| id:'tilto_elozni',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Előzni tilos', | |
| svg: prohibCircle(`<g><rect x="26" y="44" width="16" height="28" rx="6" fill="#1e293b"/><rect x="44" y="44" width="16" height="28" rx="6" fill="#C1121C"/></g>`) | |
| }, | |
| { | |
| id:'tilto_30',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Sebességkorlátozás 30 km/h', | |
| svg: prohibCircle(`<text x="60" y="72" text-anchor="middle" font-size="36" font-weight="800" fill="#1e293b" font-family="Arial,sans-serif">30</text>`) | |
| }, | |
| { | |
| id:'tilto_50',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Sebességkorlátozás 50 km/h', | |
| svg: prohibCircle(`<text x="60" y="72" text-anchor="middle" font-size="36" font-weight="800" fill="#1e293b" font-family="Arial,sans-serif">50</text>`) | |
| }, | |
| { | |
| id:'tilto_70',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Sebességkorlátozás 70 km/h', | |
| svg: prohibCircle(`<text x="60" y="72" text-anchor="middle" font-size="36" font-weight="800" fill="#1e293b" font-family="Arial,sans-serif">70</text>`) | |
| }, | |
| { | |
| id:'tilto_megallni',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Megállni tilos', | |
| svg: prohibBlueCircle(`<line x1="30" y1="30" x2="90" y2="90" stroke="#C1121C" stroke-width="7"/><line x1="90" y1="30" x2="30" y2="90" stroke="#C1121C" stroke-width="7"/>`) | |
| }, | |
| { | |
| id:'tilto_varakozni',cat:'tilto',catName:'Tiltó táblák', | |
| name:'Várakozni tilos', | |
| svg: prohibBlueCircle(`<line x1="30" y1="30" x2="90" y2="90" stroke="#C1121C" stroke-width="7"/>`) | |
| }, | |
| // ===== FIGYELMEZTETŐ TÁBLÁK (9) ===== | |
| { | |
| id:'figy_veszely',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Egyéb veszély', | |
| svg: warnTriangle(`<text x="60" y="82" text-anchor="middle" font-size="48" font-weight="900" fill="#1e293b" font-family="Arial,sans-serif">!</text>`) | |
| }, | |
| { | |
| id:'figy_jobbra',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Jobbra ívelő kanyar', | |
| svg: warnTriangle(`<path d="M50 80 Q50 55 70 45" fill="none" stroke="#1e293b" stroke-width="6" stroke-linecap="round"/><polygon points="72,38 76,50 64,48" fill="#1e293b"/>`) | |
| }, | |
| { | |
| id:'figy_balra',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Balra ívelő kanyar', | |
| svg: warnTriangle(`<path d="M70 80 Q70 55 50 45" fill="none" stroke="#1e293b" stroke-width="6" stroke-linecap="round"/><polygon points="48,38 44,50 56,48" fill="#1e293b"/>`) | |
| }, | |
| { | |
| id:'figy_kereszt',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Útkereszteződés', | |
| svg: warnTriangle(`<rect x="55" y="40" width="10" height="46" rx="2" fill="#1e293b"/><rect x="40" y="55" width="40" height="10" rx="2" fill="#1e293b"/>`) | |
| }, | |
| { | |
| id:'figy_gyalogos',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Gyalogos-átkelőhely közeledik', | |
| svg: warnTriangle(`<g transform="translate(55,48) scale(0.7)"> | |
| <circle cx="0" cy="-12" r="6" fill="#1e293b"/> | |
| <line x1="0" y1="-6" x2="0" y2="18" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="-12" y1="4" x2="12" y2="4" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="-10" y2="36" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="10" y2="36" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| </g><g transform="translate(40,76)"><rect x="0" y="0" width="4" height="14" fill="#1e293b"/><rect x="7" y="0" width="4" height="14" fill="#1e293b"/><rect x="14" y="0" width="4" height="14" fill="#1e293b"/></g>`) | |
| }, | |
| { | |
| id:'figy_utepites',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Útépítés', | |
| svg: warnTriangle(`<g transform="translate(55,50) scale(0.7)"> | |
| <circle cx="0" cy="-12" r="6" fill="#1e293b"/> | |
| <line x1="0" y1="-6" x2="0" y2="18" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="0" y1="4" x2="16" y2="-8" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="0" y1="4" x2="-14" y2="0" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="-10" y2="36" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="10" y2="36" stroke="#1e293b" stroke-width="4" stroke-linecap="round"/> | |
| <line x1="16" y1="-8" x2="20" y2="-20" stroke="#1e293b" stroke-width="3.5" stroke-linecap="round"/> | |
| <polygon points="14,-22 26,-22 20,-28" fill="#1e293b"/> | |
| </g>`) | |
| }, | |
| { | |
| id:'figy_csuszos',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Csúszós útburkolat', | |
| svg: warnTriangle(`<path d="M48 44 C48 44 44 60 38 72 M52 44 C56 56 68 60 72 68" fill="none" stroke="#1e293b" stroke-width="5" stroke-linecap="round"/> | |
| <rect x="42" y="38" width="16" height="10" rx="3" fill="#1e293b"/>`) | |
| }, | |
| { | |
| id:'figy_vasut',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Vasúti átjáró sorompóval', | |
| svg: warnTriangle(`<rect x="35" y="52" width="50" height="6" rx="2" fill="#1e293b"/><rect x="35" y="62" width="50" height="6" rx="2" fill="#1e293b"/><rect x="55" y="50" width="6" height="34" rx="2" fill="#1e293b"/>`) | |
| }, | |
| { | |
| id:'figy_egyenetlen',cat:'figyelmez',catName:'Figyelmeztető táblák', | |
| name:'Egyenetlen úttest', | |
| svg: warnTriangle(`<path d="M35 75 Q45 55 55 70 Q65 85 75 65" fill="none" stroke="#1e293b" stroke-width="6" stroke-linecap="round"/>`) | |
| }, | |
| // ===== UTASÍTÓ TÁBLÁK (8) ===== | |
| { | |
| id:'utas_jobbra',cat:'utasito',catName:'Utasító táblák', | |
| name:'Kötelező haladási irány jobbra', | |
| svg: blueCircle(`<polygon points="50,45 80,60 50,75" fill="#fff"/><rect x="30" y="54" width="26" height="12" rx="2" fill="#fff"/>`) | |
| }, | |
| { | |
| id:'utas_balra',cat:'utasito',catName:'Utasító táblák', | |
| name:'Kötelező haladási irány balra', | |
| svg: blueCircle(`<polygon points="70,45 40,60 70,75" fill="#fff"/><rect x="64" y="54" width="26" height="12" rx="2" fill="#fff"/>`) | |
| }, | |
| { | |
| id:'utas_egyenesen',cat:'utasito',catName:'Utasító táblák', | |
| name:'Kötelező haladási irány egyenesen', | |
| svg: blueCircle(`<polygon points="45,42 60,22 75,42" fill="#fff"/><rect x="54" y="36" width="12" height="40" rx="2" fill="#fff"/>`) | |
| }, | |
| { | |
| id:'utas_korforgalom',cat:'utasito',catName:'Utasító táblák', | |
| name:'Körforgalom', | |
| svg: blueCircle(`<g fill="none" stroke="#fff" stroke-width="5" stroke-linecap="round"> | |
| <path d="M42 44 A20 20 0 0 1 78 56"/><path d="M78 56 A20 20 0 0 1 56 80"/><path d="M56 80 A20 20 0 0 1 38 50"/> | |
| </g><polygon points="38,40 48,48 36,52" fill="#fff"/><polygon points="82,50 74,60 80,46" fill="#fff"/><polygon points="52,84 58,72 64,84" fill="#fff"/>`) | |
| }, | |
| { | |
| id:'utas_kerekpar',cat:'utasito',catName:'Utasító táblák', | |
| name:'Kerékpárút', | |
| svg: blueCircle(`<g transform="translate(60,62) scale(0.78)"><circle cx="0" cy="12" r="10" fill="none" stroke="#fff" stroke-width="4"/><circle cx="0" cy="-14" r="10" fill="none" stroke="#fff" stroke-width="4"/><line x1="0" y1="12" x2="0" y2="-14" stroke="#fff" stroke-width="3.5"/><line x1="0" y1="-14" x2="-8" y2="-24" stroke="#fff" stroke-width="3"/><line x1="0" y1="-14" x2="8" y2="-24" stroke="#fff" stroke-width="3"/><line x1="0" y1="-4" x2="10" y2="-10" stroke="#fff" stroke-width="3"/></g>`) | |
| }, | |
| { | |
| id:'utas_gyalog',cat:'utasito',catName:'Utasító táblák', | |
| name:'Gyalogút', | |
| svg: blueCircle(`<g transform="translate(60,52) scale(0.85)"> | |
| <circle cx="0" cy="-14" r="7" fill="#fff"/> | |
| <line x1="0" y1="-7" x2="0" y2="18" stroke="#fff" stroke-width="5" stroke-linecap="round"/> | |
| <line x1="-14" y1="3" x2="14" y2="3" stroke="#fff" stroke-width="5" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="-12" y2="38" stroke="#fff" stroke-width="5" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="12" y2="38" stroke="#fff" stroke-width="5" stroke-linecap="round"/> | |
| </g>`) | |
| }, | |
| { | |
| id:'utas_min30',cat:'utasito',catName:'Utasító táblák', | |
| name:'Legkisebb megengedett sebesség 30 km/h', | |
| svg: blueCircle(`<text x="60" y="72" text-anchor="middle" font-size="36" font-weight="800" fill="#fff" font-family="Arial,sans-serif">30</text>`) | |
| }, | |
| { | |
| id:'utas_egyenesen_jobbra',cat:'utasito',catName:'Utasító táblák', | |
| name:'Kötelező egyenesen vagy jobbra', | |
| svg: blueCircle(`<polygon points="45,38 60,20 75,38" fill="#fff"/><rect x="54" y="32" width="12" height="30" rx="2" fill="#fff"/> | |
| <polygon points="66,68 86,56 78,72" fill="#fff"/><rect x="56" y="56" width="18" height="10" rx="2" fill="#fff"/>`) | |
| }, | |
| // ===== TÁJÉKOZTATÓ TÁBLÁK (8) ===== | |
| { | |
| id:'taj_gyalogos',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Gyalogos-átkelőhely', | |
| svg: blueSquare(`<polygon points="60 24, 96 80, 24 80" fill="#fff"/> | |
| <g transform="translate(58,48) scale(0.6)"> | |
| <circle cx="0" cy="-12" r="7" fill="#003DA5"/> | |
| <line x1="0" y1="-5" x2="0" y2="18" stroke="#003DA5" stroke-width="5" stroke-linecap="round"/> | |
| <line x1="-14" y1="3" x2="14" y2="3" stroke="#003DA5" stroke-width="5" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="-12" y2="36" stroke="#003DA5" stroke-width="5" stroke-linecap="round"/> | |
| <line x1="0" y1="18" x2="12" y2="36" stroke="#003DA5" stroke-width="5" stroke-linecap="round"/> | |
| </g> | |
| <g transform="translate(35,72)"><rect x="0" y="0" width="4" height="12" fill="#003DA5"/><rect x="7" y="0" width="4" height="12" fill="#003DA5"/><rect x="14" y="0" width="4" height="12" fill="#003DA5"/><rect x="21" y="0" width="4" height="12" fill="#003DA5"/></g>`) | |
| }, | |
| { | |
| id:'taj_parkolas',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Parkolás', | |
| svg: blueSquare(`<text x="60" y="80" text-anchor="middle" font-size="60" font-weight="800" fill="#fff" font-family="Arial,sans-serif">P</text>`) | |
| }, | |
| { | |
| id:'taj_korhaz',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Kórház', | |
| svg: blueSquare(`<text x="60" y="80" text-anchor="middle" font-size="60" font-weight="800" fill="#fff" font-family="Arial,sans-serif">H</text>`) | |
| }, | |
| { | |
| id:'taj_egyiranyu',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Egyirányú forgalom', | |
| svg: blueRect(`<polygon points="76,45 100,60 76,75" fill="#fff"/><rect x="24" y="52" width="56" height="16" rx="3" fill="#fff"/>`) | |
| }, | |
| { | |
| id:'taj_foutvonal',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Főútvonal', | |
| svg: svgWrap(`<rect x="60" y="18" width="50" height="50" rx="4" fill="#FCBF16" stroke="#1e293b" stroke-width="3" transform="rotate(45,60,60)"/><rect x="60" y="28" width="36" height="36" rx="2" fill="#fff" transform="rotate(45,60,60)"/>`) | |
| }, | |
| { | |
| id:'taj_foutvonal_vege',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Főútvonal vége', | |
| svg: svgWrap(`<rect x="60" y="18" width="50" height="50" rx="4" fill="#FCBF16" stroke="#1e293b" stroke-width="3" transform="rotate(45,60,60)"/><rect x="60" y="28" width="36" height="36" rx="2" fill="#fff" transform="rotate(45,60,60)"/> | |
| <line x1="32" y1="32" x2="88" y2="88" stroke="#1e293b" stroke-width="5"/> | |
| <line x1="36" y1="28" x2="92" y2="84" stroke="#1e293b" stroke-width="3"/> | |
| <line x1="28" y1="36" x2="84" y2="92" stroke="#1e293b" stroke-width="3"/>`) | |
| }, | |
| { | |
| id:'taj_busz',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Autóbusz-megállóhely', | |
| svg: blueSquare(`<rect x="24" y="42" width="72" height="36" rx="8" fill="#fff"/> | |
| <rect x="24" y="62" width="72" height="16" rx="0" fill="#fff"/> | |
| <circle cx="40" cy="76" r="6" fill="#003DA5"/><circle cx="80" cy="76" r="6" fill="#003DA5"/> | |
| <rect x="28" y="48" width="16" height="12" rx="3" fill="#003DA5"/> | |
| <rect x="48" y="48" width="16" height="12" rx="3" fill="#003DA5"/> | |
| <rect x="68" y="48" width="16" height="12" rx="3" fill="#003DA5"/>`) | |
| }, | |
| { | |
| id:'taj_autopalya',cat:'taj',catName:'Tájékoztató táblák', | |
| name:'Autópálya', | |
| svg: svgWrap(`<rect x="8" y="16" width="104" height="88" rx="8" fill="#008751"/> | |
| <path d="M38 88 L52 36 Q60 26 68 36 L82 88" fill="none" stroke="#fff" stroke-width="5"/> | |
| <line x1="52" y1="50" x2="68" y2="50" stroke="#fff" stroke-width="4"/> | |
| <path d="M30 88 Q60 50 90 88" fill="none" stroke="#fff" stroke-width="3"/>`) | |
| } | |
| ]; | |
| // ===== QUIZ STATE ===== | |
| let selectedCat = 'all'; | |
| let selectedCount = 10; | |
| let questions = []; | |
| let currentQ = 0; | |
| let score = 0; | |
| let answered = false; | |
| let wrongAnswers = []; | |
| function selectCat(el){ | |
| document.querySelectorAll('.cat-pill').forEach(p=>p.classList.remove('active')); | |
| el.classList.add('active'); | |
| selectedCat = el.dataset.cat; | |
| } | |
| function selectCount(el){ | |
| document.querySelectorAll('.count-btn').forEach(b=>b.classList.remove('active')); | |
| el.classList.add('active'); | |
| selectedCount = parseInt(el.dataset.count); | |
| } | |
| function shuffle(arr){ | |
| const a=[...arr]; | |
| for(let i=a.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[a[i],a[j]]=[a[j],a[i]]} | |
| return a; | |
| } | |
| function getDistractors(correctSign, count){ | |
| // Prefer same category, then other categories | |
| const sameCat = signs.filter(s=>s.cat===correctSign.cat && s.id!==correctSign.id); | |
| const otherCat = signs.filter(s=>s.cat!==correctSign.cat); | |
| const shuffledSame = shuffle(sameCat); | |
| const shuffledOther = shuffle(otherCat); | |
| const pool = [...shuffledSame, ...shuffledOther]; | |
| return pool.slice(0, count); | |
| } | |
| function startQuiz(){ | |
| let pool = selectedCat==='all' ? [...signs] : signs.filter(s=>s.cat===selectedCat); | |
| pool = shuffle(pool); | |
| let count = selectedCount===0 ? pool.length : Math.min(selectedCount, pool.length); | |
| questions = pool.slice(0, count); | |
| currentQ = 0; | |
| score = 0; | |
| answered = false; | |
| wrongAnswers = []; | |
| document.getElementById('startScreen').style.display='none'; | |
| document.getElementById('quizScreen').style.display='block'; | |
| document.getElementById('resultScreen').style.display='none'; | |
| showQuestion(); | |
| } | |
| function showQuestion(){ | |
| answered = false; | |
| const q = questions[currentQ]; | |
| const total = questions.length; | |
| document.getElementById('progressBar').style.width = ((currentQ)/total*100)+'%'; | |
| document.getElementById('questionNum').textContent = `${currentQ+1} / ${total}`; | |
| document.getElementById('scoreDisplay').textContent = `${score} pont`; | |
| document.getElementById('signSvg').innerHTML = q.svg; | |
| const catEl = document.getElementById('signCat'); | |
| catEl.textContent = q.catName; | |
| catEl.className = 'sign-category ' + q.cat; | |
| // Build answers: correct + 3 distractors | |
| const distractors = getDistractors(q, 3); | |
| let options = shuffle([q, ...distractors]); | |
| const letters = ['A','B','C','D']; | |
| const div = document.getElementById('answersDiv'); | |
| div.innerHTML = ''; | |
| options.forEach((opt,i) => { | |
| const btn = document.createElement('button'); | |
| btn.className = 'answer-btn'; | |
| btn.innerHTML = `<span class="letter">${letters[i]}</span><span>${opt.name}</span>`; | |
| btn.onclick = () => handleAnswer(btn, opt.id === q.id, q, opt); | |
| div.appendChild(btn); | |
| }); | |
| document.getElementById('nextBtn').classList.remove('visible'); | |
| // Fade in | |
| const card = document.getElementById('signCard'); | |
| card.classList.remove('fade-out'); | |
| card.classList.add('fade-in'); | |
| requestAnimationFrame(()=>{requestAnimationFrame(()=>{card.classList.remove('fade-in')})}); | |
| } | |
| function handleAnswer(btn, isCorrect, question, chosen){ | |
| if(answered) return; | |
| answered = true; | |
| const allBtns = document.querySelectorAll('.answer-btn'); | |
| allBtns.forEach(b => { | |
| b.classList.add('disabled'); | |
| // Reveal correct answer | |
| if(b.querySelector('span:last-child').textContent === question.name){ | |
| b.classList.add('reveal-correct'); | |
| } | |
| }); | |
| if(isCorrect){ | |
| btn.classList.remove('reveal-correct'); | |
| btn.classList.add('correct'); | |
| score++; | |
| document.getElementById('scoreDisplay').textContent = `${score} pont`; | |
| } else { | |
| btn.classList.add('wrong'); | |
| wrongAnswers.push({question, chosenName: chosen.name}); | |
| } | |
| document.getElementById('nextBtn').classList.add('visible'); | |
| } | |
| function nextQuestion(){ | |
| currentQ++; | |
| if(currentQ >= questions.length){ | |
| showResult(); | |
| return; | |
| } | |
| const card = document.getElementById('signCard'); | |
| card.classList.add('fade-out'); | |
| setTimeout(()=>{showQuestion()}, 200); | |
| } | |
| function showResult(){ | |
| document.getElementById('quizScreen').style.display='none'; | |
| document.getElementById('resultScreen').style.display='block'; | |
| const total = questions.length; | |
| const pct = Math.round(score/total*100); | |
| const wrong = total - score; | |
| // Donut | |
| const donut = document.getElementById('donutChart'); | |
| const green = '#16a34a'; | |
| const red = '#ef4444'; | |
| const gray = '#e2e8f0'; | |
| const correctDeg = pct * 3.6; | |
| donut.style.background = `conic-gradient(${green} 0deg ${correctDeg}deg, ${red} ${correctDeg}deg 360deg)`; | |
| if(total===0) donut.style.background = gray; | |
| document.getElementById('pctText').textContent = pct + '%'; | |
| document.getElementById('statCorrect').textContent = score; | |
| document.getElementById('statTotal').textContent = total; | |
| document.getElementById('statWrong').textContent = wrong; | |
| let msg, sub, color; | |
| if(pct >= 90){ msg='Kiváló eredmény!'; sub='Szinte hibátlan, gratulálok!'; color='#16a34a'; } | |
| else if(pct >= 70){ msg='Jó eredmény!'; sub='Még egy kis gyakorlás és tökéletes lesz.'; color='#3b82f6'; } | |
| else if(pct >= 50){ msg='Elfogadható.'; sub='Érdemes átismételni a táblákat.'; color='#f59e0b'; } | |
| else { msg='Gyenge eredmény.'; sub='Több gyakorlásra van szükség!'; color='#ef4444'; } | |
| document.getElementById('resultMsg').textContent = msg; | |
| document.getElementById('resultMsg').style.color = color; | |
| document.getElementById('resultSub').textContent = sub; | |
| document.getElementById('pctText').style.color = color; | |
| // Wrong answers review | |
| const reviewDiv = document.getElementById('wrongReview'); | |
| if(wrongAnswers.length > 0){ | |
| let html = '<h3>Hibás válaszok áttekintése</h3>'; | |
| wrongAnswers.forEach(w => { | |
| html += `<div class="wrong-item"> | |
| ${w.question.svg.replace('viewBox=','style="width:56px;height:56px" viewBox=')} | |
| <div class="wrong-detail"> | |
| <div class="correct-ans">Helyes: ${w.question.name}</div> | |
| <div class="your-ans">Te válaszod: ${w.chosenName}</div> | |
| </div> | |
| </div>`; | |
| }); | |
| reviewDiv.innerHTML = html; | |
| } else { | |
| reviewDiv.innerHTML = '<h3 style="text-align:center;color:#16a34a">Hibátlan! Egyetlen hibás válasz sem volt.</h3>'; | |
| } | |
| // Animate progress bar to 100% | |
| document.getElementById('progressBar').style.width = '100%'; | |
| } | |
| function restartQuiz(){ | |
| document.getElementById('startScreen').style.display='block'; | |
| document.getElementById('quizScreen').style.display='none'; | |
| document.getElementById('resultScreen').style.display='none'; | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment