以下の内容はhttps://koseiwatanabe.hatenablog.com/entry/2024/05/13/105151より取得しました。


TeXによるデータベース構築

目次

目的

私は鉄緑会という学習塾で中高生に英語を教えていて,その講義資料をTeXで作成しています。高校3年生の講義では主に東京大学の過去問を扱い,その解説をするのですが,その過程でTeXにより問題のデータベースを作成したいという要求が生じました。理由としては,授業で扱う問題というのは毎年固定されたものではなく,差し替えが行われるからです。1つのTeXファイルに各問題の解説を列挙していく形式では,問題の差し替えの度にファイルを修正する必要があります。さらに,仮に1つのファイルだけを編集すればよいならまだましですが,詳しくは次の「データベースの内容」にある通り,1つの問題に関する情報が複数のファイルに存在することは運用上避けられません。具体的には,1つの問題の情報は,①問題冊子②解答冊子③解説冊子④解答用紙⑤講評の5つのファイルに散らばっています。これらのファイルの情報を問題改訂の度に変えるというのはミスの原因にもなりますし,それを防ごうとすると問題を改訂する意欲が失われ,「本当はこの問題は差し替えたいけど,面倒だから今年はそのままにしよう」というようなことにも繋がってしまいます。TeXによるデータベース化により,動的に内容を変化させることができれば,ファイルの書き換えという非本質的な時間を節約し,テキストの内容そのものに時間をかけることができ,教材の質の向上に繋がります。

同様の趣旨の記事として,参考にy_minodaさんの記事を貼っておきます。

qiita.com

データベースの内容

データベースに登録する内容ですが,1つのレコードは,問題,解答,解答用紙,配点,採点基準,目標解答時間,解説,講評の8つのフィールドからなります。簡単にそれぞれについて説明すると,


  1. 問題・解答:過去問の問題本文とそれに対する模範解答です。
  2. 解答用紙:東京大学の英語の入試問題は字数指定問題や記号問題など様々な形式があるため,数学の白紙の解答用紙や理科の罫線のみが入った解答用紙とは異なり,問題ごとに個別に作成する必要があります。
  3. 配点・採点基準:小問ごとの配点や採点基準です。
  4. 目標解答時間:解説冊子に載せる目標解答時間です。
  5. 解説:演習後の講義で使う解説資料です。
  6. 講評:生徒の答案を採点し,翌週に配布する採点所感,多かったミスなどを記載した資料です。

使用する問題情報の一元化

まずは,使用する問題の情報を一元化します。つまり,問題冊子.texの中で\input{東京大学-2000-1A}...し, 解説冊子.texの中でも\input{東京大学-2000-1A}...などとするのではなく,1つのファイル(ここでは使用問題設定.sty)に,それぞれの授業でどの問題を使用するのかという一覧を作成します。カンマ区切りで使用する問題を順に指定していきます。

%\使用問題設定{週}{第1問,第2問,第3問...}
\使用問題設定{01}{東京大学-2000-1A,東京大学-2001-1B,東京大学-2002-3,東京大学-2022-4A,東京大学-2023-4B}%
\使用問題設定{02}{東京大学-1986-1A,東京大学-1999-1B,東京大学-1973-2A,東京大学-2004-2B,東京大学-2010-3,東京大学-2012-5}%
...

\使用問題設定は以下のように定義しておきます。

また,準備として\@namedefの完全展開版である,\e@namedefを以下のように定義します。

\def\e@namedef#1{\expandafter\edef\csname#1\endcsname}

%latex.ltx内の\@namedefの定義内の\defを\edefに置き換えたもの
%\def\@namedef#1{\expandafter\def\csname #1\endcsname
\newcounter{回別問題数}%
\def\使用問題設定#1#2{%%%\使用問題設定{週}{第1問,第2問,第3問...}%
\setcounter{回別問題数}{0}%
\expandafter\@for\expandafter\list\expandafter:\expandafter=#2\do{%
\stepcounter{回別問題数}%
\e@namedef{#1回使用問題\arabic{回別問題数}}{\list}%
\global\e@namedef{#1回問題数}{\arabic{回別問題数}}%
}%
}%

問題冊子,解答冊子,解説冊子などを作成するときには,このファイルを参照し,教材を改訂するときには,この1つのファイルのみを変更すれば済むというようにします。

データベースの作成

データベース自体は,以下のようなディレクトリツリー構造をとるものとします。

├東京大学/
 ├1970/
  ├東京大学-1970-1A.tex
  ├東京大学-1970-1B.tex
  ├東京大学-1970-2A.tex
  ├東京大学-1970-2B.tex
  ├東京大学-1970-3.tex
  ├東京大学-1970-4A.tex
  ├東京大学-1970-4B.tex
  ├東京大学-1970-5.tex
 ...
 ├2023/
  ├東京大学-2023-1A.tex
  ├東京大学-2023-1B.tex
  ├東京大学-2023-2A.tex
  ├東京大学-2023-2B.tex
  ├東京大学-2023-3.tex
  ├東京大学-2023-4A.tex
  ├東京大学-2023-4B.tex
  ├東京大学-2023-5.tex

├慶應義塾大学医学部/
 ├2023/
  ├慶應義塾大学医学部-2023-1.tex
  ├慶應義塾大学医学部-2023-2.tex
  ├慶應義塾大学医学部-2023-3.tex
  ├慶應義塾大学医学部-2023-4.tex

さらに,この1つ1つのファイルの中に上述した8つのフィールドが存在しています。 たとえば,東京大学-2023-1A.texというファイルは以下のようになっています。

\問題登録{hoge}
\解答登録{huga}
\配点登録{hige}
\採点基準登録{hogehoge}
\目標解答時間登録{12分}
\解答用紙登録{piyo}
\解説登録{puyo}
\講評登録{piyora}

それぞれの命令は以下のように定義しておきます。

\long\def\問題登録#1{\long\@namedef{\currfilebase-問題}{#1}}
\long\def\解答登録#1{\long\@namedef{\currfilebase-解答}{#1}}
\long\def\配点登録#1{\long\@namedef{\currfilebase-配点}{#1}}
\long\def\目標解答時間登録#1{\long\@namedef{\currfilebase-目標解答時間}{#1}}
\long\def\解答用紙登録#1{\long\@namedef{\currfilebase-解答用紙}{#1}}
\long\def\解説登録#1{\long\@namedef{\currfilebase-解説}{#1}}
\long\def\講評登録#1{\long\@namedef{\currfilebase-講評}{#1}}
\long\def\採点基準登録#1{\long\@namedef{\currfilebase-採点基準}{#1}}

currfileパッケージをロードし,子ファイルのファイル名を\currfilebaseにより取得しています。\jobnameだと元締めファイルのファイル名になってしまいます。

データベースを呼び出す側のファイル

データベースを呼び出すファイル,たとえば問題冊子を生成するファイルは以下のようになっています。本来はデータベースはこのファイルとは別のディレクトリに存在しますが,簡単にするため,データベースは元締めファイルの直下にあるものとします。

\begin{document}
\出典読み込み%ここでその週に使う問題のデータベースを読み込む
%\使用問題{大問番号}{その回に使う問題の通し番号}{その問題を読み込んだ後に行う処理}
\使用問題{1}{1}{\newpage}%
\使用問題{1}{2}{}%
\使用問題{2}{3}{\newpage}%
\使用問題{3}{4}{\newpage}%
\使用問題{3}{5}{}%
\end{document}

膨大なデータベースをすべて読み込むとコンパイル時間が長くなってしまうので,\出典読み込み という命令でその回に必要なデータベースだけを読み込むようにしておきます。\出典読み込み という命令の定義は以下のようになっています。\newcounter{週}によりカウンタを定義し,元締めファイル側で,そのファイルで呼び出したい週の数値をセットします。

\def\parse出典#1{%
\@parse出典#1\@nil
}

\def\@parse出典#1-#2-#3\@nil{%
\input{./#1/#2/#1-#2-#3.tex}
}
\newcounter{}
\def\出典読み込み{%  その週の出典のすべてのTeXソースを読み込み,問題・解答・解説などの情報を@namedef{第01回使用問題1-問題}のように定義していく
\fornext<k>[1]{\@nameuse{\ifnum\c@週<10 0\fi\the\c@週 回問題数}}{%
\expandafter\expandafter\expandafter\parse出典\expandafter\expandafter\expandafter{\csname\ifnum\c@週<10 0\fi\the\c@週 回使用問題\arabic{k}\endcsname}
}
}

つぎに,\使用問題の定義ですが,たとえば,第1回であれば使用問題設定.styに登録した, 東京大学-2000-1A, 東京大学-2001-1B, 東京大学-2002-3, 東京大学-2022-4A, 東京大学-2023-4Bの5つの問題を使用しますが,実際の入試問題のように東京大学-2000-1Aと東京大学-2000-1Bは同じ大問に含めたいです。また,第1問と第2問の間には\newpageを含めたいなどの微調整をできるようにします。簡潔にするため,大問は3問からなるものとします。

\def\第1問使用問題{\noindent 第1問\par}
\def\第2問使用問題{\noindent 第2問\par}
\def\第3問使用問題{\noindent 第3問\par}


\long\def\使用問題#1#2#3{% 
\if#11\relax
\appto\第1問使用問題{%
\csname\csname\ifnum\c@週<10 0\fi\the\c@週 回使用問題#2\endcsname-問題\endcsname%
#3%
}%
\fi
\if#12\relax
\appto\第2問使用問題{%
\csname\csname\ifnum\c@週<10 0\fi\the\c@週 回使用問題#2\endcsname-問題\endcsname%
#3%
}%
\fi
\if#13\relax
\appto\第3問使用問題{%
\csname\csname\ifnum\c@週<10 0\fi\the\c@週 回使用問題#2\endcsname-問題\endcsname%
#3%
}%
\fi
}

\apptoを使うことで,\第○問使用問題という命令のあとに付け足していきます。なお,\apptoを使うにはetoolbox.styを読み込む必要があります。

おわりに

このようにTeXによりデータベースを作成し,内容に応じて必要なファイルをロードしながら,TeXソース(トークン列)をメモリ上で動的に構築していくことで,教材改訂の手間を軽減することができます。このような非本質的な時間を減らすことで,教材の内容そのものにこだわる時間や生徒と接する時間を増やすことができます。




以上の内容はhttps://koseiwatanabe.hatenablog.com/entry/2024/05/13/105151より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14