Re: B-089調査依頼: ことわざ・慣用句クイズ追加のための基盤調査
B-089 調査レポート: ことわざ・慣用句クイズ追加のための基盤調査
1. 既存クイズ基盤の構造
1-1. ディレクトリ構成
クイズ機能は以下のディレクトリに格納されている。
src/quiz/
types.ts # 型定義 (QuizDefinition, QuizMeta, QuizQuestion, QuizChoice, QuizResult, QuizAnswer, QuizPhase, QuizType)
registry.ts # レジストリ (quizBySlug, allQuizMetas, getAllQuizSlugs, getResultIdsForQuiz)
scoring.ts # スコアリング (calculateKnowledgeScore, calculatePersonalityPoints, determineResult, isCorrectChoice)
__tests__/
registry.test.ts # レジストリのデータ整合性テスト
scoring.test.ts # スコアリングロジックのテスト
_components/
QuizContainer.tsx # クライアントコンポーネント。intro -> playing -> result のライフサイクル管理
QuizContainer.module.css
QuestionCard.tsx # 問題表示。knowledge型は正誤フィードバック+「次へ」ボタン、personality型は即遷移
QuestionCard.module.css
ResultCard.tsx # 結果表示+シェアボタン+「もう一度挑戦する」
ResultCard.module.css
ProgressBar.tsx # 進捗バー (current/total)
ProgressBar.module.css
ShareButtons.tsx # X, LINE, コピー, Web Share API
ShareButtons.module.css
data/
kanji-level.ts # 漢字力診断 (knowledge, 10問, 4択, 5結果)
yoji-level.ts # 四字熟語力診断 (knowledge, 10問, 4択, 5結果)
traditional-color.ts # 伝統色性格診断 (personality, 8問, 4択, 8結果)
yoji-personality.ts # 四字熟語性格診断 (personality, 8問, 4択, 8結果)
ルーティング:
src/app/quiz/
page.tsx # クイズ一覧ページ (allQuizMetas をループ表示)
page.module.css
layout.tsx # 空レイアウト (<>{children}</>)
__tests__/page.test.tsx # 一覧ページのテスト
[slug]/
page.tsx # 個別クイズページ (generateStaticParams + QuizContainer)
page.module.css
opengraph-image.tsx # OGP画像生成 (slug -> quiz.meta から icon, title, accentColor, shortDescription)
result/[resultId]/
page.tsx # 結果共有ページ (generateStaticParams で全組み合わせ生成)
page.module.css
opengraph-image.tsx # 結果OGP画像 (quiz title, result icon, result title)
1-2. レジストリパターンの仕組み
registry.ts は非常にシンプルなパターン:
- 各データファイルから QuizDefinition をインポート
- quizEntries 配列にすべて登録
- Map (quizBySlug) と配列 (allQuizMetas) をエクスポート
- ヘルパー関数 (getAllQuizSlugs, getResultIdsForQuiz) を提供
新テーマの追加は以下の2ステップのみで完了する:
- (a)
src/quiz/data/に新しいデータファイルを作成 - (b)
src/quiz/registry.tsの import と quizEntries 配列に1行ずつ追加
これだけで、ルーティング、OGP画像、サイトマップ、検索インデックス、ホームページのクイズ一覧、ヘッダー/フッターのリンクすべてに自動的に反映される。
1-3. 型定義の詳細
type QuizType = "knowledge" | "personality";
type QuizChoice = {
id: string; // "q1-a" 形式
text: string;
points?: Record<string, number>; // personality型用
isCorrect?: boolean; // knowledge型用
};
type QuizQuestion = {
id: string; // "q1" 形式
text: string;
choices: QuizChoice[];
explanation?: string; // knowledge型用。回答後に表示される解説
};
type QuizResult = {
id: string; // URL安全なID (例: "master", "beginner")
title: string;
description: string;
color?: string; // personality型用テーマカラー
icon?: string; // 絵文字アイコン
minScore?: number; // knowledge型用。この結果に必要な最小スコア
recommendation?: string; // おすすめテキスト
recommendationLink?: string; // おすすめリンクURL
};
type QuizMeta = {
slug: string; // URL用スラッグ
title: string;
description: string; // メタディスクリプション用
shortDescription: string; // カード表示用
type: QuizType;
questionCount: number; // questions.length と一致必須
icon: string; // 絵文字アイコン
accentColor: string; // テーマカラー (hex)
keywords: string[]; // SEOキーワード
publishedAt: string; // 公開日 (YYYY-MM-DD)
relatedLinks?: Array<{ label: string; href: string }>;
};
1-4. 自動統合ポイント
以下のファイルはレジストリから自動的にデータを取得するため、新テーマ追加時の個別変更は不要:
src/app/sitemap.ts- getAllQuizSlugs(), getResultIdsForQuiz() を使用src/lib/search/build-index.ts- allQuizMetas を使用src/app/page.tsx(ホームページ) - allQuizMetas を使用src/app/quiz/page.tsx(一覧) - allQuizMetas を使用src/app/quiz/[slug]/page.tsx- generateStaticParams() が自動src/app/quiz/[slug]/opengraph-image.tsx- 自動src/app/quiz/[slug]/result/[resultId]/page.tsx- 自動src/app/quiz/[slug]/result/[resultId]/opengraph-image.tsx- 自動src/lib/seo.ts- generateQuizMetadata(), generateQuizJsonLd() がmeta型で動作src/components/common/Header.tsx- /quiz へのリンク (変更不要)src/components/common/Footer.tsx- /quiz へのリンク (変更不要)
2. 既存クイズのデータ設計
2-1. データ量の比較
| クイズ | type | 問題数 | 選択肢数 | 結果パターン | explanation |
|---|---|---|---|---|---|
| 漢字力診断 | knowledge | 10 | 4 | 5 (minScore: 0,3,5,7,9) | あり |
| 四字熟語力診断 | knowledge | 10 | 4 | 5 (minScore: 0,3,5,7,9) | あり |
| 伝統色性格診断 | personality | 8 | 4 | 8 | なし |
| 四字熟語性格診断 | personality | 8 | 4 | 8 | なし |
2-2. 出題形式
knowledge型では以下のパターンが使われている:
- 意味→語: 「〜を表す四字熟語は?」(四字熟語力診断)
- 語→読み: 「〜の読みは?」(漢字力診断)
personality型:
- 状況に対する回答選択: 「休日の過ごし方は?」「困難に直面したとき、あなたはどうする?」など
2-3. 難易度の分け方
knowledge型の結果は minScore で段階的に分かれている:
- 5段階 (0, 3, 5, 7, 9 正解)
- 段階名: ビギナー → 見習い/卵 → 中級者 → 上級者 → マスター
3. コンテンツの範囲: ことわざ・慣用句クイズ
3-1. ことわざと慣用句の定義と違い
ことわざ: 昔から人々の間で言い伝えられてきた言葉。生活の知恵や教訓を短く表現したもの。単体で完結する文として使える。例:「猿も木から落ちる」「石橋を叩いて渡る」
慣用句: 2つ以上の言葉が結びついて、元の言葉とは異なる特定の意味を表す表現。気持ちや動作を表現する決まり文句。文中に組み込んで使う。例:「腹が立つ」「目が高い」「足を引っ張る」
主な違い:
- ことわざは教訓・知恵を含む完結した文。慣用句は表現の豊かさに重点を置いた句。
- ことわざは独立して使える。慣用句は前後の文脈が必要な場合が多い。
- 両者の境界は曖昧で重複するものもある (例:「壁に耳あり障子に目あり」)。
3-2. クイズとして成立しやすい形式の検討
既存の人気クイズサイトの調査から、以下の形式が有効:
(A) 穴埋め形式 (推奨)
- 「猿も木から〇〇〇」→「落ちる」を選ぶ
- 「〇〇に耳あり障子に目あり」→「壁」を選ぶ
- ことわざの認知度が高くても穴埋めにすると適度な難易度になる
- 既存の四択UIと完全に互換
(B) 意味→ことわざ形式
- 「上手な人でも時には失敗するという意味のことわざは?」→「猿も木から落ちる」
- 四字熟語力診断と同じパターンで実装が容易
(C) ことわざ→意味形式
- 「『石の上にも三年』の意味は?」→ 正しい意味を選ぶ
- 漢字力診断の読み当てと同じパターン
推奨: knowledge型で、(B)意味→ことわざ形式を中心に、一部(A)穴埋め形式を混ぜると変化があって良い。ただし既存UIの制約 (question.text が1行のテキスト) を考慮すると、(B) が最もシンプルに実装できる。穴埋め形式も question.text に「〇〇に入る言葉は?」と書けば現行UIで対応可能。
3-3. 問題数・結果パターンの目安
既存パターンに合わせて:
- 問題数: 10問 (knowledge型の標準)
- 選択肢数: 4択
- 結果パターン: 5段階 (minScore: 0, 3, 5, 7, 9)
- explanation: あり (ことわざの由来や意味を解説)
3-4. ことわざと慣用句を分けるか1つにまとめるか
推奨: 1つのクイズにまとめる
理由:
- 両者の境界が曖昧であり、「ことわざ・慣用句」として1つにまとめるのが自然
- 10問の中で、ことわざ6-7問 + 慣用句3-4問程度の混合が適切
- 分けると問題数が足りなくなるか、難易度の幅が狭くなるリスクがある
- 四字熟語力診断 (knowledge型) と対をなすテーマとして「ことわざ・慣用句力診断」が分かりやすい
4. 新テーマ追加に必要な変更点の一覧
4-1. 必須の変更 (2ファイル)
| # | ファイル | 変更内容 |
|---|---|---|
| 1 | src/quiz/data/kotowaza-level.ts (新規) |
QuizDefinition を作成。meta (slug: "kotowaza-level"), questions (10問), results (5段階) |
| 2 | src/quiz/registry.ts |
import 1行追加 + quizEntries 配列に1行追加 |
4-2. 自動的に反映されるもの (変更不要)
| 対象 | ファイル | 理由 |
|---|---|---|
| ルーティング | src/app/quiz/[slug]/page.tsx |
generateStaticParams()がregistry経由で自動取得 |
| 結果ページ | src/app/quiz/[slug]/result/[resultId]/page.tsx |
同上 |
| OGP画像 (クイズ) | src/app/quiz/[slug]/opengraph-image.tsx |
同上 |
| OGP画像 (結果) | src/app/quiz/[slug]/result/[resultId]/opengraph-image.tsx |
同上 |
| サイトマップ | src/app/sitemap.ts |
getAllQuizSlugs()経由で自動 |
| 検索インデックス | src/lib/search/build-index.ts |
allQuizMetas経由で自動 |
| クイズ一覧ページ | src/app/quiz/page.tsx |
allQuizMetas経由で自動 |
| ホームページ | src/app/page.tsx |
allQuizMetas経由で自動 |
| SEO (metadata) | src/lib/seo.ts |
generateQuizMetadata()がQuizMeta型で動作 |
| SEO (JSON-LD) | src/lib/seo.ts |
generateQuizJsonLd()がQuizMeta型で動作 |
| ヘッダー/フッター | Header.tsx / Footer.tsx | /quiz へのリンクは変更不要 |
4-3. テストで確認すべき項目
既存テストが自動的にカバーする:
| テスト | ファイル | カバー内容 |
|---|---|---|
| レジストリ整合性 | src/quiz/__tests__/registry.test.ts |
meta必須フィールド, questionCount一致, result ID一意性, question ID一意性, choice ID一意性, knowledge型の正解が1つ, minScore定義 |
| 一覧ページ | src/app/quiz/__tests__/page.test.tsx |
新クイズのタイトルが表示されることの確認が必要 (テストの更新が必要) |
| 検索インデックス | src/lib/search/__tests__/build-index.test.ts |
quiz型のドキュメントが含まれることは自動確認 |
注意: src/app/quiz/__tests__/page.test.tsx は現在ハードコードで4つのクイズタイトルを確認している。新クイズ追加時にこのテストを更新するか、動的な検証に書き換える必要がある。
4-4. データファイルの設計テンプレート
// src/quiz/data/kotowaza-level.ts
import type { QuizDefinition } from "../types";
const kotowazaLevelQuiz: QuizDefinition = {
meta: {
slug: "kotowaza-level",
title: "ことわざ・慣用句力診断",
description: "ことわざや慣用句の意味から正しい表現を当てるクイズです。全10問であなたのことわざ力を診断します。...",
shortDescription: "ことわざ・慣用句10問であなたの語彙力を測定",
type: "knowledge",
questionCount: 10,
icon: "📜", // または "諺" のような漢字1文字
accentColor: "#...", // 既存と被らない色を選定
keywords: ["ことわざ", "慣用句", "クイズ", "診断", "語彙力", "テスト", "意味"],
publishedAt: "2026-02-26",
relatedLinks: [
// 関連する辞典やゲームへのリンク (あれば)
],
},
questions: [
{
id: "q1",
text: "「上手な人でも時には失敗する」という意味のことわざは?",
choices: [
{ id: "q1-a", text: "猿も木から落ちる", isCorrect: true },
{ id: "q1-b", text: "犬も歩けば棒に当たる" },
{ id: "q1-c", text: "馬の耳に念仏" },
{ id: "q1-d", text: "豚に真珠" },
],
explanation: "「猿も木から落ちる」は、木登りが得意な猿でも時には落ちることがあるということから、...",
},
// ... q2-q10
],
results: [
{ id: "beginner", title: "ことわざビギナー", description: "...", icon: "🌱", minScore: 0, ... },
{ id: "learner", title: "ことわざ見習い", description: "...", icon: "📝", minScore: 3, ... },
{ id: "intermediate", title: "ことわざ中級者", description: "...", icon: "📖", minScore: 5, ... },
{ id: "advanced", title: "ことわざ上級者", description: "...", icon: "🎓", minScore: 7, ... },
{ id: "master", title: "ことわざマスター", description: "...", icon: "👑", minScore: 9, ... },
],
};
export default kotowazaLevelQuiz;
4-5. accentColor の選定
既存クイズで使用されている色:
- 漢字力診断: #2563eb (青)
- 伝統色診断: #0d5661 (深緑)
- 四字熟語力診断: #7c3aed (紫)
- 四字熟語性格診断: #b91c1c (赤)
推奨: #d97706 (琥珀/amber系) や #0d9488 (teal系) など、既存と被らない色。
5. 問題コンテンツの方向性
5-1. 難易度バランスの目安
10問中:
- 易しい (3-4問): 「猿も木から落ちる」「石橋を叩いて渡る」「花より団子」など誰もが知る有名なもの
- 普通 (3-4問): 「灯台下暗し」「二階から目薬」「足元を見る」など日常で使われるが少し考えるもの
- 難しい (2-3問): 「烏合の衆」「糠に釘」「河童の川流れ」など知識が試されるもの
5-2. 出題テーマの多様性
動物のことわざ、体の部位の慣用句、自然に関することわざなど、テーマを偏らせず多様に出題すると良い。
5-3. explanation (解説) の品質
既存クイズの解説パターン:
- 読み方 (漢字クイズ) / 語源・由来 (四字熟語クイズ)
- 50-100文字程度
- ことわざクイズでは: 語源・由来、使い方の例、類似表現の紹介などを含めると教育的価値が高い
6. まとめ
既存のクイズ基盤は非常によく設計されたレジストリパターンにより、新テーマの追加コストは極めて低い。必須の変更は2ファイル (データファイルの新規作成 + registry.tsへの2行追加) のみ。残りはすべて自動統合される。
主な作業は問題コンテンツの作成であり、以下が推奨仕様:
- slug: "kotowaza-level"
- type: "knowledge" (知識テスト)
- 10問 / 4択 / 解説付き
- 5段階結果 (minScore: 0, 3, 5, 7, 9)
- ことわざと慣用句を混合 (ことわざ6-7問 + 慣用句3-4問)
- 出題形式: 意味→ことわざ/慣用句 (四字熟語力診断と同パターン)
- 難易度: 易3-4問 / 普通3-4問 / 難2-3問
テストについては、page.test.tsx のハードコードされたタイトル確認に新クイズのタイトルを追加する必要がある点に留意。