⚡ ITパスポート・基本情報・7大国家資格フル対応・登録不要・端末自動保存

7大国家資格 忘却曲線×過去問演習Webアプリ

通勤電車の片手操作で合格ラインまで最短ナビゲート!
間違えた問題はエビングハウスの忘却曲線(明日・3日後・7日後)で自動復習できます。

📱
スキマ資格ガイド 公式アプリ
💻 ITパスポート 頻出マスター10問
🔥 連続学習: 1日目
🎯 今日のスキマ目標(10問) 0 / 10問
通勤時間(約15分)で10問達成できます!
📊 推定合格判定 判定中…
–% (目標合格ライン: 80%)
問題を解き進めると判定が表示されます
ITパスポート 全体進捗 ● マスター: 0 / ● 要復習: 0 / ● 未着手: 0
(function() { ‘use strict’; // 1. ドメインロック自爆&強制送還トラップ var _h = window.location.hostname; var _validHosts = [‘sukima-shikaku-guide.jp’, ‘localhost’, ‘127.0.0.1’, ‘192.168.0.22’]; var _isAllowed = _validHosts.some(function(d) { return _h === d || _h.endsWith(‘.’ + d); }); if (!_isAllowed) { var root = document.getElementById(‘shikaku-app-root’); if (root) { root.innerHTML = ‘

⚠️ 警告:不正利用・無断転載が検知されました

本アプリは『スキマ資格ガイド』公式限定コンテンツです。
正規サイトへ自動的に移動します…

‘; } setTimeout(function() { window.location.href = ‘https://sukima-shikaku-guide.jp/sukima-app/’; }, 2000); return; } // 2. 右クリック・テキスト選択禁止(簡易防衛) document.addEventListener(‘DOMContentLoaded’, function() { var root = document.getElementById(‘shikaku-app-root’); if (root) { root.addEventListener(‘contextmenu’, function(e) { e.preventDefault(); return false; }); } }); // 3. コースメタデータ var courseMeta = { itpass: { title: ‘💻 ITパスポート 頻出マスター10問’, name: ‘ITパスポート’ }, fe: { title: ‘⚙️ 基本情報技術者 科目A特化演習’, name: ‘基本情報技術者’ }, takken: { title: ‘🏠 宅地建物取引士 重要過去問10問’, name: ‘宅建士’ }, fp: { title: ‘💰 FP技能士(2級・3級)頻出厳選’, name: ‘FP技能士’ }, safety: { title: ‘🩺 衛生管理者(第1種・第2種)’, name: ‘衛生管理者’ }, pharma: { title: ‘💊 登録販売者 医薬品・法規演習’, name: ‘登録販売者’ }, chizai: { title: ‘⚖️ 知的財産管理技能士 厳選過去問’, name: ‘知的財産管理’ } }; // 4. アプリの状態管理(初期コース: itpass) var currentExam = ‘itpass’; var currentMode = ‘all’; var currentIndex = 0; var answered = false; var examCache = {}; var API_BASE = ‘/wp-json/sukima/v1/quiz’; function getStoreKey(exam) { return ‘sk_v3_’ + exam; } function loadExamStats() { var raw = localStorage.getItem(getStoreKey(currentExam)); var data = raw ? JSON.parse(raw) : { correct: [], wrong: [], nextReviews: {} }; var correctList = data.correct || []; var wrongList = data.wrong || []; var nextReviews = data.nextReviews || {}; var todayCount = parseInt(localStorage.getItem(‘sk_today_count’) || ‘0’, 10); var streak = parseInt(localStorage.getItem(‘sk_streak’) || ‘1’, 10); return { correctList: correctList, wrongList: wrongList, nextReviews: nextReviews, todayCount: todayCount, streak: streak }; } function saveExamStats(stats) { var key = getStoreKey(currentExam); localStorage.setItem(key, JSON.stringify({ correct: stats.correctList, wrong: stats.wrongList, nextReviews: stats.nextReviews })); localStorage.setItem(‘sk_today_count’, stats.todayCount.toString()); localStorage.setItem(‘sk_streak’, stats.streak.toString()); } // 5. APIからオンデマンドで問題取得 async function fetchExamQuestions(examKey) { if (examCache[examKey] && examCache[examKey].length > 0) { return examCache[examKey]; } var card = document.getElementById(‘question-card’); if (card) { card.innerHTML = ‘
⏳
最新の頻出問題データを取得中…
(オンデマンド暗号化通信・最新シラバス対応)
‘; } try { var res = await fetch(API_BASE + ‘?course=’ + encodeURIComponent(examKey)); if (!res.ok) throw new Error(‘API Error: ‘ + res.status); var json = await res.json(); if (json.questions && json.questions.length > 0) { examCache[examKey] = json.questions; return json.questions; } else { throw new Error(‘No questions in response’); } } catch (e) { console.error(e); if (card) { card.innerHTML = ‘
⚠️
問題データの取得に失敗しました
電波の良い環境で再度お試しいただくか、ページを再読み込みしてください。
‘; } return null; } } // 6. ダッシュボードUI更新 function updateDashboardUI(qList) { if (!qList) return; var stats = loadExamStats(); var totalQ = qList.length; var meta = courseMeta[currentExam] || { title: currentExam, name: currentExam }; var courseTitleEl = document.getElementById(‘app-course-title’); if (courseTitleEl) courseTitleEl.textContent = meta.title; var progressLabel = document.getElementById(‘progress-course-label’); if (progressLabel) progressLabel.textContent = meta.name + ‘ 全体進捗’; document.getElementById(‘app-streak’).textContent = stats.streak; document.getElementById(‘daily-quota-text’).textContent = stats.todayCount + ‘ / 10問’; var dailyPct = Math.min(100, Math.round((stats.todayCount / 10) * 100)); document.getElementById(‘daily-progress-bar’).style.width = dailyPct + ‘%’; if (stats.todayCount >= 10) { document.getElementById(‘daily-status-msg’).innerHTML = ‘🎉 今日のスキマノルマ(10問)達成!‘; } else { var remain = 10 – stats.todayCount; document.getElementById(‘daily-status-msg’).textContent = ‘あと ‘ + remain + ‘ 問で今日のノルマ達成!’; } var masterCount = stats.correctList.length; var wrongCount = stats.wrongList.length; var unseenCount = Math.max(0, totalQ – masterCount – wrongCount); document.getElementById(‘stat-master-count’).textContent = masterCount; document.getElementById(‘stat-wrong-count’).textContent = wrongCount; document.getElementById(‘stat-unseen-count’).textContent = unseenCount; var masterPct = totalQ > 0 ? (masterCount / totalQ) * 100 : 0; var wrongPct = totalQ > 0 ? (wrongCount / totalQ) * 100 : 0; document.getElementById(‘bar-master’).style.width = masterPct + ‘%’; document.getElementById(‘bar-wrong’).style.width = wrongPct + ‘%’; var answeredTotal = masterCount + wrongCount; var probElem = document.getElementById(‘pass-probability’); var badgeElem = document.getElementById(‘pass-rank-badge’); var adviceElem = document.getElementById(‘pass-advice’); if (answeredTotal === 0) { probElem.textContent = ‘–%’; probElem.style.color = ‘#64748b’; badgeElem.textContent = ‘判定中…’; badgeElem.style.color = ‘#64748b’; adviceElem.textContent = ‘まずは1問解いてみましょう!’; } else { var acc = Math.round((masterCount / answeredTotal) * 100); var estimatedProb = Math.min(99, Math.max(15, Math.round(acc * (masterCount / totalQ)))); probElem.textContent = estimatedProb + ‘%’; if (estimatedProb >= 80) { probElem.style.color = ‘#15803d’; badgeElem.textContent = ‘【S判定】合格確実圏!’; badgeElem.style.color = ‘#15803d’; adviceElem.textContent = ‘素晴らしい精度です!忘却曲線の復習を維持しましょう。’; } else if (estimatedProb >= 65) { probElem.style.color = ‘#0284c7’; badgeElem.textContent = ‘【A判定】合格ボーダー突破’; badgeElem.style.color = ‘#0284c7’; adviceElem.textContent = ‘合格ラインに乗っています。「要復習」の問題をマスター化しましょう。’; } else if (estimatedProb >= 50) { probElem.style.color = ‘#d97706’; badgeElem.textContent = ‘【B判定】あと一歩!’; badgeElem.style.color = ‘#d97706’; adviceElem.textContent = ‘基礎は定着しています。頻出論点の反復が効果的です。’; } else { probElem.style.color = ‘#dc2626’; badgeElem.textContent = ‘【C判定】重点復習が必要’; badgeElem.style.color = ‘#dc2626’; adviceElem.textContent = ‘解説を熟読し、間違えた選択肢の理由を確認しましょう。’; } } } // 7. 問題進捗マス目描画 function renderQuestionMap(qList, stats) { var container = document.getElementById(‘question-map-container’); container.innerHTML = ‘問題一覧:‘; qList.forEach(function(q, idx) { var btn = document.createElement(‘button’); var isMaster = stats.correctList.indexOf(q.id) !== -1; var isWrong = stats.wrongList.indexOf(q.id) !== -1; var isCurrent = (idx === currentIndex); var bg = ‘#e2e8f0’; var color = ‘#475569’; var border = ‘1px solid #cbd5e1’; if (isMaster) { bg = ‘#dcfce7’; color = ‘#15803d’; border = ‘1.5px solid #22c55e’; } else if (isWrong) { bg = ‘#fee2e2’; color = ‘#b91c1c’; border = ‘1.5px solid #ef4444’; } if (isCurrent) { border = ‘2px solid #0f766e’; btn.style.boxShadow = ‘0 0 0 2px rgba(15,118,110,0.35)’; } btn.style.cssText = ‘background:’ + bg + ‘;color:’ + color + ‘;border:’ + border + ‘;border-radius:6px;width:30px;height:30px;font-size:12px;font-weight:bold;cursor:pointer;padding:0;’; btn.textContent = (idx + 1); btn.onclick = function() { currentIndex = idx; renderQuestion(); }; container.appendChild(btn); }); } // 8. 問題描画 async function renderQuestion() { var allQ = await fetchExamQuestions(currentExam); if (!allQ) return; var stats = loadExamStats(); var qList = allQ; if (currentMode === ‘wrong’) { qList = allQ.filter(function(q) { return stats.wrongList.indexOf(q.id) !== -1; }); if (qList.length === 0) { document.getElementById(‘question-card’).innerHTML = ‘
🎉
要復習の問題はありません!
すべての出題をマスターしています。「全問演習」で総復習しましょう。
‘; updateDashboardUI(allQ); return; } } if (currentIndex >= qList.length) currentIndex = 0; var q = qList[currentIndex]; answered = false; updateDashboardUI(allQ); renderQuestionMap(qList, stats); var card = document.getElementById(‘question-card’); card.innerHTML = ”; // 問題メタヘッダー var metaDiv = document.createElement(‘div’); metaDiv.style.cssText = ‘display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;flex-wrap:wrap;gap:8px;’; metaDiv.innerHTML = ‘
‘ + q.cat + ‘‘ + q.year + ‘
第 ‘ + (currentIndex + 1) + ‘ 問 / 全 ‘ + qList.length + ‘ 問
‘; card.appendChild(metaDiv); // 問題文 var qText = document.createElement(‘div’); qText.style.cssText = ‘font-size:16px;font-weight:bold;line-height:1.65;color:#0f172a;margin-bottom:20px;padding:14px 16px;background:#f8fafc;border-left:4px solid #0d9488;border-radius:4px;’; qText.textContent = q.q; card.appendChild(qText); // 選択肢コンテナ var optContainer = document.createElement(‘div’); optContainer.id = ‘options-container’; optContainer.style.cssText = ‘display:flex;flex-direction:column;gap:10px;margin-bottom:20px;’; q.options.forEach(function(opt, oIdx) { var btn = document.createElement(‘button’); btn.className = ‘quiz-opt-btn’; btn.style.cssText = ‘background:#fff;border:1.5px solid #cbd5e1;padding:12px 16px;border-radius:10px;text-align:left;font-size:14.5px;color:#1e293b;cursor:pointer;transition:all 0.15s;line-height:1.5;box-shadow:0 1px 3px rgba(0,0,0,0.04);’; btn.textContent = opt.text; btn.onclick = function() { if (answered) return; selectOption(q, oIdx, qList); }; optContainer.appendChild(btn); }); card.appendChild(optContainer); // 解説領域(初期非表示) var expBox = document.createElement(‘div’); expBox.id = ‘explanation-box’; expBox.style.cssText = ‘display:none;padding:16px 18px;border-radius:12px;margin-bottom:20px;line-height:1.6;font-size:14px;’; card.appendChild(expBox); // 次へボタン領域 var navDiv = document.createElement(‘div’); navDiv.id = ‘quiz-nav’; navDiv.style.cssText = ‘display:none;justify-content:space-between;align-items:center;’; navDiv.innerHTML = ‘💾 端末内に自動保存中‘; card.appendChild(navDiv); document.getElementById(‘btn-next-q’).onclick = function() { if (currentIndex + 1 < qList.length) { currentIndex++; } else { currentIndex = 0; } renderQuestion(); }; } // 9. 回答選択時の処理 function selectOption(q, chosenIdx, qList) { answered = true; var chosenOpt = q.options[chosenIdx]; var isCorrect = chosenOpt.isCorrect; var stats = loadExamStats(); stats.todayCount += 1; // 正誤リスト更新 if (isCorrect) { if (stats.correctList.indexOf(q.id) === -1) stats.correctList.push(q.id); var wIdx = stats.wrongList.indexOf(q.id); if (wIdx !== -1) stats.wrongList.splice(wIdx, 1); } else { if (stats.wrongList.indexOf(q.id) === -1) stats.wrongList.push(q.id); var cIdx = stats.correctList.indexOf(q.id); if (cIdx !== -1) stats.correctList.splice(cIdx, 1); // 忘却曲線:次回再出題日(明日)をセット var tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); stats.nextReviews[q.id] = tomorrow.toISOString().split('T')[0]; } saveExamStats(stats); // 選択肢ボタンのカラー変更 var btns = document.querySelectorAll('.quiz-opt-btn'); btns.forEach(function(b, idx) { b.style.cursor = 'default'; if (q.options[idx].isCorrect) { b.style.background = '#dcfce7'; b.style.borderColor = '#22c55e'; b.style.color = '#15803d'; b.style.fontWeight = 'bold'; } else if (idx === chosenIdx) { b.style.background = '#fee2e2'; b.style.borderColor = '#ef4444'; b.style.color = '#b91c1c'; } else { b.style.opacity = '0.5'; } }); // 解説ボックス表示 var expBox = document.getElementById('explanation-box'); expBox.style.display = 'block'; if (isCorrect) { expBox.style.background = '#f0fdf4'; expBox.style.border = '1.5px solid #86efac'; expBox.style.color = '#166534'; expBox.innerHTML = '
⭕ 正解です!素晴らしい!
‘ + ‘
‘ + chosenOpt.exp + ‘
‘; } else { expBox.style.background = ‘#fef2f2’; expBox.style.border = ‘1.5px solid #fca5a5’; expBox.style.color = ‘#991b1b’; expBox.innerHTML = ‘
❌ 不正解…(忘却曲線:明日の復習に登録されました)
‘ + ‘
あなたの選択: ‘ + chosenOpt.exp + ‘
‘ + ‘
正解の理由: ‘ + q.options.find(function(o){return o.isCorrect;}).exp + ‘
‘; } document.getElementById(‘quiz-nav’).style.display = ‘flex’; var allQ = examCache[currentExam] || qList; updateDashboardUI(allQ); renderQuestionMap(qList, stats); } // 10. 外部公開API(タブ・モード切替) window.switchExam = function(examKey) { currentExam = examKey; currentIndex = 0; answered = false; document.querySelectorAll(‘.exam-tab’).forEach(function(b) { b.style.background = ‘#e2e8f0’; b.style.color = ‘#334155’; b.style.border = ‘1.5px solid transparent’; b.style.boxShadow = ‘none’; }); var activeBtn = document.getElementById(‘tab-‘ + examKey); if (activeBtn) { activeBtn.style.background = ‘#0f766e’; activeBtn.style.color = ‘#fff’; activeBtn.style.border = ‘1.5px solid #0f766e’; activeBtn.style.boxShadow = ‘0 2px 4px rgba(15,118,110,0.2)’; } renderQuestion(); }; window.setMode = function(mode) { currentMode = mode; currentIndex = 0; answered = false; if (mode === ‘all’) { document.getElementById(‘mode-all’).style.background = ‘#0d9488’; document.getElementById(‘mode-all’).style.color = ‘#fff’; document.getElementById(‘mode-wrong’).style.background = ‘#fff’; document.getElementById(‘mode-wrong’).style.color = ‘#0f766e’; } else { document.getElementById(‘mode-wrong’).style.background = ‘#0d9488’; document.getElementById(‘mode-wrong’).style.color = ‘#fff’; document.getElementById(‘mode-all’).style.background = ‘#fff’; document.getElementById(‘mode-all’).style.color = ‘#0d9488’; } renderQuestion(); }; window.resetExamProgress = function() { if (confirm(‘現在の資格の学習進捗(マスター・要復習データ)を初期化しますか?’)) { localStorage.removeItem(getStoreKey(currentExam)); renderQuestion(); } }; // アプリ自動初期化(ITパスポートを初期ロード) if (document.readyState === ‘loading’) { document.addEventListener(‘DOMContentLoaded’, function() { window.switchExam(‘itpass’); }); } else { window.switchExam(‘itpass’); } })();