summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2024-02-03 21:13:32 +0000
committerKarl Berry <karl@freefriends.org>2024-02-03 21:13:32 +0000
commit628f2068c18d2c8c8f4e07e12dacbce540f52cf7 (patch)
tree49c2c01f32278d85f561b7f8b673c974602fbbb9
parent10f488f7278131d9b690237de589609a63900c80 (diff)
randexam (3feb24)
git-svn-id: svn://tug.org/texlive/trunk@69690 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/randexam/randexam-a-answer.pdfbin49496 -> 49588 bytes
-rw-r--r--Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex8
-rw-r--r--Master/texmf-dist/doc/latex/randexam/randexam-a-blank.pdfbin41288 -> 41374 bytes
-rw-r--r--Master/texmf-dist/doc/latex/randexam/randexam-b-answer.pdfbin49469 -> 49570 bytes
-rw-r--r--Master/texmf-dist/doc/latex/randexam/randexam-b-blank.pdfbin41229 -> 41309 bytes
-rw-r--r--Master/texmf-dist/doc/latex/randexam/randexam.pdfbin50412 -> 52431 bytes
-rw-r--r--Master/texmf-dist/doc/latex/randexam/randexam.tex102
-rw-r--r--Master/texmf-dist/tex/latex/randexam/randexam.cls1131
8 files changed, 750 insertions, 491 deletions
diff --git a/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.pdf b/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.pdf
index d7d570e9b24..6c62155246e 100644
--- a/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.pdf
+++ b/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex b/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex
index fdfec30618d..bd1cbc9f702 100644
--- a/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex
+++ b/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex
@@ -1,8 +1,8 @@
% -*- coding: utf-8 -*-
% !TEX program = xelatex
-\documentclass[12pt,most]{randexam}
+\documentclass[12pt,math=all]{randexam}
-%\answerfalse % hide answers
+%\boolfalse{exam@answer} % hide answers
\SetExamOption{
seed = 19061116, % random seed
@@ -10,7 +10,7 @@
\begin{document}
-\examtitle{name=Math 1906 Final Exam,date=2018-06-28,version=A} % make exam title
+\examtitle{name=Math 1906 Final Exam,date=\today,version=A} % make exam title
\gradetable[total=4]
@@ -309,7 +309,7 @@ Text text $H_0:\mu=3140$ text text ($\alpha = 0.01$).
\exampart{Work out math proofs.}{2 questions; 16 points in total.}
-\DeclareExamTranslation{current}{solution-Solution=Proof} % rename "Solution" as "Proof"
+\SetExamTranslation{solution-Solution=Proof} % rename "Solution" as "Proof"
\begin{question}[points=9]
The first question $\{x_n\}$ text $x_1=\sqrt2$, $x_{n+1}=\sqrt{2+x_n}$.
diff --git a/Master/texmf-dist/doc/latex/randexam/randexam-a-blank.pdf b/Master/texmf-dist/doc/latex/randexam/randexam-a-blank.pdf
index 1a85a26f4cd..dcc54e2939d 100644
--- a/Master/texmf-dist/doc/latex/randexam/randexam-a-blank.pdf
+++ b/Master/texmf-dist/doc/latex/randexam/randexam-a-blank.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/randexam/randexam-b-answer.pdf b/Master/texmf-dist/doc/latex/randexam/randexam-b-answer.pdf
index 349d3a80d95..c6be0a3b3dc 100644
--- a/Master/texmf-dist/doc/latex/randexam/randexam-b-answer.pdf
+++ b/Master/texmf-dist/doc/latex/randexam/randexam-b-answer.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/randexam/randexam-b-blank.pdf b/Master/texmf-dist/doc/latex/randexam/randexam-b-blank.pdf
index 5ee6962d09c..17ea5a41ab6 100644
--- a/Master/texmf-dist/doc/latex/randexam/randexam-b-blank.pdf
+++ b/Master/texmf-dist/doc/latex/randexam/randexam-b-blank.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/randexam/randexam.pdf b/Master/texmf-dist/doc/latex/randexam/randexam.pdf
index 2faabec1c8d..307234cc1cf 100644
--- a/Master/texmf-dist/doc/latex/randexam/randexam.pdf
+++ b/Master/texmf-dist/doc/latex/randexam/randexam.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/randexam/randexam.tex b/Master/texmf-dist/doc/latex/randexam/randexam.tex
index feb1af2e145..382375dc119 100644
--- a/Master/texmf-dist/doc/latex/randexam/randexam.tex
+++ b/Master/texmf-dist/doc/latex/randexam/randexam.tex
@@ -1,9 +1,9 @@
% -*- coding: utf-8 -*-
-\documentclass[12pt,plain,most]{randexam}
+\documentclass[12pt,plain,math=most]{randexam}
\geometry{b5paper,margin=2cm}
-\newcommand*{\myversion}{2024C}
+\newcommand*{\myversion}{2024D}
\newcommand*{\mydate}{\the\year-\mylpad\month-\mylpad\day}
\newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
@@ -28,6 +28,7 @@
\renewcommand{\arraystretch}{1.3}
\usepackage{tabularx}
+\usepackage{booktabs}
\newcommand{\fillbox}[1]{\ulinefill{#1}\underline{#1}\ulinefill{#1}}
@@ -361,7 +362,7 @@ The meanings of keys in the \verb!\gradetable! command are:
\subsection{Answer tables}
Before true-or-false, fill-in-the-blank, or multiple-choice questions,
-you may use \mycmd{\answertable} to generate an blank answer table:
+you may use \mycmd{\answertable} to generate a blank answer table:
\begin{code}
\answertable[total=6,column=3,strut=3em]
@@ -427,9 +428,19 @@ you could modify the translation of \mykey{solution-Solution} keyword
The following example changes it from "Solution" to "Proof":
\begin{code}
-\DeclareExamTranslation{current}{solution-Solution=Proof}
+\SetExamTranslation{solution-Solution=Proof}
+\begin{solution}
+ This is the proof.
+\end{solution}
\end{code}
+\begingroup
+\SetExamTranslation{solution-Solution=Proof}
+\begin{solution}
+ This is the proof.
+\end{solution}
+\endgroup
+
\subsection{Points command}
Inside \myenv{solution} environment, you could use \mycmd{\points} to give points for each step.
@@ -452,7 +463,7 @@ And the point text will be printed at the right edge of the line.
\subsection{Alignment commands}
-With class option \myopt{many}, \mypkg{randexam} will load \mypkg{freealign} package.
+With class option \myopt{freealign}, \mypkg{randexam} loads \mypkg{freealign} package,
and \mypkg{freealign} package provides several commands for aligning math formulas in different lines.
Here is the first example:
@@ -491,10 +502,37 @@ you need two compilations to get correct results.
\section{Class options}
+All options provided by \mypkg{randexam} class are listed in the following table:
+
+\begin{tabularx}{\linewidth}{@{}lX@{}}
+\toprule
+ \myopt{noanswer} & hide all answers in the exam paper \\
+ \myopt{random} & shuffle questions in each part \\
+ \myopt{seed} & the random seed used by \myopt{random} option \\
+\midrule
+ \myopt{plain} & set page style \myval{plain} \\
+ \myopt{a3paper} & typeset a two-column paper of A3 size \\
+ \myopt{a3input} & input a paper of A4 size and change it to A3 size \\
+\midrule
+ \myopt{mathdesign} & use \mypkg{mathdesign} utopia font \\
+ \myopt{freealign} & load \mypkg{freealign} package \\
+ \myopt{medmath} & load \mypkg{medmath} package \\
+ \myopt{moremath} & define more math commands \\
+ \myopt{math=many} & $\Leftrightarrow$ \myopt{mathdesign,freealign} \\
+ \myopt{math=most} & $\Leftrightarrow$ \myopt{mathdesign,freealign,medmath} \\
+ \myopt{math=all} & $\Leftrightarrow$ \myopt{mathdesign,freealign,medmath,moremath} \\
+\midrule
+ \myopt{chinese} & select Chinese language and load \mypkg{ctex} package \\
+\bottomrule
+\end{tabularx}
+
+Some of the options could also be modified with \mycmd{\SetExamOption}:
+\myopt{noanswer}, \myopt{random}, and \myopt{seed}.
+
\subsection{Blank exam papers}
Assume \myfile{exam-a-answer.tex} is an exam paper with answers.
-You can easily get an blank exam paper with answers removed,
+You can easily get a blank exam paper with answers removed,
by creating an \myfile{exam-a-blank.tex} file with the following lines:
\begin{code}
@@ -508,7 +546,7 @@ The answers will be hidden in the compiled exam paper.
\subsection{Randomized variants}\label{opt:random}
Assume \myfile{exam-a-answer.tex} is an exam paper.
-You can get an randomized variant with all questions in the same part shuffled,
+You could get a randomized variant with all questions in the same part shuffled,
by creating an \myfile{exam-b-answer.tex} file with the following lines:
\begin{code}
@@ -553,7 +591,7 @@ even if you have only the PDF file.
\subsection{Translations of keywords}\label{subsect:translation}
With \mycmd{\DeclareExamTranslation} you can define the translaitons of the keywords
-in an \mypkg{randexam} paper. At this time only English keywords are defined:
+in a \mypkg{randexam} paper.
\begin{code}
\DeclareExamTranslation{english}{
@@ -579,7 +617,9 @@ in an \mypkg{randexam} paper. At this time only English keywords are defined:
}
\end{code}
-You could translate them for another language and enable them with \mycmd{\SelectExamTranslation} command:
+At this time only English and Chinese keywords are defined.
+You could translate them for another language and enable them
+with \mycmd{\SelectExamTranslation} command:
\begin{code}
\DeclareExamTranslation{somelang}{
@@ -613,21 +653,53 @@ This command is useful in defining new templates for the exam (see Subsection \r
\subsection{Saving and reading key values}
-With \mycmd{\DeclareExamValue} and \mycmd{\UseExamValue} you could save and read
+With \mycmd{\SetExamValue} and \mycmd{\UseExamValue} you could save and read
the value of a key, respectively.
\begin{code}
-\DeclareExamValue{somemodule}{somekey}{SomeValue}
+\SetExamValue{somemodule}{somekey=SomeValue}
\UseExamValue{somemodule}{somekey}
\end{code}
\hrule
-\DeclareExamValue{somemodule}{somekey}{SomeValue}
+\SetExamValue{somemodule}{somekey=SomeValue}
\UseExamValue{somemodule}{somekey}
\vspace{0.5em}
\hrule
\vspace{0.5em}
-These two commands are useful in defining new templates
+The \mypkg{randexam} class also provides commands \mycmd{\IfExamValueExistT},
+\mycmd{\IfExamValueExistF}, and \mycmd{\IfExamValueExistTF},
+with which you can do conditional typesetting.
+
+\begin{code}
+\IfExamValueExistTF{somemodule}{somekey}{True}{False}
+\end{code}
+\hrule
+\IfExamValueExistTF{somemodule}{somekey}{True}{False}
+\vspace{0.5em}
+\hrule
+\vspace{0.5em}
+
+Furthermore, you may change typeset command of some counter with \mycmd{\SetExamValue}
+and the counter is typeset with \mycmd{\TheExamCounter} command when needed.
+
+\setcounter{exampart}{4}
+\begin{code}
+\SetExamValue{exampart}{number=\Roman}
+\SetExamValue{question}{number=\arabic}
+Part \TheExamCounter{exampart},
+Question \TheExamCounter{question}
+\end{code}
+\hrule
+\SetExamValue{exampart}{number=\Roman}
+\SetExamValue{question}{number=\arabic}
+Part \TheExamCounter{exampart},
+Question \TheExamCounter{question}
+\vspace{0.5em}
+\hrule
+\vspace{0.5em}
+
+These commands are useful in defining new templates
for the exam (see Subsection \ref{subsect:template}).
\subsection{Templates of elements}\label{subsect:template}
@@ -657,10 +729,10 @@ you can write the following code in document preamble:
Then the \mycmd{\examtitle} command in document body will produce different result:
\begin{code}
-\examtitle{name=Final Exam in My School,date=2024-01-01}
+\examtitle{name=Final Exam in My School,date=\today}
\end{code}
\vspace{-1em}
-\examtitle{name=Final Exam in My School,date=2024-01-01}
+\examtitle{name=Final Exam in My School,date=\today}
Normally \mycmd{\examtitle} will call \mycmd{\UseExamTemplate{examtitle}{default}}.
diff --git a/Master/texmf-dist/tex/latex/randexam/randexam.cls b/Master/texmf-dist/tex/latex/randexam/randexam.cls
index d103dfe5584..105d3de1683 100644
--- a/Master/texmf-dist/tex/latex/randexam/randexam.cls
+++ b/Master/texmf-dist/tex/latex/randexam/randexam.cls
@@ -1,50 +1,81 @@
% -*- coding: utf-8 -*-
% ----------------------------------------------------------------------------
% Author: Jianrui Lyu <tolvjr@163.com>
+% Package: https://ctan.org/pkg/randexam
% License: The LaTeX Project Public License 1.3c
% ----------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
-\ProvidesClass{randexam}[2024-01-28 v2024C Make an exam paper and its randomized variants]
+\ProvidesClass{randexam}[2024-02-03 v2024D Make an exam paper and its randomized variants]
%% Old LaTeX release could not recognize date format like 2022-11-01
%\@ifl@t@r\fmtversion{2022-11-01}{}{
\@ifl@t@r\fmtversion{2022/11/01}{}{
\ClassError{randexam}{%
Your current TeX distribution is quite old.\MessageBreak
- We need CTeX 3.0+ or MiKTeX 2023+ or TeXLive 2023+%
+ We need TeXLive 2023+ or MiKTeX 2023+ or CTeX 3.0+%
}{Please update your TeX distribution first.}
}
+%% ---------------------------------------------------------------------------
+%% Start ignoring spaces in the code
+%% ---------------------------------------------------------------------------
+
\RequirePackage{functional}
\IgnoreSpacesOn
+%% ---------------------------------------------------------------------------
+%% Declare class options
+%% ---------------------------------------------------------------------------
+
\RequirePackage{etoolbox}
-\newbool{plain} \boolfalse{plain} % use plain page style
-\newbool{twoinone} \boolfalse{twoinone} % use A3 paper
-\newbool{oneside} \boolfalse{oneside} % use single sided exam paper
-\newbool{resetnumber} \booltrue{resetnumber} % reset numbers in new exam groups
-\newbool{random} \boolfalse{random} % shuffle questions
-\newbool{answer} \booltrue{answer} % show answers
-\newbool{amsfonts} \boolfalse{amsfonts} % use ams fonts
-\newbool{freealign} \boolfalse{freealign} % load freealign package
-\newbool{medmath} \boolfalse{medmath} % use medium-size formulas
-\newbool{evaluator} \boolfalse{evaluator} % add evaluator line in the grade table
-
-\DeclareKeys{
- plain .if = plain,
- a3paper .if = twoinone,
- a3input .code = \booltrue{twoinone}\booltrue{plain},
- oneside .if = oneside,
- random .if = random,
- noanswer .ifnot = answer,
- amsfonts .if = amsfonts,
- freealign .if = freealign,
- medmath .if = medmath,
- evaluator .if = evaluator,
- many .code = \booltrue{freealign},
- most .code = \booltrue{freealign}\booltrue{medmath}
+\newbool{exam@plain} \boolfalse{exam@plain} % use plain page style
+\newbool{exam@twoinone} \boolfalse{exam@twoinone} % use A3 paper
+\newbool{exam@oneside} \boolfalse{exam@oneside} % use single sided exam paper
+\newbool{exam@resetnumber}\booltrue{exam@resetnumber} % reset numbers in new exam parts
+\newbool{exam@random} \boolfalse{exam@random} % shuffle questions
+\newbool{exam@answer} \booltrue{exam@answer} % show answers
+\newbool{exam@evaluator} \boolfalse{exam@evaluator} % add evaluator line in the grade table
+\newbool{exam@mathdesign} \booltrue{exam@mathdesign} % use mathdesign fonts
+\newbool{exam@freealign} \boolfalse{exam@freealign} % load freealign package
+\newbool{exam@medmath} \boolfalse{exam@medmath} % use medium-size formulas
+\newbool{exam@moremath} \boolfalse{exam@moremath} % define more math commands
+
+\DeclareKeys[randexam]{
+ plain .if = exam@plain
+ ,a3paper .if = exam@twoinone
+ ,a3input .code = \booltrue{exam@twoinone}\booltrue{exam@plain}
+ ,oneside .if = exam@oneside
+ ,random .if = exam@random
+ ,noanswer .ifnot = exam@answer
+ ,evaluator .if = exam@evaluator
+ ,mathdesign .if = exam@mathdesign
+ ,freealign .if = exam@freealign
+ ,medmath .if = exam@medmath
+ ,moremath .if = exam@moremath
+ ,math .choice:
+ ,math .default:n = many
+ ,math/many .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign}
+ ,math/most .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign}
+ \booltrue{exam@medmath}
+ ,math/all .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign}
+ \booltrue{exam@medmath}\booltrue{exam@moremath}
+}
+
+%% Support for Chinese language
+\newbool{exam@ctex} \boolfalse{exam@ctex} % load ctex package
+\newbool{exam@solidot} \boolfalse{exam@solidot} % use full-width solid periods
+\newbool{exam@sourcehan}\boolfalse{exam@sourcehan} % use source han font
+\DeclareKeys[randexam]{
+ ctex .if = exam@ctex
+ ,solidot .if = exam@solidot
+ ,sourcehan .if = exam@sourcehan
+ ,chinese .choice:
+ ,chinese .default:n = many
+ ,chinese/many .code = \booltrue{exam@ctex}
+ ,chinese/most .code = \booltrue{exam@ctex}\booltrue{exam@solidot}
+ ,chinese/all .code = \booltrue{exam@ctex}\booltrue{exam@solidot}\booltrue{exam@sourcehan}
}
\DeclareUnknownKeyHandler{\PassOptionsToClass{\CurrentOption}{article}}
@@ -53,11 +84,11 @@
\LoadClass{article}
-\iftwoinone
+\ifbool{exam@twoinone}{
\RequirePackage[a3paper,landscape,twocolumn,columnsep=60mm,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
-\else
+}{
\RequirePackage[a4paper,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
-\fi
+}
\RequirePackage{amsmath}
\RequirePackage{array}
@@ -70,18 +101,26 @@
\RequirePackage{tabularx}
\RequirePackage{xcolor}
-\ifplain
- \allowdisplaybreaks[4]
-\fi
+\ifbool{exam@plain}{\allowdisplaybreaks[4]}{}
-\ifamsfonts
- \RequirePackage{amssymb}
-\else
+\ifbool{exam@twoinone}{
+ \RequirePackage{pdfpages}
+ % When pdfpages package is newer enough, putting \includepdf at the beginning
+ % of document body will cause an error about an undefined command;
+ % see https://tex.stackexchange.com/questions/352007/ieeetran-and-pdfpages
+ % Also since LaTeX release 2018-04-01 \@ifundefined won't turn an undefined command
+ % into \relax; see https://www.latex-project.org/news/latex2e-news/ltnews28.pdf
+ \@ifundefined{@setmarks}{\let\@setmarks\relax}{}
+}{}
+
+\ifbool{exam@mathdesign}{
\RequirePackage[utopia]{mathdesign} % charter, utopia
\renewcommand\bfdefault{bx}
\let\oldoiint\oiint\renewcommand{\oiint}{\oldoiint\nolimits}
\DeclareTextCommandDefault{\nobreakspace}{\leavevmode\nobreak\ }
-\fi
+}{
+ \RequirePackage{amssymb}
+}
\newcolumntype{Y}{>{\centering\arraybackslash}X}
\newcolumntype{n}[1]{>{\centering\arraybackslash}m{#1}}
@@ -101,13 +140,11 @@
%% Otherwise, we may enable the template by using \SelectExamTemplate command
\NewDocumentCommand\DeclareExamTemplate{mm+m}{
\tlSet{\expName{l@rdxm@template@#1@#2@tl}}{#3}
- \ignorespaces
}
%% #1: exam element; #2: template name
\NewDocumentCommand\SelectExamTemplate{mm}{
\tlSetEq{\expName{l@rdxm@template@#1@default@tl}}{\expName{l@rdxm@template@#1@#2@tl}}
- \ignorespaces
}
%% #1: exam element; #2: template name.
@@ -122,7 +159,7 @@
\tlSet\l@rdxm@current@language@tl{english}
-\DeclareUnknownKeyHandler[randexam-translation]{
+\DeclareUnknownKeyHandler[randexam/translation]{
\tlSet{\expName{l@rdxm@translate@\l@rdxm@declare@language@tl @#1@tl}}{#2}
}
@@ -133,14 +170,18 @@
}{
\tlSet\l@rdxm@declare@language@tl{#1}
}
- \SetKeys[randexam-translation]{#2}
- \ignorespaces
+ \SetKeys[randexam/translation]{#2}
+}
+
+%% #1: a keyval list with keyword = transaltion format
+\NewDocumentCommand\SetExamTranslation{m}{
+ \tlSetEq\l@rdxm@declare@language@tl\l@rdxm@current@language@tl
+ \SetKeys[randexam/translation]{#1}
}
%% #1: language name
\NewDocumentCommand\SelectExamTranslation{m}{
\tlSet\l@rdxm@current@language@tl{#1}
- \ignorespaces
}
%% #1: keyword name.
@@ -149,6 +190,17 @@
\UseName{l@rdxm@translate@\l@rdxm@current@language@tl @#1@tl}
}
+%% #1: keyword translation; #2: keyword number.
+%% The \relax prevents functional package from treating the result as a function
+\NewDocumentCommand\MakeExamNameNumber{mm}{
+ \clistSet\lTmpaClist{\expWhole{#1}}
+ \intCompareTF{\clistVarCount\lTmpaClist}>{1}{
+ \prgReturn{\relax\clistVarItem\lTmpaClist{1}#2\clistVarItem\lTmpaClist{2}}
+ }{
+ \prgReturn{#1~#2}
+ }
+}
+
\DeclareExamTranslation{english}{
answertable-Answer = Answer
,answertable-Number = Number
@@ -174,21 +226,54 @@
\SelectExamTranslation{english}
%% ---------------------------------------------------------------------------
-%% Keyvalue commands for exam options
+%% Keyvalue commands for exam elements
%% ---------------------------------------------------------------------------
-%% #1 module name; #2: key name; #3: its value
-\NewDocumentCommand\DeclareExamValue{mm+m}{
+%% #1 element name; #2: key definitions
+\NewDocumentCommand\DeclareExamValue{m+m}{
+ \DeclareKeys[randexam/#1]{#2}
+}
+
+%% #1 element name; #2: key name; #3: its value
+\NewDocumentCommand\rdxm@set@one@value{mm+m}{
\tlSet{\expName{l@rdxm@value@#1@#2@tl}}{#3}
- \ignorespaces
}
-%% #1: module name; #2: key name.
+\newrobustcmd\rdxm@declare@key@handler[1]{
+ \DeclareUnknownKeyHandler[randexam/#1]{\rdxm@set@one@value{#1}{##1}{##2}}
+}
+
+%% #1 element name; #2: key-value list
+\NewDocumentCommand\SetExamValue{m+m}{
+ \rdxm@declare@key@handler{#1}
+ \SetKeys[randexam/#1]{#2}
+}
+
+%% #1: element name; #2: key name.
%% In an expandable command, we should use \UseName but not \expName.
+%% When the key is undefined, the expanded result of \UseName is \relax,
+%% and we could test this case with \tlIfExist function.
\NewExpandableDocumentCommand\UseExamValue{mm}{
\UseName{l@rdxm@value@#1@#2@tl}
}
+%% In fact, \ifdef/ifcsname is a wrapper for \ifdefined/\ifcsname in eTeX;
+%% they will not turn an undefined macro into \relax
+\NewExpandableDocumentCommand\IfExamValueExistT{mm+m}{
+ \ifcsdef{l@rdxm@value@#1@#2@tl}{#3}{}
+}
+\NewExpandableDocumentCommand\IfExamValueExistF{mm+m}{
+ \ifcsdef{l@rdxm@value@#1@#2@tl}{}{#3}
+}
+\NewExpandableDocumentCommand\IfExamValueExistTF{mm+m+m}{
+ \ifcsdef{l@rdxm@value@#1@#2@tl}{#3}{#4}
+}
+
+%% #1 element name
+\NewDocumentCommand\TheExamCounter{m}{
+ \UseExamValue{#1}{number}{#1}
+}
+
%% ---------------------------------------------------------------------------
%% Command for exam title: \examtitle
%% ---------------------------------------------------------------------------
@@ -197,23 +282,14 @@
\newcommand{\underbox}[2]{\kern0pt\underline{\makebox[#1]{#2}}\kern0pt\relax}
\newcommand{\underparbox}[2]{\kern0pt\underline{\parbox[b]{#1}{#2}}\kern0pt\relax}
-\newcommand{\ischeck}[1]{\ifnum#1>0\,$\checkmark$\,\else\quad\fi}
-\newcommand{\isquad}[1]{\ifnum#1=0\,$\checkmark$\,\else\quad\fi}
-
-\DeclareKeys[randexam-title]{
- name .code = \DeclareExamValue{examtitle}{name}{#1}
- ,date .code = \DeclareExamValue{examtitle}{date}{#1}
- ,version .code = \DeclareExamValue{examtitle}{version}{#1}
-}
-
-\NewDocumentCommand\SetExamTitle{+m}{\SetKeys[randexam-title]{#1}}
+\rdxm@declare@key@handler{examtitle}
-\SetExamTitle{name=Math~1906,date=\today,version=A}
+\SetExamValue{examtitle}{name=Math~1906,date=\today,version=A}
\DeclareExamTemplate{examtitle}{normal}{
\begingroup
\Large\noindent
- \ifbool{answer}{
+ \ifbool{exam@answer}{
\textcolor{red!80!black}{
\UseExamValue{examtitle}{name}\hfill\UseExamTranslation{examtitle-Solutions}
}
@@ -225,14 +301,14 @@
\SelectExamTemplate{examtitle}{normal}
\NewDocumentCommand\examtitle{+m}{
- \SetExamTitle{#1}
+ \SetExamValue{examtitle}{#1}
\thispagestyle{plain}
- \ifbool{random}{
+ \ifbool{exam@random}{
\tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{A}{
- \DeclareExamValue{examtitle}{version}{B}
+ \SetExamValue{examtitle}{version=B}
}
\tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{C}{
- \DeclareExamValue{examtitle}{version}{D}
+ \SetExamValue{examtitle}{version=D}
}
}{}
\UseExamTemplate{examtitle}{default}
@@ -244,17 +320,13 @@
%% total: total number of parts in current exam;
%% strut: strut height in the score row.
-\DeclareKeys[randexam-gradetable]{
- total .code = \DeclareExamValue{gradetable}{total}{#1}
- ,total .initial:n = 6
- ,strut .code = \DeclareExamValue{gradetable}{strut}{#1}
- ,strut .initial:n = 2.5em
-}
+\rdxm@declare@key@handler{gradetable}
+\SetKeys[randexam/gradetable]{total=6,strut=2.5em}
\newcounter{@exam@grade@cnt}
\newrobustcmd\rdxm@part@number[1]{
\setcounter{@exam@grade@cnt}{#1}
- \exam@part@number{@exam@grade@cnt}
+ \UseExamValue{exampart}{number}{@exam@grade@cnt}
}
%% #1: the tl variable; #2: the first cell; #3: the last cell
@@ -288,7 +360,7 @@
{}
{\UseExamValue{gradetable}{total}}
\rdxm@gobble@one
- \ifbool{evaluator}{
+ \ifbool{exam@evaluator}{
\rdxm@table@make@row
\l@rdxm@gradetable@evaluator@tl
{\textbf{\UseExamTranslation{gradetable-Evaluator}}
@@ -302,7 +374,7 @@
\hline
\l@rdxm@gradetable@part@tl \\ \hline
\l@rdxm@gradetable@score@tl \\ \hline
- \ifbool{evaluator}{\l@rdxm@gradetable@evaluator@tl \\ \hline}{}
+ \ifbool{exam@evaluator}{\l@rdxm@gradetable@evaluator@tl \\ \hline}{}
\end{tabularx}
}
\SelectExamTemplate{gradetable}{normal}
@@ -310,7 +382,7 @@
\NewDocumentCommand\gradetable{O{}}{
\par\vspace{1em}
\begingroup
- \SetKeys[randexam-gradetable]{#1}
+ \SetKeys[randexam/gradetable]{#1}
\UseExamTemplate{gradetable}{default}
\endgroup
}
@@ -322,7 +394,7 @@
\newcommand{\rdxm@columnbox}[1]{\makebox[\columnwidth]{#1}}
\newcommand{\rdxm@headleft}{\UseExamValue{examtitle}{name}}
\newcommand{\rdxm@headright}{
- \ifbool{answer}{
+ \ifbool{exam@answer}{
\UseExamTranslation{headfoot-Solutions}
}{
\UseExamTranslation{headfoot-Name}:\hspace{12em}
@@ -331,46 +403,44 @@
\newcommand{\rdxm@headtext}{\rdxm@headleft\hfill\rdxm@headright}
\newcommand{\rdxm@footleft}{\UseExamValue{examtitle}{date}}
\newcommand{\rdxm@footcenter}{
- \UseExamTranslation{headfoot-Page}~\thepage\space
- \UseExamTranslation{headfoot-of}~\zpageref{LastPage}
+ \MakeExamNameNumber{\UseExamTranslation{headfoot-Page}}{\thepage}
+ \space
+ \MakeExamNameNumber{\UseExamTranslation{headfoot-of}}{\zpageref{LastPage}}
}
\newcommand{\rdxm@footright}{
- \UseExamTranslation{headfoot-Version}~\UseExamValue{examtitle}{version}
+ \MakeExamNameNumber{\UseExamTranslation{headfoot-Version}}
+ {\UseExamValue{examtitle}{version}}
}
\newcommand{\rdxm@foottext}{\rdxm@footleft\hfill\rdxm@footcenter\hfill\rdxm@footright}
% fancy page style
\fancyhf{} % clear head and foot
-\iftwoinone
- \renewcommand{\headrulewidth}{0pt}%
+\ifbool{exam@twoinone}{
+ \renewcommand{\headrulewidth}{0pt}
\lhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}}
\rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}}
\lfoot{\small\rdxm@columnbox{\rdxm@foottext}}
\rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}}
-\else
+}{
\lhead{\small\rdxm@headleft}
\rhead{\small\rdxm@headright}
\cfoot{\small\rdxm@foottext}
-\fi
+}
% plain page style
\fancypagestyle{plain}{
- \renewcommand{\headrulewidth}{0pt}%
+ \renewcommand{\headrulewidth}{0pt}
\fancyhf{}
- \iftwoinone
+ \ifbool{exam@twoinone}{
\rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext\strut}}}
\lfoot{\small\rdxm@columnbox{\rdxm@foottext}}
\rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}}
- \else
+ }{
\cfoot{\small\rdxm@foottext}
- \fi
+ }
}
-\ifplain
- \pagestyle{plain}
-\else
- \pagestyle{fancy}
-\fi
+\ifbool{exam@plain}{\pagestyle{plain}}{\pagestyle{fancy}}
%% ---------------------------------------------------------------------------
%% Class option for shuffling questions: random
@@ -384,17 +454,18 @@
seed .initial:n = 19061116
}
-\ifrandom
+\ifbool{exam@random}{
\RequirePackage{pgf}
\RequirePackage{pgffor}
- \newcommand*\exam@set@seed{%
- %% 当\pgfmathrandom的参数为3的倍数时,对相邻种子生成的多个随机数分布不均匀
- %\pgfmathsetseed{\numexpr\rdxm@random@seed+\value{rdxm@part}-1\relax}%
- %% 因此我们改用下面的方法,用随机数种子生成下一个随机数种子
- \pgfmathsetseed{\rdxm@random@seed}%
- \pgfmathrandominteger\rdxm@random@seed{1}{2147483647}%
+ \newcommand*\exam@set@seed{
+ %% When the argument of \pgfmathrandom is a multiple of three,
+ %% the random numbers generated by nearby seeds are not uniformly distributed
+ %\pgfmathsetseed{\numexpr\rdxm@random@seed+\value{exampart}-1\relax}
+ %% Therefore we take this approach: generating next random seed with current seed
+ \pgfmathsetseed{\rdxm@random@seed}
+ \pgfmathrandominteger\rdxm@random@seed{1}{2147483647}
}
-\fi
+}{}
%% ---------------------------------------------------------------------------
%% Command for exam groups: \exampart
@@ -403,20 +474,26 @@
%% Environment for solutions: solution
%% ---------------------------------------------------------------------------
-%% You need to put .code before .initial:n
-\DeclareKeys[randexam-exampart]{%
- partnumber .code = \let\exam@part@number#1,
- partnumber .initial:n = \Roman,
-}
+\newcounter{exampart}
+\renewcommand\theexampart{\Roman{exampart}}
+
+\rdxm@declare@key@handler{exampart}
+\SetExamValue{exampart}{number=\Roman}
+
+%% No displaying question number when there is only one question in the part
+\newbool{exam@onlyonequestion}\boolfalse{exam@onlyonequestion}
-\newif\ifonlyonequestion \onlyonequestionfalse % 此部分仅有一道题时不显示题目编号
\xdef\allquestions{}
\xdef\lastquestion{}
-\newcounter{question} % 当前题型的小题编号
-\newcounter{questionreal} % 实际显示的小题编号,在各题型小题统一编号时使用
-\newcounter{totalquestions} % 之前各题型小题总数,在各题型小题统一编号时使用
-\newcounter{choice} % 后面选择题的 abcd 环境要用到
+%% question: problem number within current part
+%% questionreal: problem number for display, used when exam@resetnumber=false
+%% totalquestions: total number of problems in previous parts, used when exam@resetnumber=false
+\newcounter{question}
+\newcounter{questionreal}
+\newcounter{totalquestions}
+
+\newcounter{choice} % used in abcd environment
\newcommand{\hangtext}{}
\newlength{\hanglength}
\colorlet{part~number}{black}
@@ -426,83 +503,83 @@
\newcounter{rdxm@shuffle@temp@cnt}
\newcounter{rdxm@list@temp@cnt}
-\newcommand\rdxm@list@print[1]{%
- \par\renewcommand*{\do}[1]{(##1)}%
+\newcommand\rdxm@list@print[1]{
+ \par\renewcommand*{\do}[1]{(##1)}
\dolistloop#1%
}
-\newcommand\rdxm@list@remove[2]{%
+\newcommand\rdxm@list@remove[2]{
%\rdxm@list@print\rdxm@shuffle@list
- \setcounter{rdxm@list@temp@cnt}{0}%
- \global\let\rdxm@tmpa@list=#1%
+ \setcounter{rdxm@list@temp@cnt}{0}
+ \global\let\rdxm@tmpa@list=#1
\gdef#1{}%
- \par\renewcommand*{\do}[1]{%
- \stepcounter{rdxm@list@temp@cnt}%
- \ifnumequal{\value{rdxm@list@temp@cnt}}{#2}{%
- \def\rdxm@list@item{##1}%
- %[##1]%
+ \par\renewcommand*{\do}[1]{
+ \stepcounter{rdxm@list@temp@cnt}
+ \ifnumequal{\value{rdxm@list@temp@cnt}}{#2}{
+ \def\rdxm@list@item{##1}
+ %[##1]
}{
- \listxadd#1{##1}%
+ \listxadd#1{##1}
}%
}%
\dolistloop\rdxm@tmpa@list
}
-\newcommand\rdxm@shuffle@questions{%
+\newcommand\rdxm@shuffle@questions{
\exam@set@seed
- \ifnumgreater{\value{question}}{2}{%
- \gdef\rdxm@shuffle@list{}%
- \foreach \i in {1,...,\value{question}} {\listxadd\rdxm@shuffle@list{\i}}%
- %% 首尾两个小题的位置总要改变
- \pgfmathrandom{2,\value{question}}%
- \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
- \global\csletcs{rdxm@question@b@1}{rdxm@question@a@\rdxm@list@item}%
+ \ifnumgreater{\value{question}}{2}{
+ \gdef\rdxm@shuffle@list{}
+ \foreach \i in {1,...,\value{question}} {\listxadd\rdxm@shuffle@list{\i}}
+ %% always change the postions of the first and the last questions
+ \pgfmathrandom{2,\value{question}}
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}
+ \global\csletcs{rdxm@question@b@1}{rdxm@question@a@\rdxm@list@item}
\ifnumequal{\rdxm@list@item}{\value{question}}{
- \pgfmathrandom{\numexpr\value{question}-1\relax}%
- \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
- \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}%
- }{%
- \pgfmathrandom{\numexpr\value{question}-2\relax}%
- \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
- \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}%
- }%
- %% 其他小题的位置没有任何限制
- \setcounter{rdxm@shuffle@temp@cnt}{1}%
- \whileboolexpr{%
- test{\ifnumless{\value{rdxm@shuffle@temp@cnt}}{\numexpr\value{question}-1\relax}}%
- }{%
- \stepcounter{rdxm@shuffle@temp@cnt}%
- \pgfmathrandom{\numexpr\value{question}-\value{rdxm@shuffle@temp@cnt}\relax}%
- \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
- \global\csletcs{rdxm@question@b@\the\value{rdxm@shuffle@temp@cnt}}{%
+ \pgfmathrandom{\numexpr\value{question}-1\relax}
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}
+ \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}
+ }{
+ \pgfmathrandom{\numexpr\value{question}-2\relax}
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}
+ \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}
+ }
+ %% no restrition for questions in the middle
+ \setcounter{rdxm@shuffle@temp@cnt}{1}
+ \whileboolexpr{
+ test{\ifnumless{\value{rdxm@shuffle@temp@cnt}}{\numexpr\value{question}-1\relax}}
+ }{
+ \stepcounter{rdxm@shuffle@temp@cnt}
+ \pgfmathrandom{\numexpr\value{question}-\value{rdxm@shuffle@temp@cnt}\relax}
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}
+ \global\csletcs{rdxm@question@b@\the\value{rdxm@shuffle@temp@cnt}}{
rdxm@question@a@\rdxm@list@item
- }%
- }%
- }{%
- \ifnumequal{\value{question}}{2}{%
- \global\csletcs{rdxm@question@b@1}{rdxm@question@a@2}%
- \global\csletcs{rdxm@question@b@2}{rdxm@question@a@1}%
- }{}%
- }%
+ }
+ }
+ }{
+ \ifnumequal{\value{question}}{2}{
+ \global\csletcs{rdxm@question@b@1}{rdxm@question@a@2}
+ \global\csletcs{rdxm@question@b@2}{rdxm@question@a@1}
+ }{}
+ }
}
-\newcommand{\printquestions}{%
- \ifrandom
+\newcommand{\printquestions}{
+ \ifbool{exam@random}{
\rdxm@appto@questions
\rdxm@shuffle@questions
- \setcounter{question}{0}%
+ \setcounter{question}{0}
\allquestions
- \fi
- \xdef\allquestions{}%
- \xdef\lastquestion{}%
+ }{}
+ \xdef\allquestions{}
+ \xdef\lastquestion{}
}
-\newcounter{rdxm@part}
-
\DeclareExamTemplate{exampart}{normal}{
\noindent
\textbf{
- \textcolor{part~number}{\UseExamTranslation{exampart-Part}~\Roman{rdxm@part}}
+ \textcolor{part~number}{
+ \MakeExamNameNumber{\UseExamTranslation{exampart-Part}}{\TheExamCounter{exampart}}
+ }
:~\UseExamValue{exampart}{type}
}
\space(\UseExamValue{exampart}{points})
@@ -513,21 +590,21 @@
\printquestions
\setcounter{totalquestions}{\value{totalquestions}+\value{question}}
\setcounter{question}{0}
- \stepcounter{rdxm@part}
+ \stepcounter{exampart}
\vspace{1em}
\begingroup
- \DeclareExamValue{exampart}{type}{#1}
- \DeclareExamValue{exampart}{points}{#2}
+ \SetExamValue{exampart}{type=#1,points=#2}
\UseExamTemplate{exampart}{default}
\endgroup
\par\nopagebreak
\if\relax\detokenize{#1}\relax % #1 is empty
- \onlyonequestiontrue
+ \booltrue{exam@onlyonequestion}
\else
- \onlyonequestionfalse
- \vspace{1em}%
+ \boolfalse{exam@onlyonequestion}
+ \vspace{1em}
\fi
- %其中设定了\@nobreaktrue,保证在列表前也不分页,详情见 source2e
+ % \@afterheading sets \@nobreaktrue, which will prevent page breaks before lists;
+ % see source2e
\@afterheading
}
@@ -542,7 +619,7 @@
\NewDocumentCommand\examdata{+m}{
\printquestions\rdxm@stop@random
- \DeclareExamValue{examdata}{caption}{#1}
+ \SetExamValue{examdata}{caption=#1}
\UseExamTemplate{examdata}{default}
}
@@ -550,12 +627,7 @@
\newcommand\ignorepars{\@ifnextchar\par{\expandafter\ignorepars\@gobble}{}}
-% local definition, valid only in current question
-\DeclareKeys[randexam-question]{
- points .store = \l@rdxm@question@points
- ,level .store = \l@rdxm@question@level
- ,year .store = \l@rdxm@question@year
-}
+\rdxm@declare@key@handler{question}
\newcommand\pointorpoints[1]{
\ifnumgreater{#1}{1}{
@@ -565,26 +637,28 @@
}
}
-\newcommand{\questionpointstext}[1]{ (#1 \pointorpoints{#1}) }
+\newcommand{\questionpointstext}[1]{ (#1~\pointorpoints{#1}) }
\newcommand\rdxm@hook@exec@other@keys{}
\newrobustcmd\execute@question@keys{
\rdxm@hook@exec@other@keys
- \ifdefvoid{\l@rdxm@question@points}{}{\questionpointstext{\l@rdxm@question@points}}
+ \IfExamValueExistT{question}{points}{
+ \questionpointstext{\UseExamValue{question}{points}}
+ }
}
\DeclareExamTemplate{questionbegin}{normal}{
- \ifresetnumber
- \ifonlyonequestion
- \renewcommand{\hangtext}{\qquad}%
- \else
+ \ifbool{exam@resetnumber}{
+ \ifbool{exam@onlyonequestion}{
+ \renewcommand{\hangtext}{\qquad}
+ }{
\renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question~number}{\arabic{question}}.}}\;\,}
- \fi
- \else
- \setcounter{questionreal}{\value{totalquestions}+\value{question}}%
+ }
+ }{
+ \setcounter{questionreal}{\value{totalquestions}+\value{question}}
\renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question~number}{\arabic{questionreal}}.}}\;\,}
- \fi
+ }
\settowidth{\hanglength}{\hangtext}
\description[leftmargin=\hanglength,labelwidth=0pt,labelsep=0pt,topsep=0pt,parsep=0pt]
\item[\hangtext]\execute@question@keys
@@ -597,7 +671,7 @@
\NewDocumentEnvironment{questionreal}{O{}}{
\stepcounter{question}
\setcounter{choice}{0}
- \SetKeys[randexam-question]{#1}
+ \SetKeys[randexam/question]{#1}
\UseExamTemplate{questionbegin}{default}
}{
\UseExamTemplate{questionend}{default}
@@ -628,30 +702,30 @@
\let \oldmedskip = \medskip
\let \oldbigskip = \bigskip
-\ifrandom
- \newcommand\rdxm@appto@questions{%
- \xappto\allquestions{\expandonce\lastquestion}%
- }%
- \NewEnviron{question}{%
- \stepcounter{question}%
+\ifbool{exam@random}{
+ \newcommand\rdxm@appto@questions{
+ \xappto\allquestions{\expandonce\lastquestion}
+ }
+ \NewEnviron{question}{
+ \stepcounter{question}
\rdxm@appto@questions
- \csxdef{rdxm@question@a@\the\value{question}}{%
- \unexpanded{\begin{questionreal}}%
- \unexpanded\expandafter{\BODY}%
- \unexpanded{\end{questionreal}}%
- }%
- \csxdef{rdxm@question@b@\the\value{question}}{%
- \expandonce{\csname rdxm@question@a@\the\value{question}\endcsname}%
- }%
- \xdef\lastquestion{%
- \expandonce{\csname rdxm@question@b@\the\value{question}\endcsname}%
- }%
+ \csxdef{rdxm@question@a@\the\value{question}}{
+ \unexpanded{\begin{questionreal}}
+ \unexpanded\expandafter{\BODY}
+ \unexpanded{\end{questionreal}}
+ }
+ \csxdef{rdxm@question@b@\the\value{question}}{
+ \expandonce{\csname rdxm@question@a@\the\value{question}\endcsname}
+ }
+ \xdef\lastquestion{
+ \expandonce{\csname rdxm@question@b@\the\value{question}\endcsname}
+ }
}
- \NewEnviron{solution}{%
- \csxappto{rdxm@question@a@\the\value{question}}{%
- \unexpanded{\begin{solutionreal}}%
- \expandonce{\BODY}%
- \unexpanded{\end{solutionreal}}%
+ \NewEnviron{solution}{
+ \csxappto{rdxm@question@a@\the\value{question}}{
+ \unexpanded{\begin{solutionreal}}
+ \expandonce{\BODY}
+ \unexpanded{\end{solutionreal}}
}%
}
\renewcommand{\newpage}{\gappto\lastquestion{\oldnewpage}}
@@ -659,54 +733,47 @@
\renewcommand{\smallskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldsmallskip}}
\renewcommand{\medskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldmedskip}}
\renewcommand{\bigskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldbigskip}}
-\else
+}{
\newenvironment{question}[1][]{\questionreal[#1]}{\endquestionreal}
%\newenvironment{solution}{\solutionreal}{\endsolutionreal}
\NewEnviron{solution}{\begin{solutionreal}\BODY\end{solutionreal}}
-\fi
+}
-\newcommand{\rdxm@stop@random}{%
- \ifrandom
- \renewenvironment{question}{\questionreal}{\endquestionreal}%
- \renewenvironment{solution}{\solutionreal}{\endsolutionreal}%
+\newcommand{\rdxm@stop@random}{
+ \ifbool{exam@random}{
+ \renewenvironment{question}{\questionreal}{\endquestionreal}
+ \renewenvironment{solution}{\solutionreal}{\endsolutionreal}
\let \newpage = \oldnewpage
\let \vfill = \oldvfill
\let \smallskip = \oldsmallskip
\let \medskip = \oldmedskip
\let \bigskip = \oldbigskip
- \fi
+ }{}
}
\def\CommentCutFile{\jobname.cut}
-\AtBeginDocument{%
- \ifanswer\else
- \excludecomment{solution}
- \fi
+\AtBeginDocument{
+ \ifbool{exam@answer}{}{\excludecomment{solution}}
}
%% ---------------------------------------------------------------------------
%% Command for answer tables: \answertable
%% ---------------------------------------------------------------------------
-%% property .store is the same as .tl_set:N in ltkeys.
-%% you need to put .code before .initial:n.
%% total: total number of questions in current exam part;
%% column: number of questions in each answer row;
%% strut: strut height in each answer rows;
%% notice: notice text before the answer table.
-\DeclareKeys[randexam-answertable]{
- total .code = \DeclareExamValue{answertable}{total}{#1}
- ,column .code = \DeclareExamValue{answertable}{column}{#1}
- ,strut .code = \DeclareExamValue{answertable}{strut}{#1}
- ,strut .initial:n = 1em
- ,notice .code = \DeclareExamValue{answertable}{notice}{#1}
- ,notice .initial:n = {Notice:~you~MUST~write~the~answers~in~the~following~tables.}
+\rdxm@declare@key@handler{answertable}
+\SetKeys[randexam/answertable]{
+ strut = 1em
+ ,notice = {Notice:~you~MUST~write~the~answers~in~the~following~tables.}
}
-\gdef\answer@lines@temp{}%
-\newcommand{\answer@lines@add}[1]{%
- \xdef\answer@lines@temp{\answer@lines@temp#1}%
+\gdef\answer@lines@temp{}
+\newcommand{\answer@lines@add}[1]{
+ \xdef\answer@lines@temp{\answer@lines@temp#1}
}
\newrobustcmd\answer@number@hided[1]{\UseExamTranslation{answertable-Number}}
@@ -719,38 +786,39 @@
\newcounter{answer@total}
%% #1: strut; #2: total; #3: column.
-\newcommand{\answer@lines}[3]{%
- \setcounter{answer@row}{(#2-1)/#3+1}% 除法向下取整,改为向上取整
+\newcommand{\answer@lines}[3]{
+ % change rounding down to rounding up in the division
+ \setcounter{answer@row}{(#2-1)/#3+1}
\begingroup
- \let\hline=\relax \let\\=\relax % 禁止展开
- \gdef\answer@lines@temp{}%
- \setcounter{answer@total}{1}%
+ \let\hline=\relax \let\\=\relax % forbid expansions
+ \gdef\answer@lines@temp{}
+ \setcounter{answer@total}{1}
\whileboolexpr{
test{\ifnumgreater{\value{answer@row}}{0}}
- }{%
- \addtocounter{answer@row}{-1}%
- \answer@lines@add{\answer@number@hided}%
- \setcounter{answer@col}{1}%
- \unlessboolexpr{%
- test{\ifnumgreater{\value{answer@col}}{#3}}%
- }{%
- \answer@lines@add{&}%
- \ifnumgreater{\value{answer@total}}{#2}{}{%
- \answer@lines@add{\arabic{answer@total}}%
- }%
- \stepcounter{answer@col}%
- \stepcounter{answer@total}%
- }%
- \answer@lines@add{\\ \hline \answer@cell@strut{#1}}%
- \setcounter{answer@col}{1}%
+ }{
+ \addtocounter{answer@row}{-1}
+ \answer@lines@add{\answer@number@hided}
+ \setcounter{answer@col}{1}
\unlessboolexpr{
test{\ifnumgreater{\value{answer@col}}{#3}}
- }{%
- \answer@lines@add{&}%
- \stepcounter{answer@col}%
- }%
- \answer@lines@add{\\ \hline}%
- }%
+ }{
+ \answer@lines@add{&}
+ \ifnumgreater{\value{answer@total}}{#2}{}{
+ \answer@lines@add{\arabic{answer@total}}
+ }
+ \stepcounter{answer@col}
+ \stepcounter{answer@total}
+ }
+ \answer@lines@add{\\ \hline \answer@cell@strut{#1}}
+ \setcounter{answer@col}{1}
+ \unlessboolexpr{
+ test{\ifnumgreater{\value{answer@col}}{#3}}
+ }{
+ \answer@lines@add{&}
+ \stepcounter{answer@col}
+ }
+ \answer@lines@add{\\ \hline}
+ }
\endgroup
\answer@lines@temp
}
@@ -767,7 +835,7 @@
\NewDocumentCommand\answertable{O{}}{
\begingroup
- \SetKeys[randexam-answertable]{#1}
+ \SetKeys[randexam/answertable]{#1}
\UseExamTemplate{answertable}{default}
\endgroup
\par\vspace{0.8em}
@@ -780,7 +848,7 @@
%% Command for multiple-choice questions: \pickin and \pickout
%% ---------------------------------------------------------------------------
-\newcommand{\answer}[1]{\ifanswer#1\else\phantom{#1}\fi}
+\newcommand{\answer}[1]{\ifbool{exam@answer}{#1}{\phantom{#1}}}
\newcommand*{\cdotfill}{\leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax}
@@ -798,18 +866,19 @@
\newcommand*{\fillout}[1]{\allowbreak\hbox{}\nobreak\ulinefill{#1}\underline{\color{blue}\answer{#1}}\ulinefill{#1}}
\newcommand*{\fillin}[1]{\underline{\hspace{1em}\color{blue}\minwidthbox{2em}{\answer{#1}}\hspace{1em}}}
-\newcommand*\pickoutreal[1]{%
- \unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})%
+\newcommand*\pickoutreal[1]{
+ \unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})
}
-\newcommand*\pickinreal[1]{%
+\newcommand*\pickinreal[1]{
\unskip\nobreak
- \hspace{0.3em}(\makebox[1.5em]{\color{blue}\answer{#1}})\hspace{0.3em}%
+ \hspace{0.3em}(\makebox[1.5em]{\color{blue}\answer{#1}})\hspace{0.3em}
\ignorespaces
}
-%% 选择题四个选项打乱顺序,用三种方法即可保证答案不同
+%% We choose three ways for shuffling four choices in a multiple-choice question
%% 1:ABCD -> CDAB; 2:ABCD -> BADC; 3: ABCD -> DCBA
-%% 即在两行排列时仅用到上下交换以及左右交换,这样可以保持两行长度不变
+%% In other word, we only exchange choices in the same row or column,
+%% so as to make the lengths of choice lines unchanged
\csdef{rdxm@shuffle@1@A}{C} \csdef{rdxm@shuffle@2@A}{B} \csdef{rdxm@shuffle@3@A}{D}
\csdef{rdxm@shuffle@1@B}{D} \csdef{rdxm@shuffle@2@B}{A} \csdef{rdxm@shuffle@3@B}{C}
@@ -819,33 +888,33 @@
\def\@rdxm@choice@random{0}
\newcommand\rdxm@shuffle@abcd[1]{\csuse{rdxm@shuffle@\@rdxm@choice@random @#1}}
-\newcommand*\pickout[1]{%
- \ifbool{random}{%
+\newcommand*\pickout[1]{
+ \ifbool{exam@random}{
\exam@set@seed
- \pgfmathrandominteger\@rdxm@choice@random{1}{3}%
+ \pgfmathrandominteger\@rdxm@choice@random{1}{3}
%\@rdxm@choice@random
- \pickoutreal{\rdxm@shuffle@abcd{#1}}%
- }{%
- \pickoutreal{#1}%
- }%
+ \pickoutreal{\rdxm@shuffle@abcd{#1}}
+ }{
+ \pickoutreal{#1}
+ }
}
-\newcommand*\pickoutfixed[1]{%
- \pickoutreal{#1}%
- \randomfalse
+\newcommand*\pickoutfixed[1]{
+ \pickoutreal{#1}
+ \boolfalse{exam@random}
}
-\newcommand*\pickin[1]{%
- \ifbool{random}{%
+\newcommand*\pickin[1]{
+ \ifbool{exam@random}{
\exam@set@seed
- \pgfmathrandominteger\@rdxm@choice@random{1}{3}%
+ \pgfmathrandominteger\@rdxm@choice@random{1}{3}
%\@rdxm@choice@random
- \pickinreal{\rdxm@shuffle@abcd{#1}}%
- }{%
- \pickinreal{#1}%
- }%
+ \pickinreal{\rdxm@shuffle@abcd{#1}}
+ }{
+ \pickinreal{#1}
+ }
}
-\newcommand*\pickinfixed[1]{%
- \pickinreal{#1}%
- \randomfalse
+\newcommand*\pickinfixed[1]{
+ \pickinreal{#1}
+ \boolfalse{exam@random}
}
%% ---------------------------------------------------------------------------
@@ -856,17 +925,17 @@
\newlength{\rdxm@item@len}
\newlength{\rdxm@label@len}
-\newcommand\rdxm@item@temp{%
- \unskip\cr\stepcounter{choice}(\Alph{choice})\ %
+\newcommand\rdxm@item@temp{
+ \unskip\cr\stepcounter{choice}(\Alph{choice})\
}
-\newcommand\rdxm@item@box{%
+\newcommand\rdxm@item@box{
\hfill\egroup\hfill\hbox to \rdxm@item@len\bgroup
\stepcounter{choice}(\Alph{choice})\ \ignorespaces
}
-\newcommand\rdxm@item@par{%
- \stepcounter{choice}%
- \def\rdxm@label@text{(\Alph{choice})\ }%
- \settowidth{\rdxm@label@len}{\rdxm@label@text}%
+\newcommand\rdxm@item@par{
+ \stepcounter{choice}
+ \def\rdxm@label@text{(\Alph{choice})\ }
+ \settowidth{\rdxm@label@len}{\rdxm@label@text}
\par \parshape 2 \hanglength \linewidth
\dimexpr\hanglength + \rdxm@label@len\relax
\dimexpr\linewidth - \rdxm@label@len\relax
@@ -875,87 +944,87 @@
\NewEnviron{abcdreal}{
\unskip
- \setlength{\parindent}{0pt}%
- \setlength{\parskip}{0pt}%
- \setcounter{choice}{0}%
+ \setlength{\parindent}{0pt}
+ \setlength{\parskip}{0pt}
+ \setcounter{choice}{0}
\let\item=\rdxm@item@temp
- \settowidth{\rdxm@item@len}{\vbox{\halign{##\hfil\cr\BODY\crcr}}}%
- \setcounter{choice}{0}%
+ \settowidth{\rdxm@item@len}{\vbox{\halign{##\hfil\cr\BODY\crcr}}}
+ \setcounter{choice}{0}
\ifdim\rdxm@item@len>0.486\linewidth
- \setlength{\rdxm@item@len}{\linewidth}%
+ \setlength{\rdxm@item@len}{\linewidth}
\let\item=\rdxm@item@par
\BODY\par
\else
\ifdim\rdxm@item@len>.243\linewidth
- \setlength{\rdxm@item@len}{0.5\linewidth}%
+ \setlength{\rdxm@item@len}{0.5\linewidth}
\else
- \setlength{\rdxm@item@len}{0.25\linewidth}%
+ \setlength{\rdxm@item@len}{0.25\linewidth}
\fi
\let\item=\rdxm@item@box
\par\bgroup\BODY\hfill\egroup\par
\fi
}
-\newcommand\rdxm@item@one@line{%
+\newcommand\rdxm@item@one@line{
\unskip
\ifnumequal{\value{choice}}{0}{}{\hfill}
- \stepcounter{choice}(\Alph{choice})\ %
+ \stepcounter{choice}(\Alph{choice})\
}
-\newcommand\rdxm@item@two@line{%
+\newcommand\rdxm@item@two@line{
\unskip
- \ifnumodd{\value{choice}}{&}{\unskip\cr}%
- \stepcounter{choice}(\Alph{choice})\ %
+ \ifnumodd{\value{choice}}{&}{\unskip\cr}
+ \stepcounter{choice}(\Alph{choice})\
}
\NewEnviron{abcd*real}{
\unskip
- \setlength{\parindent}{0pt}%
- \setlength{\parskip}{0pt}%
- \setcounter{choice}{0}%
+ \setlength{\parindent}{0pt}
+ \setlength{\parskip}{0pt}
+ \setcounter{choice}{0}
\let\item=\rdxm@item@one@line
- \settowidth{\rdxm@item@len}{\BODY}%
+ \settowidth{\rdxm@item@len}{\BODY}
\ifdim\rdxm@item@len<0.95\linewidth
- \setcounter{choice}{0}%
+ \setcounter{choice}{0}
\par\bgroup\BODY\hfill\hfill\par\egroup\par
\else
- \setcounter{choice}{0}%
+ \setcounter{choice}{0}
\let\item=\rdxm@item@two@line
- \settowidth{\rdxm@item@len}{\vbox{\halign{##&##\hfil\cr\BODY\crcr}}}%
+ \settowidth{\rdxm@item@len}{\vbox{\halign{##&##\hfil\cr\BODY\crcr}}}
\ifdim\rdxm@item@len<0.975\linewidth
- \setcounter{choice}{0}%
+ \setcounter{choice}{0}
\par\bgroup\nointerlineskip
- \vbox{\halign to\linewidth{##\hfil\tabskip=0pt plus 1fil&##\hfil\cr\BODY\crcr}}%
+ \vbox{\halign to\linewidth{##\hfil\tabskip=0pt plus 1fil&##\hfil\cr\BODY\crcr}}
\egroup\par
\else
- \setcounter{choice}{0}%
+ \setcounter{choice}{0}
\let\item=\rdxm@item@par
\par\bgroup\BODY\hfill\egroup\par
\fi
\fi
}
-\ifbool{random}{%
+\ifbool{exam@random}{
\csdef{rdxm@swap@items@1}#1#2#3#4{\item#3\item#4\item#1\item#2}
\csdef{rdxm@swap@items@2}#1#2#3#4{\item#2\item#1\item#4\item#3}
\csdef{rdxm@swap@items@3}#1#2#3#4{\item#4\item#3\item#2\item#1}
- \long\def\rdxm@swap@items#1\item#2\item#3\item#4\item#5\@rdxm@stop@mark{%
- #1\csuse{rdxm@swap@items@\@rdxm@choice@random}{#2}{#3}{#4}{#5}%
+ \long\def\rdxm@swap@items#1\item#2\item#3\item#4\item#5\@rdxm@stop@mark{
+ #1\csuse{rdxm@swap@items@\@rdxm@choice@random}{#2}{#3}{#4}{#5}
}
}{}
-\NewDocumentEnvironment{abcd}{+b}{%
- \ifbool{random}{%
- \begin{abcdreal}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcdreal}%
- }{%
- \begin{abcdreal}#1\end{abcdreal}%
- }%
+\NewDocumentEnvironment{abcd}{+b}{
+ \ifbool{exam@random}{
+ \begin{abcdreal}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcdreal}
+ }{
+ \begin{abcdreal}#1\end{abcdreal}
+ }
}{}
-\NewDocumentEnvironment{abcd*}{+b}{%
- \ifbool{random}{%
- \begin{abcd*real}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcd*real}%
- }{%
- \begin{abcd*real}#1\end{abcd*real}%
- }%
+\NewDocumentEnvironment{abcd*}{+b}{
+ \ifbool{exam@random}{
+ \begin{abcd*real}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcd*real}
+ }{
+ \begin{abcd*real}#1\end{abcd*real}
+ }
}{}
%% ---------------------------------------------------------------------------
@@ -971,8 +1040,8 @@
%% Use freealign package to align math formulas in different lines
%% ---------------------------------------------------------------------------
-\AtBeginDocument{%
- \ifbool{freealign}{\RequirePackage{freealign}}{}%
+\AtBeginDocument{
+ \ifbool{exam@freealign}{\RequirePackage{freealign}}{}
}
%% ---------------------------------------------------------------------------
@@ -982,31 +1051,31 @@
\PassOptionsToPackage{tbtags}{amsmath}
\RequirePackage{amsmath}
-\newcommand{\solutionpointstext}[1]{%
- \textcolor{red}{#1\kern0.15em\pointorpoints{#1}}%
+\newcommand{\solutionpointstext}[1]{
+ \textcolor{red}{#1\kern0.15em\pointorpoints{#1}}
}
-\newcommand{\pointstext}[1]{%
- \mbox{}\nobreak\hfill$\cdots\cdots$\solutionpointstext{#1}%
+\newcommand{\pointstext}[1]{
+ \mbox{}\nobreak\hfill$\cdots\cdots$\solutionpointstext{#1}
\par\noindent\ignorespaces
}
\newcommand{\pointseqno}[1]{\eqno{\cdots\cdots\text{\solutionpointstext{#1}}}}
\newcommand{\pointstag}[1]{\tag*{$\cdots\cdots$\solutionpointstext{#1}}}
-\newrobustcmd{\points}[1]{%
- \ifbool{mmode}{%
- \ifdefstrequal{\tag}{\dft@tag}{\pointseqno{#1}}{\pointstag{#1}}%
- }{%
- \pointstext{#1}%
- }%
+\newrobustcmd{\points}[1]{
+ \ifbool{mmode}{
+ \ifdefstrequal{\tag}{\dft@tag}{\pointseqno{#1}}{\pointstag{#1}}
+ }{
+ \pointstext{#1}
+ }
}
%% ---------------------------------------------------------------------------
%% Use medium-size fractions and operators in both inline and displayed formulas
%% ---------------------------------------------------------------------------
-\AtBeginDocument{%
- \ifbool{medmath}{\RequirePackage{medmath}}{}%
+\AtBeginDocument{
+ \ifbool{exam@medmath}{\RequirePackage{medmath}}{}
}
%% ---------------------------------------------------------------------------
@@ -1022,150 +1091,268 @@
\setlength\arraycolsep{4pt}
-\RequirePackage{diagbox}
-%% 修正 \diagbox 在 array 环境中使用的问题
-\newrobustcmd{\diagboxtwo}[3][]{%
- \ifbool{mmode}{%
- \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}}%
- }{%
- \diagbox[#1]{#2}{#3}%
+\newrobustcmd\rdxm@moremath@diagbox{
+ \RequirePackage{diagbox}
+ %% Fix problem in using \diagbox in array environment
+ \newrobustcmd{\diagboxtwo}[3][]{
+ \ifbool{mmode}{
+ \hbox{\let\tabcolsep=\arraycolsep\diagbox[##1]{$##2$}{$##3$}}
+ }{
+ \diagbox[##1]{##2}{##3}
+ }
+ }
+ \newrobustcmd{\diagboxthree}[4][]{
+ \ifbool{mmode}{
+ \hbox{\let\tabcolsep=\arraycolsep\diagbox[##1]{$##2$}{$##3$}{$##4$}}
+ }{
+ \diagbox[##1]{##2}{##3}{##4}
+ }
}
}
-\newrobustcmd{\diagboxthree}[4][]{%
- \ifbool{mmode}{%
- \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}{$#4$}}%
- }{%
- \diagbox[#1]{#2}{#3}{#4}%
+
+\newrobustcmd\rdxm@moremath@limits{
+ \AtBeginDocument{
+ \let\rdxm@saved@lim=\lim \def\lim{\rdxm@saved@lim\limits}
+ \let\rdxm@saved@sum=\sum \def\sum{\rdxm@saved@sum\limits}
+ \let\rdxm@saved@prod=\prod \def\prod{\rdxm@saved@prod\limits}
}
}
-\RequirePackage{mathtools} % \mathllap 命令,pmatrix* 环境等
-\RequirePackage{extarrows}
-
-\AtBeginDocument{%
- \let\rdxm@saved@lim=\lim \def\lim{\rdxm@saved@lim\limits}%
- \let\rdxm@saved@sum=\sum \def\sum{\rdxm@saved@sum\limits}%
- \let\rdxm@saved@prod=\prod \def\prod{\rdxm@saved@prod\limits}%
-}
-
-\newcommand{\e}{\mathrm{e}}
-\newcommand{\R}{\mathbb{R}}
-
-\DeclareMathOperator{\arccot}{arccot}
-\DeclareMathOperator{\Corr}{\rho}
-\DeclareMathOperator{\Cov}{Cov}
-\DeclareMathOperator{\diag}{diag}
-\DeclareMathOperator{\grad}{grad}
-\DeclareMathOperator{\Prj}{Prj}
-\DeclareMathOperator{\tr}{tr}
-\DeclareMathOperator{\Var}{Var}
-
-\DeclareMathOperator{\diver}{div}
-\let\division=\div
-\let\div=\diver
-
-\newcommand{\diff}{\mathop{}\!\mathrm{d}}
-\newcommand{\dx}{\diff x}
-\newcommand{\dy}{\diff y}
-\def\dz{\diff z} % 不确定命令是否已经定义
-\newcommand{\du}{\diff u}
-\newcommand{\dv}{\diff v}
-\newcommand{\dr}{\diff r}
-\newcommand{\ds}{\diff s}
-\newcommand{\dt}{\diff t}
-\newcommand{\dS}{\diff S}
-% 有些宏包比如 hyperref 会修改 \d 的定义,所以放在 document 开始处
-% 利用 etoolbox 将 \d 定义为健壮命令,以避免在 align 等环境中错误地展开
-\AtBeginDocument{%
- \let\oldd=\d
- \renewrobustcmd{\d}{\ifbool{mmode}{\diff}{\oldd}}%
-}
-
-\let\pd=\partial
-\newcommand{\pdf}{\pd f}
-\newcommand{\pdg}{\pd g}
-\newcommand{\pdh}{\pd h}
-\newcommand{\pdl}{\pd l}
-\newcommand{\pdn}{\pd n}
-\newcommand{\pdu}{\pd u}
-\newcommand{\pdv}{\pd v}
-\newcommand{\pdx}{\pd x}
-\newcommand{\pdy}{\pd y}
-\newcommand{\pdz}{\pd z}
-\newcommand{\pdF}{\pd F}
-\newcommand{\pdL}{\pd L}
-\newcommand{\pdP}{\pd P}
-\newcommand{\pdQ}{\pd Q}
-\newcommand{\pdR}{\pd R}
-
-% from mathabx package
-\DeclareFontFamily{U}{mathx}{\hyphenchar\font45}
-\DeclareFontShape{U}{mathx}{m}{n}{<-> mathx10}{}
-\DeclareSymbolFont{mathx}{U}{mathx}{m}{n}
-\DeclareMathAccent{\widebar}{0}{mathx}{"73}
-
-\newcommand{\va}{\vec{a}}
-\newcommand{\vb}{\vec{b}}
-\newcommand{\vc}{\vec{c}}
-\newcommand{\vd}{\vec{d}}
-\newcommand{\ve}{\vec{e}}
-\newcommand{\vi}{\vec{i}}
-\newcommand{\vj}{\vec{j}}
-\newcommand{\vk}{\vec{k}}
-\newcommand{\vn}{\vec{n}}
-\newcommand{\vs}{\vec{s}}
-\newcommand{\vv}{\vec{v}}
-
-\let\ov=\overrightarrow
-
-\let\le=\leqslant
-\let\ge=\geqslant
-
-\let\lb=\{
-\let\rb=\}
-
-\def\T{\mathrm{T}\kern-.5pt}
-
-% 分数线长一点的分数,\wfrac[2pt]{x}{y} 表示左右加 2pt
-% 和前面的 medmath 一样,将代码放在 \AtBeginDocument 里
-\AtBeginDocument{%
- \newrobustcmd{\wfrac}[3][2pt]{%
- \frac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
- }%
- \newrobustcmd{\wdfrac}[3][2pt]{%
- \dfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
- }%
- \newrobustcmd{\wtfrac}[3][2pt]{%
- \tfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
- }%
+\newrobustcmd\rdxm@moremath@differential{
+ \newcommand{\diff}{\mathop{}\!\mathrm{d}}
+ \newcommand{\dx}{\diff x}
+ \newcommand{\dy}{\diff y}
+ \def\dz{\diff z} % not sure whether it has been defined
+ \newcommand{\du}{\diff u}
+ \newcommand{\dv}{\diff v}
+ \newcommand{\dr}{\diff r}
+ \newcommand{\ds}{\diff s}
+ \newcommand{\dt}{\diff t}
+ \newcommand{\dS}{\diff S}
+ %% Some packages such as hyperref will modify the definition of \d,
+ %% so we put the code in \AtBeginDocument.
+ %% Also we define \d as a protected command, so as to avoid wrong expansions of
+ %% it at the beginning of math arrays such as align from amsmath package.
+ \AtBeginDocument{
+ \let\oldd=\d
+ \renewrobustcmd{\d}{\ifbool{mmode}{\diff}{\oldd}}
+ }
+ \let\pd=\partial
+ \newcommand{\pdf}{\pd f}
+ \newcommand{\pdg}{\pd g}
+ \newcommand{\pdh}{\pd h}
+ \newcommand{\pdl}{\pd l}
+ \newcommand{\pdn}{\pd n}
+ \newcommand{\pdu}{\pd u}
+ \newcommand{\pdv}{\pd v}
+ \newcommand{\pdx}{\pd x}
+ \newcommand{\pdy}{\pd y}
+ \newcommand{\pdz}{\pd z}
+ \newcommand{\pdF}{\pd F}
+ \newcommand{\pdL}{\pd L}
+ \newcommand{\pdP}{\pd P}
+ \newcommand{\pdQ}{\pd Q}
+ \newcommand{\pdR}{\pd R}
+}
+
+\newrobustcmd\rdxm@moremath@widebar{
+ %% from mathabx package
+ \DeclareFontFamily{U}{mathx}{\hyphenchar\font45}
+ \DeclareFontShape{U}{mathx}{m}{n}{<-> mathx10}{}
+ \DeclareSymbolFont{mathx}{U}{mathx}{m}{n}
+ \DeclareMathAccent{\widebar}{0}{mathx}{"73}
+}
+
+\newrobustcmd\rdxm@moremath@vector{
+ \newcommand{\va}{\vec{a}}
+ \newcommand{\vb}{\vec{b}}
+ \newcommand{\vc}{\vec{c}}
+ \newcommand{\vd}{\vec{d}}
+ \newcommand{\ve}{\vec{e}}
+ \newcommand{\vi}{\vec{i}}
+ \newcommand{\vj}{\vec{j}}
+ \newcommand{\vk}{\vec{k}}
+ \newcommand{\vn}{\vec{n}}
+ \newcommand{\vs}{\vec{s}}
+ \newcommand{\vv}{\vec{v}}
+}
+
+\newrobustcmd\rdxm@moremath@widefrac{
+ %% Longer fraction rules, \wfrac[2pt]{x}{y} will add 2pt to the left and right
+ \AtBeginDocument{
+ \newrobustcmd{\wfrac}[3][2pt]{
+ \frac{\hspace{##1}##2\hspace{##1}}{\hspace{##1}##3\hspace{##1}}
+ }
+ \newrobustcmd{\wdfrac}[3][2pt]{
+ \dfrac{\hspace{##1}##2\hspace{##1}}{\hspace{##1}##3\hspace{##1}}
+ }
+ \newrobustcmd{\wtfrac}[3][2pt]{
+ \tfrac{\hspace{##1}##2\hspace{##1}}{\hspace{##1}##3\hspace{##1}}
+ }
+ }
}
-% 使用 stix font 中的 white arrows
-\AtBeginDocument{\@ifpackageloaded{fontspec}{%
+\newrobustcmd\rdxm@moremath@whitearrow{
+ %% 使用 stix font 中的 white arrows
+ \AtBeginDocument{\@ifpackageloaded{fontspec}{
%\IfFileExists{STIX-Regular.otf}{% 在 TeXLive 中无效
- \IfFileExists{stix.sty}{%
- \newfontfamily{\@rdxm@stix}{STIX} % stix v1.1
- }{%
- \newfontfamily{\@rdxm@stix}{STIXGeneral} % stix v1.0
+ \IfFileExists{stix.sty}{
+ \newfontfamily{\@rdxm@stix}{STIX} % stix v1.1
+ }{
+ \newfontfamily{\@rdxm@stix}{STIXGeneral} % stix v1.0
}
- \newrobustcmd\leftwhitearrow{%
- \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E6}}}%
+ \newrobustcmd\leftwhitearrow{
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E6}}}
}
- \newrobustcmd\upwhitearrow{%
- \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E7}}}%
+ \newrobustcmd\upwhitearrow{
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E7}}}
}
- \newrobustcmd\rightwhitearrow{%
- \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E8}}}%
+ \newrobustcmd\rightwhitearrow{
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E8}}}
}
- \newrobustcmd\downwhitearrow{%
- \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E9}}}%
+ \newrobustcmd\downwhitearrow{
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E9}}}
}
-}{%
+ }{
\let \leftwhitearrow = \Leftarrow
\let \rightwhitearrow = \Rightarrow
\let \upwhitearrow = \Uparrow
\let \downwhitearrow = \Downarrow
-}}
+ }}
+}
+
+\newrobustcmd\rdxm@moremath@miscellaneous{
+ \RequirePackage{mathtools} % for \mathllap command,pmatrix* environment
+ \RequirePackage{extarrows}
+ \newcommand{\e}{\mathrm{e}}
+ \newcommand{\R}{\mathbb{R}}
+ \DeclareMathOperator{\arccot}{arccot}
+ \DeclareMathOperator{\Corr}{\rho}
+ \DeclareMathOperator{\Cov}{Cov}
+ \DeclareMathOperator{\diag}{diag}
+ \DeclareMathOperator{\grad}{grad}
+ \DeclareMathOperator{\Prj}{Prj}
+ \DeclareMathOperator{\tr}{tr}
+ \DeclareMathOperator{\Var}{Var}
+ \DeclareMathOperator{\diver}{div}
+ \let\division=\div
+ \let\div=\diver
+ \let\ov=\overrightarrow
+ \let\le=\leqslant
+ \let\ge=\geqslant
+ \let\lb=\{
+ \let\rb=\}
+ \def\T{\mathrm{T}\kern-.5pt}
+}
+
+\ifbool{exam@moremath}{
+ \rdxm@moremath@diagbox
+ \rdxm@moremath@limits
+ \rdxm@moremath@differential
+ \rdxm@moremath@widebar
+ \rdxm@moremath@vector
+ \rdxm@moremath@widefrac
+ \rdxm@moremath@whitearrow
+ \rdxm@moremath@miscellaneous
+}{}
+
+%% ---------------------------------------------------------------------------
+%% Load local user config file
+%% ---------------------------------------------------------------------------
+
+\InputIfFileExists{randexam.cfg}{}{}
+
+%% ---------------------------------------------------------------------------
+%% Support for Chinese Language
+%% ---------------------------------------------------------------------------
+
+\newrobustcmd\rdxm@chinese@ctex{
+ %% 四号 小四号 五号 小五号
+ %% 14bp 12bp 10.5bp 9bp
+ %% 实际上,在旧版本 ctex 中只能用 cs4size 和 c5size 选项
+ %% 而新版本 ctex 中,可以利用 zihao 选项指定各种中文字号
+ \PassOptionsToPackage{CJKnumber}{xeCJK}
+ \RequirePackage[cs4size,UTF8,noindent,heading]{ctex}
+ \ifbool{exam@plain}{\pagestyle{plain}}{\pagestyle{fancy}}
+ %% 在旧版本 xeCJK 中,必须用 CJKnumber 选项载入 CJKnumb 包,后面才载入会报错
+ %% 但在新版本 xeCJK 中 CJKnumber 选项已经被废弃,需要在后面自行载入它
+ %% 在 xeCJK 中已经禁止载入 CJK,但是在新版本 ctex 宏包中却失效了
+ %% 我们假装 CJK 已经载入,再载入 CJKnumb,避免出现 \CJKglue 重复定义的问题
+ %% 注意用 PDFLaTeX 编译时需要用到 CJK,所以只在未定义时才作修改
+ \ifdefined\CJKglue
+ \@namedef{ver@CJK.sty}{}
+ %\@namedef{opt@CJK.sty}{}
+ \fi
+ \RequirePackage{CJKnumb}
+ %% 新版本 xeCJK 已经废弃并禁用 CJKfntef,改用 xeCJKfntef 取代,我们需要载入后者
+ %% 注意要保证能在较旧的 TeX 系统中编译,我们只能用 \ifXeTeX 而不能用 \ifxetex
+ %% 因为旧版本 iftex 宏包只有 \ifXeTeX 命令,而 ifxetex 宏包才有 \ifxetex 命令
+ %% 在 2019 年 10 月,LaTeX 开发团队接管了 iftex 宏包,新版本同时提供这两个命令
+ \RequirePackage{CJKfntef}
+ \RequirePackage{iftex}
+ \ifXeTeX\@ifpackagelater{xeCJK}{2020/02/10}{\RequirePackage{xeCJKfntef}}{}\fi
+ \ifbool{XeTeX}{
+ % https://en.wikipedia.org/wiki/Number_Forms
+ % Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ、Ⅵ、Ⅶ、Ⅷ、Ⅸ、Ⅹ、Ⅺ、Ⅻ
+ \xeCJKsetcharclass{"2150}{"218F}{1} % 斜线分数,全角罗马数字等
+ % https://en.wikipedia.org/wiki/Enclosed_Alphanumerics
+ \xeCJKsetcharclass{"2460}{"24FF}{1} % 带圈数字字母,括号数字字母,带点数字等
+ }{}
+}
+\ifbool{exam@ctex}{\rdxm@chinese@ctex}{}
+
+\newrobustcmd\rdxm@chinese@sourcehan{
+ \setCJKmainfont[BoldFont=Source~Han~Sans~SC]{Source~Han~Serif~SC}
+ \setCJKsansfont{Source~Han~Sans~SC}
+ %% 用中文字体名时 LuaTeX 找不到该字体,XeTeX 正常
+ %\setCJKmainfont[BoldFont=思源黑体]{思源宋体}
+ %\setCJKsansfont{思源黑体}
+}
+\AtBeginDocument{
+ \ifbool{exam@sourcehan}{
+ \ifbool{XeTeX}{\rdxm@chinese@sourcehan}{
+ \ifbool{LuaTeX}{\rdxm@chinese@sourcehan}{}
+ }
+ }{}
+}
+
+%% 这里不能用 \ifbool,因为涉及到 catcode 的改变
+\ifexam@solidot
+ \ifXeTeX
+ \catcode`。=\active\def。{.}
+ \else\ifLuaTeX
+ \catcode`。=\active\def。{.}
+ \fi
+ \fi
+\fi
+
+%% Chinese translations of keywords
+\DeclareExamTranslation{chinese}{
+ answertable-Answer = 答案
+ ,answertable-Number = 小题
+ ,examdata-Appendix = 附录
+ ,exampart-Part = {第,部分}
+ ,examtitle-Name = 姓名
+ ,examtitle-Solutions = 试卷解答
+ ,gradetable-Evaluator = 评阅人
+ ,gradetable-Part = 部分
+ ,gradetable-Score = 得分
+ ,gradetable-Total = 总分
+ ,headfoot-Name = 姓名
+ ,headfoot-of = {共,页}
+ ,headfoot-Page = {第,页}
+ ,headfoot-Solutions = 试卷解答
+ ,headfoot-Version = {\relax,卷}
+ ,points-point = 分
+ ,points-points = 分
+ ,question-Question = 题
+ ,solution-Solution = 解
+}
+\ifbool{exam@ctex}{\SelectExamTranslation{chinese}}{}
+
+%% ---------------------------------------------------------------------------
+%% Stop ignoring spaces in the code
+%% ---------------------------------------------------------------------------
\IgnoreSpacesOff