% -*- coding: utf-8 -*- % ---------------------------------------------------------------------------- % Author: Jianrui Lyu % Website: https://lvjr.bitbucket.io/jnuexam.html % License: The LaTeX Project Public License 1.3c % ---------------------------------------------------------------------------- \NeedsTeXFormat{LaTeX2e} \ProvidesClass{jnuexam}[2024-02-18 v2024E An exam class for Jinan University] %% 旧版本的 LaTeX 不能识别 2022-11-01 这种日期格式 %\@ifl@t@r\fmtversion{2022-11-01}{}{ \@ifl@t@r\fmtversion{2022/11/01}{}{ \ClassError{jnuexam}{% Your current TeX distribution is quite old.\MessageBreak We need CTeX 3.0+ or MiKTeX 2023+ or TeXLive 2023+% }{Please update your TeX distribution first.} } %% --------------------------------------------------------------------------- %% 开始忽略代码中的空白符号 %% --------------------------------------------------------------------------- \RequirePackage{functional} \IgnoreSpacesOn \InputIfFileExists{jnuexam.cfg}{}{} \DeclareKeys[jnuexam]{ english .code = \PassOptionsToClass{language=english}{randexam} ,chinese .code = \PassOptionsToClass{language=chinese}{randexam} } \DeclareUnknownKeyHandler{\PassOptionsToClass{\CurrentOption}{randexam}} \ProcessKeyOptions \LoadClass[freealign,moremath]{randexam} %% --------------------------------------------------------------------------- %% 试卷中英文字符串翻译 %% --------------------------------------------------------------------------- \DeclareExamTranslation{chinese}{ gradetable-Part = 题\quad 号 ,gradetable-Score = 得\quad 分 } \DeclareExamTranslation{english}{ gradetable-Part = Section~No. ,gradetable-Total = Total~Score ,exampart-Score = Score ,exampart-Evaluator = Evaluator ,exampart-Part = Section } \IfExamLanguageEqT{chinese}{ \SetExamValue{answertable}{ notice = {答题须知:本题答案必须写在如下表格中,否则不给分.} } \renewcommand{\questionpointstext}[1]{(#1~\pointorpoints{#1})} } %% --------------------------------------------------------------------------- %% 中文期末试卷表头定制 %% --------------------------------------------------------------------------- \NewDocumentCommand\examcheckquad{mm}{\ifnumequal{#1}{#2}{\,$\checkmark$\,}{\quad}} \SetExamValue{examtitle}{ niandu = 2016--2017, % 教学年度 xueqi = 2, % 第几学期 kecheng = 数学课程, % 课程名称 zhuanye = , % 专业学分 jiaoshi = {吕荐瑞}, % 教师姓名 shijian = , % 考试时间 bixiu = 1, % 1 为必修,0 为选修 bijuan = 1, % 1 为闭卷,0 为开卷 shijuan = A, % A 或 B 或 C 卷 neizhao = 1, % 1 打勾,0 不勾 waizhao = 1, % 1 打勾,0 不勾 } \newcommand{\jdxm@fc@examtitle@table@a}{ \begin{tabular}{l} \underbox{11\ccwd}{\UseExamValue{examtitle}{niandu}}学年度第 \underbox{5.5\ccwd}{\UseExamValue{examtitle}{xueqi}}学期 \\ 课程名称:\underbox{17.5\ccwd}{ \UseExamValue{examtitle}{kecheng} \tlIfEmptyF{\expWhole{\UseExamValue{examtitle}{zhuanye}}}{ \kern0pt(\UseExamValue{examtitle}{zhuanye}) } } \\ 授课教师:\underparbox{17.5\ccwd}{ \centering\rule{0pt}{3ex}\UseExamValue{examtitle}{jiaoshi} } \\ 考试时间:\underbox{17.5\ccwd}{\UseExamValue{examtitle}{shijian}} \\ \end{tabular} } \newcommand{\jdxm@fc@examtitle@table@b}{ \renewcommand{\arraystretch}{1} \begin{tabular}{l} \textbf{课程类别} \\ 必修~[\examcheckquad{1}{\UseExamValue{examtitle}{bixiu}}]\quad 选修~[\examcheckquad{0}{\UseExamValue{examtitle}{bixiu}}] \\ \hline \textbf{考试方式} \\ 开卷~[\examcheckquad{0}{\UseExamValue{examtitle}{bijuan}}]\quad 闭卷~[\examcheckquad{1}{\UseExamValue{examtitle}{bijuan}}] \\ \hline \textbf{试卷类别}~(\,A, B, C\,)\\ \relax [\,\UseExamValue{examtitle}{shijuan}\,]\hfill 共~\zpageref{LastPage}~页 \end{tabular} } \newcommand{\jdxm@fc@examtitle@table@c}{ \begin{tabular}{l} \underspace{10\ccwd}学院\underspace{8\ccwd}专业\underspace{7.5\ccwd}班 \kern0pt(\kern0pt{}级\kern0pt) \\[1em] 姓名\underspace{8\ccwd}学号\underspace{10\ccwd}\hfill \bfseries 内招~[\examcheckquad{1}{\UseExamValue{examtitle}{neizhao}}]~~ 外招~[\examcheckquad{1}{\UseExamValue{examtitle}{waizhao}}] %\\[0.8em] \end{tabular} } \DeclareExamTemplate{examtitle}{final-chinese}{ \centerline{ \LARGE\bfseries\IfExamBoolT{answer}{\color{red!80!black}} 暨\quad 南\quad 大\quad 学\quad 考\quad 试\quad 试\quad 卷 \IfExamBoolT{answer}{\quad 答\quad 案} } \vspace{2em} \IfExamBoolT{random}{ \tlIfEqT{\expWhole{\UseExamValue{examtitle}{shijuan}}}{A}{ \SetExamValue{examtitle}{shijuan=B} } \tlIfEqT{\expWhole{\UseExamValue{examtitle}{shijuan}}}{C}{ \SetExamValue{examtitle}{shijuan=D} } } \noindent \begin{tabularx}{\linewidth}{|@{}X@{}|} \hline\renewcommand{\arraystretch}{1.5} {\begin{tabularx}{\linewidth}{@{}>{\bfseries}l@{}|@{}X@{}|@{}l@{}} \begin{tabular}{l}教\\ 师\\ 填\\ 写\end{tabular} & \jdxm@fc@examtitle@table@a & \jdxm@fc@examtitle@table@b \end{tabularx}}\\ \hline\renewcommand{\arraystretch}{0.9} {\begin{tabularx}{\linewidth}{@{}>{\bfseries}l@{}|@{}X@{}} \begin{tabular}{l}考\\ 生\\ 填\\ 写\end{tabular} & \jdxm@fc@examtitle@table@c \end{tabularx}}\\ \hline \end{tabularx} } %% --------------------------------------------------------------------------- %% 英文期末试卷表头定制 %% --------------------------------------------------------------------------- \SetExamValue{examtitle}{ AcademicYear = 2016--2017, % 教学年度 Semester = 2, % 第几学期 CourseTitle = Math 1906, % 课程名称 MajorCredit = , % 专业学分,可以省略 Instructor = {Jianrui Lyu}, % 教师姓名 Date = , % 考试时间 Compulsory = 1, % 是否必修:1 为必修,0 为选修 ClosedBook = 1, % 是否闭卷:1 为闭卷,0 为开卷 Paper = A, % 试卷版本:A 或 B 或 C 卷 Mainland = 1, % 内招适用:1 打勾,0 不勾 NonMainland = 1, % 外招适用:1 打勾,0 不勾 } \newcommand{\jdxm@fe@examtitle@table@a}{ \begin{tabular}{l} \textbf{Academic~Year}:\underbox{5.5em}{\UseExamValue{examtitle}{AcademicYear}} \enspace \textbf{Semester}:~ 1\textsuperscript{st}~[\examcheckquad{\UseExamValue{examtitle}{Semester}}{1}] \enspace 2\textsuperscript{nd}~[\examcheckquad{\UseExamValue{examtitle}{Semester}}{2}]\\ \textbf{Course~Title}:\underbox{18.7em}{ \UseExamValue{examtitle}{CourseTitle} \tlIfEmptyF{\expWhole{\UseExamValue{examtitle}{MajorCredit}}}{ \kern0pt(\UseExamValue{examtitle}{MajorCredit}) } } \\ \textbf{Instructor's~Name}:\underparbox{16em}{ \centering\rule{0pt}{3ex}\UseExamValue{examtitle}{Instructor} } \\ \textbf{Date~of~the~Examination}:\underbox{13em}{\UseExamValue{examtitle}{Date}} \\ \end{tabular} } \newcommand{\jdxm@fe@examtitle@table@b}{ \fontsize{9pt}{11pt}\selectfont \renewcommand{\arraystretch}{1.2} \begin{tabular}{l} \textbf{Course~Type} \\ Compulsory~[\examcheckquad{1}{\UseExamValue{examtitle}{Compulsory}}]\enspace Elective~[\examcheckquad{0}{\UseExamValue{examtitle}{Compulsory}}] \\ \hline \textbf{Form~of~the~Examination} \\ Open-book~[\examcheckquad{0}{\UseExamValue{examtitle}{ClosedBook}}]\enspace Closed-book~[\examcheckquad{1}{\UseExamValue{examtitle}{ClosedBook}}] \\ \hline \tlIfEqT{\expWhole{\UseExamValue{examtitle}{Paper}}}{A}{ \textbf{Paper}~A~[\,$\checkmark$\,]\enspace \textbf{Paper}~B~[\quad] } \tlIfEqT{\expWhole{\UseExamValue{examtitle}{Paper}}}{B}{ \textbf{Paper}~A~[\quad]\enspace \textbf{Paper}~B~[\,$\checkmark$\,] } \tlIfEqT{\expWhole{\UseExamValue{examtitle}{Paper}}}{C}{ \textbf{Paper}~C~[\,$\checkmark$\,]\enspace \textbf{Paper}~D~[\quad] } \tlIfEqT{\expWhole{\UseExamValue{examtitle}{Paper}}}{D}{ \textbf{Paper}~C~[\quad]\enspace \textbf{Paper}~D~[\,$\checkmark$\,] } \\ Total~Pages~\underbox{4em}{\zpageref{LastPage}} \end{tabular} } \newcommand{\jdxm@fe@examtitle@table@c}{ \begin{tabular}{l} \textbf{School/College}\underspace{11em}~\textbf{Major}\underspace{18.3em}\\ \textbf{Name}\underspace{15.4em}~\textbf{Student~No.}\underspace{15.6em}\\ \textbf{Mainland~Student}~[\examcheckquad{1}{\UseExamValue{examtitle}{Mainland}}]\hspace{4em} \textbf{Non-mainland~Student}~[\examcheckquad{1}{\UseExamValue{examtitle}{NonMainland}}] \end{tabular} } \DeclareExamTemplate{examtitle}{final-english}{ \centerline{ \Large\bfseries\IfExamBoolT{answer}{\color{red!80!black}} The~Examination~Paper~of~Jinan~University \IfExamBoolT{answer}{~(Solutions)} } \vspace{2em} \IfExamBoolT{random}{ \tlIfEqT{\expWhole{\UseExamValue{examtitle}{Paper}}}{A}{ \SetExamValue{examtitle}{Paper=B} } \tlIfEqT{\expWhole{\UseExamValue{examtitle}{Paper}}}{C}{ \SetExamValue{examtitle}{Paper=D} } } \begingroup \setlength\tabcolsep{4pt} \fontsize{10pt}{12pt}\selectfont \noindent \begin{tabularx}{\linewidth}{|@{}X@{}|} \hline\renewcommand{\arraystretch}{1.5} {\begin{tabularx}{\linewidth}{@{}>{\bfseries}wc{5em}@{}|@{}X@{}|@{}l@{}} \fontsize{9pt}{11pt}\selectfont\begin{tabular}{c}For\\Instructor\\Only\end{tabular} & \jdxm@fe@examtitle@table@a & \jdxm@fe@examtitle@table@b \end{tabularx}}\\ \hline\renewcommand{\arraystretch}{1.5} {\begin{tabularx}{\linewidth}{@{}>{\bfseries}wc{5em}@{}|@{}X@{}} \fontsize{9pt}{11pt}\selectfont\begin{tabular}{c}For\\Student\\Only\end{tabular} & \jdxm@fe@examtitle@table@c \end{tabularx}}\\ \hline \end{tabularx} \endgroup } %% --------------------------------------------------------------------------- %% 中英文期末试卷题型命令定制 %% --------------------------------------------------------------------------- \DeclareExamTemplate{exampart}{final-chinese}{ \noindent \textbf{ \textcolor{part~number}{\TheExamCounter{exampart}}、\UseExamValue{exampart}{type} } \IfExamValueEmptyF{exampart}{points}{ (\UseExamValue{exampart}{points}) } } \DeclareExamTemplate{exampart}{final-english}{ \noindent \begin{tblr}{width=\linewidth,colspec={llX},hlines,vlines,cell{1}{3}={r=2}{}} \UseExamTranslation{exampart-Score} & \UseExamTranslation{exampart-Evaluator} & \textbf{ \textcolor{part~number}{ \UseExamTranslation{exampart-Part}~\TheExamCounter{exampart} }:~\UseExamValue{exampart}{type} }~ \IfExamValueEmptyF{exampart}{points}{ (\UseExamValue{exampart}{points}) } \\ & & \end{tblr} } %% --------------------------------------------------------------------------- %% 中英文期末试卷页眉页脚设定 %% --------------------------------------------------------------------------- \IfExamLanguageEqTF{english}{ \DeclareExamTemplate{headleft}{fancy}{ \parbox{\columnwidth}{ \fontsize{10pt}{15pt}\selectfont The~Examination~Paper~for~\ExamFillUlineText{\UseExamValue{examtitle}{CourseTitle}}~of~JNU\\ \strut Student~Name\hfill,~Student~No.\hfill\strut } } \DeclareExamTemplate{headcenter}{fancy}{} \DeclareExamTemplate{headright}{fancy}{} \DeclareExamTemplate{footleft}{fancy}{} \DeclareExamTemplate{footcenter}{fancy}{\thepage} \DeclareExamTemplate{footright}{fancy}{} }{ \DeclareExamTemplate{headleft}{fancy}{ \hspace{-0.3em}《\UseExamValue{examtitle}{kecheng}》 \kern-0.3em 试卷\,\UseExamValue{examtitle}{shijuan} } \DeclareExamTemplate{headcenter}{fancy}{} \DeclareExamTemplate{headright}{fancy}{ 姓名\hspace{6em}学号\hspace{6em} } \DeclareExamTemplate{footleft}{fancy}{} \DeclareExamTemplate{footcenter}{fancy}{ 第~\thepage~页\quad 共~\zpageref{LastPage}~页 } \DeclareExamTemplate{footright}{fancy}{} } %% --------------------------------------------------------------------------- %% 装订线命令 \addbindingline %% 草稿纸命令 \addscratchpaper %% 这两个命令需要编译两次才能得到正确结果 %% --------------------------------------------------------------------------- \IfExamBoolF{plain}{ \RequirePackage{tikz} \RequirePackage{everypage} } \IfExamLanguageEqTF{english}{ \tlSet\l@jdxm@binding@text@a@tl{the} \tlSet\l@jdxm@binding@text@b@tl{binding} \tlSet\l@jdxm@binding@text@c@tl{line} }{ \tlSet\l@jdxm@binding@text@a@tl{装} \tlSet\l@jdxm@binding@text@b@tl{订} \tlSet\l@jdxm@binding@text@c@tl{线} } \newcommand{\bindinglineleft}{ \path (current~page.north~west) +(25mm,-25mm) coordinate (a1); \path (current~page.south~west) +(25mm,25mm) coordinate (a2); \draw[dashed] (a1) -- node[left=1mm,text~width=1em,inner~sep=0pt]{ \1{\l@jdxm@binding@text@c@tl}\0 \1{\l@jdxm@binding@text@b@tl}\0 \1{\l@jdxm@binding@text@a@tl} } (a2); } \newcommand{\bindinglineright}{ \path (current~page.north~east) +(-25mm,-25mm) coordinate (b1); \path (current~page.south~east) +(-25mm,25mm) coordinate (b2); \draw[dashed] (b1) -- node[right=1mm,text~width=1em,inner~sep=0pt]{ \2{\l@jdxm@binding@text@a@tl}\0 \2{\l@jdxm@binding@text@b@tl}\0 \2{\l@jdxm@binding@text@c@tl} } (b2); } \newcommand{\bindinglineone}{% \def\0{\\[70mm]}\def\1{\rotatebox{90}}\def\2{\rotatebox{-90}} \begin{tikzpicture}[remember~picture,overlay,very~thick] \ifnumodd{\value{page}}{\bindinglineleft}{\bindinglineright} \end{tikzpicture}} \newcommand{\bindinglinetwo}{% \def\0{\\[70mm]}\def\1{\rotatebox{90}}\def\2{\rotatebox{-90}} \begin{tikzpicture}[remember~picture,overlay,very~thick] \bindinglineleft\bindinglineright \end{tikzpicture}} \IfExamBoolTF{twoinone}{ \let\bindingline=\bindinglinetwo }{ \let\bindingline=\bindinglineone } %% 必须将 .store 放在 .initial:n 之前 \DeclareKeys[randexam]{ binding .store = \zhuangdingxian, binding .initial:n = 1, binding .default:n = 2 } \newcommand{\addbindingline}{ \ifcase\zhuangdingxian % 0 \or % 1 \IfExamBoolF{answer}{\bindingline}% \or % 2 \bindingline \fi } \IfExamBoolF{plain}{\AddEverypageHook{\addbindingline}} \IfExamLanguageEqTF{english}{ \tlSet\l@jdxm@scratch@font@one@tl{ \sffamily\fontsize{100pt}{100pt}\selectfont } \tlSet\l@jdxm@scratch@font@two@tl{ \sffamily\fontsize{100pt}{100pt}\selectfont } \tlSet\l@jdxm@scratch@text@a@tl{THE} \tlSet\l@jdxm@scratch@text@b@tl{SCRATCH} \tlSet\l@jdxm@scratch@text@c@tl{PAPER} }{ \tlSet\l@jdxm@scratch@font@one@tl{ \sffamily\fontsize{120pt}{120pt}\selectfont } \tlSet\l@jdxm@scratch@font@two@tl{ \sffamily\fontsize{180pt}{180pt}\selectfont } \tlSet\l@jdxm@scratch@text@a@tl{草} \tlSet\l@jdxm@scratch@text@b@tl{稿} \tlSet\l@jdxm@scratch@text@c@tl{纸} } \newcommand{\scratchpaperone}{% \begin{tikzpicture}[remember~picture,overlay,font=\l@jdxm@scratch@font@one@tl] \node[text=lightgray!40,text~width=1000pt,align=center] at (current~page.center) { \l@jdxm@scratch@text@a@tl\\ \l@jdxm@scratch@text@b@tl\\ \l@jdxm@scratch@text@c@tl }; \end{tikzpicture}} \newcommand{\scratchpapertwo}{% \begin{tikzpicture}[remember~picture,overlay,font=\l@jdxm@scratch@font@two@tl] \node[text=lightgray!40] at (current~page.center) { \l@jdxm@scratch@text@a@tl\quad \l@jdxm@scratch@text@b@tl\quad \l@jdxm@scratch@text@c@tl }; \end{tikzpicture}} %% 必须将 .store 放在 .initial:n 之前 \DeclareKeys[randexam]{ scratch .store = \caogaozhi, scratch .initial:n = 0, scratch .default:n = 1 } \newcounter{my@empty@page} % 空白页数 \newcounter{my@scratch@page} % 草稿页数 \newcounter{my@extra@page} % 空白页数+草稿页数 % 添加空白页,使得草稿纸前页数在单面印刷时为偶数,双面印刷时为4的倍数 % 添加草稿纸,页数在单面印刷时等于设置值的两倍,双面印刷时等于设置值的4倍 \newcommand{\doscratchpaperone}{ \clearpage\pagestyle{empty}\let\addbindingline=\relax \ifnumgreater{\caogaozhi}{0}{ \IfExamBoolTF{oneside}{ \ifnumodd{\value{page}} {\setcounter{my@empty@page}{0}} {\setcounter{my@empty@page}{1}} \setcounter{my@scratch@page}{\caogaozhi*2} }{ \setcounter{my@empty@page}{(\value{page}+2)/4*4+1-\value{page}} \setcounter{my@scratch@page}{\caogaozhi*4} } \my@add@extra@page }{} } % 注意在 twocolumn 文档中,\newpage 到下一栏,\clearpage 到下一页 % 另外注意第一行的 \clearpage 等不能移动到 \my@add@extra@page 命令里 % 因为 \clearpage 后本页已经结束,page 表示的是下一页的页码 \newcommand{\doscratchpapertwo}{ \clearpage\pagestyle{empty}\let\addbindingline=\relax \ifnumgreater{\caogaozhi}{0}{ \IfExamBoolTF{oneside}{ \setcounter{my@empty@page}{0} \setcounter{my@scratch@page}{\caogaozhi} }{ \setcounter{my@empty@page}{(\value{page}/2)-(\value{page}/2)/2*2} \setcounter{my@scratch@page}{\caogaozhi*2} } \my@add@extra@page }{} } \newcommand{\my@add@extra@page}{ \setcounter{my@extra@page}{\value{my@empty@page}+\value{my@scratch@page}} \whileboolexpr{ test{\ifnumgreater{\value{my@empty@page}}{0}} }{ \addtocounter{my@empty@page}{-1} \leavevmode\clearpage } \whileboolexpr{ test{\ifnumgreater{\value{my@scratch@page}}{0}} }{ \addtocounter{my@scratch@page}{-1} \leavevmode\scratchpaper\clearpage } \addtocounter{page}{-\value{my@extra@page}} } \IfExamBoolTF{twoinone}{ \let\scratchpaper=\scratchpapertwo \let\doscratchpaper=\doscratchpapertwo }{ \let\scratchpaper=\scratchpaperone \let\doscratchpaper=\doscratchpaperone } % 在旧版本 ctex 宏包中不能用 \AtEndDocument 添加含中文的内容,即不能用 \appto 而要用 \preto \newcommand{\addscratchpaper}{ \preto{\@enddocumenthook}{\doscratchpaper} } \IfExamBoolF{plain}{\IfExamBoolF{answer}{\addscratchpaper}} %% --------------------------------------------------------------------------- %% 试卷模板主题切换 %% --------------------------------------------------------------------------- \DeclareExamTheme{final-chinese}{ \SetExamOption{chinese} \SelectExamTranslation{chinese} \SetExamValue{exampart}{number=\Chinese} \SelectExamTemplate{examtitle}{final-chinese} \SelectExamTemplate{exampart}{final-chinese} } \DeclareExamTheme{final-english}{ \geometry{top=30mm,headheight=34pt} \SetExamBoolFalse{sourcehan} \SelectExamTranslation{english} \SetExamValue{exampart}{number=\Roman} \SelectExamTemplate{examtitle}{final-english} \SelectExamTemplate{exampart}{final-english} } \IfExamLanguageEqTF{english}{ \SelectExamTheme{final-english} }{ \SelectExamTheme{final-chinese} } %% --------------------------------------------------------------------------- %% 停止忽略代码中的空白符号 %% --------------------------------------------------------------------------- \IgnoreSpacesOff