ChoTensai_V3 / docs /GenreMaster.js
TOMOCHIN4
fix: getSessionResults カラムインデックス修正 (v1.6.10)
d6a42d4
/**
* ジャンルマスターデータ
*
* 中学受験4教科のジャンル分類を定義
*
* @version 1.0.0
* @date 2025-12-07
*/
// ============================================================================
// ジャンルマスターデータ
// ============================================================================
/**
* 中学受験4教科のジャンル分類マスターデータ
* @constant {Object}
*/
var GENRE_MASTER = {
// 国語(8ジャンル)
jp: {
subject_id: 'jp',
subject_name: '国語',
genres: [
{
id: 'JP01',
name: '漢字・語彙',
description: '読み書き、四字熟語、慣用句、ことわざ'
},
{
id: 'JP02',
name: '文法・言葉のきまり',
description: '品詞、敬語、文の成分、修飾関係'
},
{
id: 'JP03',
name: '物語文読解',
description: '心情理解、場面把握、人物関係'
},
{
id: 'JP04',
name: '説明文・論説文読解',
description: '要旨、段落構成、筆者の主張'
},
{
id: 'JP05',
name: '随筆文読解',
description: '筆者の体験・感想の読み取り'
},
{
id: 'JP06',
name: '詩・韻文',
description: '詩、短歌、俳句、表現技法'
},
{
id: 'JP07',
name: '記述問題',
description: '理由説明、要約、意見記述'
},
{
id: 'JP08',
name: '知識・文学史',
description: '作家、作品名、文学的常識'
}
]
},
// 算数(10ジャンル)
math: {
subject_id: 'math',
subject_name: '算数',
genres: [
{
id: 'MA01',
name: '計算',
description: '四則演算、分数・小数、逆算'
},
{
id: 'MA02',
name: '数の性質',
description: '約数・倍数、素因数分解、規則性'
},
{
id: 'MA03',
name: '割合・比',
description: '割合、比、百分率、歩合'
},
{
id: 'MA04',
name: '速さ',
description: '旅人算、通過算、流水算、時計算'
},
{
id: 'MA05',
name: '文章題(その他)',
description: '濃度、仕事算、ニュートン算、差集め算'
},
{
id: 'MA06',
name: '平面図形',
description: '面積、角度、相似、合同'
},
{
id: 'MA07',
name: '立体図形',
description: '体積、表面積、展開図、切断'
},
{
id: 'MA08',
name: '場合の数・確率',
description: '順列、組み合わせ、確率'
},
{
id: 'MA09',
name: 'グラフ・表',
description: '統計、変化のグラフ、ダイヤグラム'
},
{
id: 'MA10',
name: '特殊算',
description: 'つるかめ算、消去算、過不足算'
}
]
},
// 理科(12ジャンル)
sci: {
subject_id: 'sci',
subject_name: '理科',
genres: [
{
id: 'SC01',
name: '力・運動',
description: 'てこ、滑車、ばね、浮力、振り子'
},
{
id: 'SC02',
name: '電気',
description: '回路、抵抗、電磁石、発熱'
},
{
id: 'SC03',
name: '光・音・熱',
description: '反射、屈折、レンズ、音の性質'
},
{
id: 'SC04',
name: '物質の性質',
description: '金属、気体、密度、状態変化'
},
{
id: 'SC05',
name: '水溶液',
description: '酸・アルカリ、中和、溶解度'
},
{
id: 'SC06',
name: '燃焼・化学変化',
description: '燃焼、酸化還元、化合'
},
{
id: 'SC07',
name: '植物',
description: 'つくり、光合成、蒸散、分類'
},
{
id: 'SC08',
name: '動物',
description: 'からだのつくり、行動、分類'
},
{
id: 'SC09',
name: '人体',
description: '消化、呼吸、血液循環、感覚器官'
},
{
id: 'SC10',
name: '天体',
description: '太陽、月、星座、地球の運動'
},
{
id: 'SC11',
name: '気象',
description: '天気、気温、湿度、雲、季節風'
},
{
id: 'SC12',
name: '地学',
description: '地層、岩石、火山、地震'
}
]
},
// 社会(10ジャンル)
soc: {
subject_id: 'soc',
subject_name: '社会',
genres: [
{
id: 'SO01',
name: '日本地理(国土・自然)',
description: '地形、気候、都道府県'
},
{
id: 'SO02',
name: '日本地理(産業)',
description: '農業、工業、水産業、商業'
},
{
id: 'SO03',
name: '世界地理',
description: '大陸、国、貿易、環境問題'
},
{
id: 'SO04',
name: '歴史(古代〜平安)',
description: '旧石器〜平安時代'
},
{
id: 'SO05',
name: '歴史(鎌倉〜室町)',
description: '武士の台頭、文化'
},
{
id: 'SO06',
name: '歴史(安土桃山〜江戸)',
description: '統一、鎖国、元禄・化政文化'
},
{
id: 'SO07',
name: '歴史(明治〜現代)',
description: '近代化、戦争、戦後'
},
{
id: 'SO08',
name: '公民(政治・憲法)',
description: '三権分立、選挙、人権'
},
{
id: 'SO09',
name: '公民(経済・国際)',
description: '経済の仕組み、国際機関、SDGs'
},
{
id: 'SO10',
name: '時事問題',
description: '直近1〜2年のニュース'
}
]
}
};
// ============================================================================
// ヘルパー関数
// ============================================================================
/**
* ジャンルIDからジャンル情報を取得
*
* @param {string} genreId - ジャンルID(例: 'JP01', 'MA05')
* @returns {Object|null} - ジャンル情報 { id, name, description, subject_id, subject_name } または null
*
* @example
* var genre = getGenreById('JP01');
* // => { id: 'JP01', name: '漢字・語彙', description: '...', subject_id: 'jp', subject_name: '国語' }
*/
function getGenreById(genreId) {
if (!genreId || typeof genreId !== 'string') {
return null;
}
var upperGenreId = genreId.toUpperCase();
// 全教科を検索
var subjects = ['jp', 'math', 'sci', 'soc'];
for (var i = 0; i < subjects.length; i++) {
var subjectId = subjects[i];
var subjectData = GENRE_MASTER[subjectId];
var genres = subjectData.genres;
for (var j = 0; j < genres.length; j++) {
var genre = genres[j];
if (genre.id === upperGenreId) {
// ジャンル情報に教科情報を追加して返却
return {
id: genre.id,
name: genre.name,
description: genre.description,
subject_id: subjectData.subject_id,
subject_name: subjectData.subject_name
};
}
}
}
return null;
}
/**
* 教科のジャンル一覧を取得
*
* @param {string} subjectId - 教科ID(jp, math, sci, soc)
* @returns {Array} - ジャンル配列(見つからない場合は空配列)
*
* @example
* var genres = getGenresBySubject('jp');
* // => [{ id: 'JP01', name: '漢字・語彙', ... }, ...]
*/
function getGenresBySubject(subjectId) {
if (!subjectId || typeof subjectId !== 'string') {
return [];
}
var subjectData = GENRE_MASTER[subjectId.toLowerCase()];
if (!subjectData) {
return [];
}
return subjectData.genres;
}
/**
* 全ジャンル数を取得
*
* @returns {number} - 総ジャンル数(40)
*
* @example
* var total = getTotalGenreCount();
* // => 40
*/
function getTotalGenreCount() {
var count = 0;
var subjects = ['jp', 'math', 'sci', 'soc'];
for (var i = 0; i < subjects.length; i++) {
var subjectId = subjects[i];
count += GENRE_MASTER[subjectId].genres.length;
}
return count;
}
/**
* ジャンルIDの検証
*
* @param {string} genreId - ジャンルID
* @returns {boolean} - 有効なジャンルIDかどうか
*
* @example
* isValidGenreId('JP01'); // => true
* isValidGenreId('XX99'); // => false
*/
function isValidGenreId(genreId) {
return getGenreById(genreId) !== null;
}
/**
* Dify用のジャンルリストを生成(問題生成プロンプト用)
*
* @param {string} subjectId - 教科ID(jp, math, sci, soc)
* @returns {string} - ジャンルリストの文字列(改行区切り)
*
* @example
* var list = getGenreListForDify('jp');
* // => "JP01: 漢字・語彙(読み書き、四字熟語、慣用句、ことわざ)\n..."
*/
function getGenreListForDify(subjectId) {
var genres = getGenresBySubject(subjectId);
if (genres.length === 0) {
return '';
}
var lines = [];
for (var i = 0; i < genres.length; i++) {
var genre = genres[i];
var line = genre.id + ': ' + genre.name + '(' + genre.description + ')';
lines.push(line);
}
return lines.join('\n');
}
// ============================================================================
// テスト関数(GASエディタで実行可能)
// ============================================================================
/**
* GenreMaster.jsのテスト関数
* GASエディタで実行して動作確認
*/
function testGenreMaster() {
Logger.log('=== GenreMaster.js テスト開始 ===');
// テスト1: ジャンル総数
var totalCount = getTotalGenreCount();
Logger.log('テスト1: 総ジャンル数 = ' + totalCount + ' (期待値: 40)');
// テスト2: ジャンルID検索
var genre1 = getGenreById('JP01');
Logger.log('テスト2: getGenreById("JP01") = ' + JSON.stringify(genre1));
var genre2 = getGenreById('MA05');
Logger.log('テスト2: getGenreById("MA05") = ' + JSON.stringify(genre2));
// テスト3: 教科別ジャンル取得
var jpGenres = getGenresBySubject('jp');
Logger.log('テスト3: 国語ジャンル数 = ' + jpGenres.length + ' (期待値: 8)');
var mathGenres = getGenresBySubject('math');
Logger.log('テスト3: 算数ジャンル数 = ' + mathGenres.length + ' (期待値: 10)');
var sciGenres = getGenresBySubject('sci');
Logger.log('テスト3: 理科ジャンル数 = ' + sciGenres.length + ' (期待値: 12)');
var socGenres = getGenresBySubject('soc');
Logger.log('テスト3: 社会ジャンル数 = ' + socGenres.length + ' (期待値: 10)');
// テスト4: ジャンルID検証
var valid1 = isValidGenreId('JP01');
Logger.log('テスト4: isValidGenreId("JP01") = ' + valid1 + ' (期待値: true)');
var valid2 = isValidGenreId('XX99');
Logger.log('テスト4: isValidGenreId("XX99") = ' + valid2 + ' (期待値: false)');
// テスト5: Dify用ジャンルリスト生成
var jpList = getGenreListForDify('jp');
Logger.log('テスト5: 国語ジャンルリスト(最初の100文字):');
Logger.log(jpList.substring(0, 100) + '...');
Logger.log('=== GenreMaster.js テスト完了 ===');
}