summaryrefslogtreecommitdiff
path: root/macros/latex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-02-04 03:00:55 +0000
committerNorbert Preining <norbert@preining.info>2024-02-04 03:00:55 +0000
commit16f68bbec3cca735a695904227872abc2ace1f90 (patch)
treebcabe1bea02359da24036bb8e3a9741751516a84 /macros/latex
parent8d5a9f6bbecb297f513b9ed16e574db1c1310228 (diff)
CTAN sync 202402040300
Diffstat (limited to 'macros/latex')
-rw-r--r--macros/latex/contrib/exesheet/README.md17
-rw-r--r--macros/latex/contrib/exesheet/exesheet.dtx169
-rw-r--r--macros/latex/contrib/exesheet/exesheet.ins4
-rw-r--r--macros/latex/contrib/exesheet/exesheet.pdfbin330415 -> 334627 bytes
-rw-r--r--macros/latex/contrib/hvqrurl/Changes1
-rw-r--r--macros/latex/contrib/hvqrurl/doc/hvqrurl.pdfbin113856 -> 115679 bytes
-rw-r--r--macros/latex/contrib/hvqrurl/doc/hvqrurl.tex10
-rw-r--r--macros/latex/contrib/hvqrurl/latex/hvqrurl.sty17
-rw-r--r--macros/latex/contrib/projlib/ProjLib.dtx84
-rw-r--r--macros/latex/contrib/projlib/ProjLib.ins4
-rw-r--r--macros/latex/contrib/projlib/README.md8
-rw-r--r--macros/latex/contrib/randexam/randexam-a-answer.pdfbin49496 -> 49588 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-a-answer.tex8
-rw-r--r--macros/latex/contrib/randexam/randexam-a-blank.pdfbin41288 -> 41374 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-b-answer.pdfbin49469 -> 49570 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-b-blank.pdfbin41229 -> 41309 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam.cls1131
-rw-r--r--macros/latex/contrib/randexam/randexam.pdfbin50412 -> 52431 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam.tex102
-rw-r--r--macros/latex/contrib/tagpdf/README.md4
-rw-r--r--macros/latex/contrib/tagpdf/ex-AF-file.pdf56
-rw-r--r--macros/latex/contrib/tagpdf/ex-alt-actualtext.pdfbin34295 -> 34295 bytes
-rw-r--r--macros/latex/contrib/tagpdf/ex-attribute.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-formula-problem.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-list.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-softhyphen.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf14
-rw-r--r--macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf50
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-backend.dtx8
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-checks.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-code.pdfbin1662036 -> 1673023 bytes
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-data.dtx18
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx6
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx6
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-roles.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-space.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-struct.dtx6
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-tree.dtx4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf-user.dtx191
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf.dtx6
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf.pdfbin1095221 -> 1103561 bytes
-rw-r--r--macros/latex/contrib/tagpdf/tagpdf.tex4
-rw-r--r--macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty2
-rw-r--r--macros/latex/contrib/wargame/README.md2
-rw-r--r--macros/latex/contrib/wargame/doc/compat.pdfbin432819 -> 435053 bytes
-rw-r--r--macros/latex/contrib/wargame/doc/symbols.pdfbin184525 -> 186882 bytes
-rw-r--r--macros/latex/contrib/wargame/doc/tutorial/export.tex14
-rw-r--r--macros/latex/contrib/wargame/doc/tutorial/game.pdfbin588181 -> 590545 bytes
-rw-r--r--macros/latex/contrib/wargame/doc/wargame.pdfbin1444437 -> 1469771 bytes
-rw-r--r--macros/latex/contrib/wargame/source/Makefile2
-rw-r--r--macros/latex/contrib/wargame/source/chit/battle.dtx2
-rw-r--r--macros/latex/contrib/wargame/source/chit/misc.dtx52
-rw-r--r--macros/latex/contrib/wargame/source/chit/modifiers.dtx2
-rw-r--r--macros/latex/contrib/wargame/source/chit/oob.dtx197
-rw-r--r--macros/latex/contrib/wargame/source/chit/shape.dtx13
-rw-r--r--macros/latex/contrib/wargame/source/chit/table.dtx58
-rw-r--r--macros/latex/contrib/wargame/source/hex/labels.dtx2
-rw-r--r--macros/latex/contrib/wargame/source/hex/ridges.dtx5
-rw-r--r--macros/latex/contrib/wargame/source/hex/terrain.dtx24
-rw-r--r--macros/latex/contrib/wargame/source/tests/chits.dtx14
-rw-r--r--macros/latex/contrib/wargame/source/tests/test.tex13
-rw-r--r--macros/latex/contrib/wargame/source/util/export.dtx216
-rw-r--r--macros/latex/contrib/wargame/source/util/tikz.dtx17
-rwxr-xr-xmacros/latex/contrib/wargame/source/utils/wgexport.py971
67 files changed, 2585 insertions, 1049 deletions
diff --git a/macros/latex/contrib/exesheet/README.md b/macros/latex/contrib/exesheet/README.md
index 6ce9032857..1c56562c44 100644
--- a/macros/latex/contrib/exesheet/README.md
+++ b/macros/latex/contrib/exesheet/README.md
@@ -3,14 +3,19 @@
## Presentation
-The exesheet package is designed for typesetting exercise or exam sheets.
-Additionally, the exesheet class loads the schooldocs package.
-
-This package offers the following features:
+The exesheet package is designed for typesetting exercise or exam sheets.
+The primary advantage of exesheet is its ability to display
+a detailed scoring guide and correction instructions as needed.
+This feature is especially beneficial for grading papers with multiple graders.
+
+Additionally, the exesheet class loads the schooldocs package
+which manages the page layout, the main title, headers and footers.
+
+The exesheet package offers the following features:
- macros for organizing exercises and subparts,
- specific settings for enumeration lists,
-- environments for questions and answers, with conditional display,
-- macros to display a marking scheme with detailed comments in the margins.
+- environments for questions and answers, which can be displayed or hidden,
+- macros for detailed comments and grading instructions in the margins which can be displayed or hidden.
## Installation
diff --git a/macros/latex/contrib/exesheet/exesheet.dtx b/macros/latex/contrib/exesheet/exesheet.dtx
index efc56a4cf9..02a8f5e68c 100644
--- a/macros/latex/contrib/exesheet/exesheet.dtx
+++ b/macros/latex/contrib/exesheet/exesheet.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 2020-2023 by Antoine Missier <antoine.missier@ac-toulouse.fr>
+% Copyright (C) 2020-2024 by Antoine Missier <antoine.missier@ac-toulouse.fr>
% ----------------------------------------------------------------------
%
% This file may be distributed and/or modified under the
@@ -23,7 +23,7 @@
%<class>\ProvidesClass{exesheet}
%<package>\ProvidesPackage{exesheet}
%<*class|package>
-[2023/12/30 v2.5 .dtx Typesetting exercise or exam sheets]
+[2024/02/03 v2.6 .dtx Typesetting exercise or exam sheets]
%</class|package>
%<*driver>
\documentclass{ltxdoc}
@@ -45,6 +45,7 @@
\usepackage{pstricks}
\usepackage{array}
\usepackage{spacingtricks}
+\usepackage{pifont}
%
\psset{unit=1cm}
\geometry{textwidth=355pt,vmarginratio=1:1,hmarginratio=3:2}
@@ -84,7 +85,7 @@
%</driver>
% \fi
%
-% \CheckSum{1183}
+% \CheckSum{1192}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
@@ -173,6 +174,10 @@
% - comparison with other packages
% - modifying introduction}
%
+% \changes{v2.6}{2024/02/03}{
+% - error message when using colsenum or colsitem without loading multicol
+% - changes in the comparison with other packages}
+%
% \GetFileInfo{exesheet.dtx}
%
% \maketitle
@@ -182,7 +187,8 @@
% \section{Introduction}
%
% The \textsf{exesheet} \emph{package} is designed for typesetting exercise or exam sheets.
-% Additionally, the \textsf{exesheet} \emph{class} loads the \textsf{schooldocs} package.
+% Additionally, the \textsf{exesheet} \emph{class} loads the
+% \textsf{schooldocs} package~\cite{SCHOOL}.
% The latter makes adjustments to margins and titles, and defines various layout styles
% with specific headers and footers suitable for exercise sheets, among other uses.
% Refer to the documentation of the \textsf{schooldocs} package for more details.
@@ -256,9 +262,6 @@
% Calculate $1+1$.
%
% \bigskip
-% ^^A Various settings can be modified by refining the following commands.
-%
-% ^^A \medskip
% \DescribeMacro{\exercisename}
% The term ``\exercisename'' is automatically translated into various languages
% \footnote{Currently, translation is integrated into the package
@@ -314,7 +317,6 @@
% To begin, prepare your cup of tea.
% \subpart
% Now you are ready to proceed with the current exercise.
-% \bigskip
%
% \pagebreak
% The following macros allow customization in the same manner as for |\exercise|.
@@ -589,8 +591,8 @@
% The mandatory parameter is the number of columns,
% and the optional parameter will be passed to the underlying \texttt{enumerate} environment,
% allowing you to change the numbering type (\eg a, A, etc.), among other possibilities.
-% To use this environment, you need to load the
-% \textsf{multicol} package in the preamble.
+% \emph{To use this environment, you need to load the
+% \textsf{multicol} package in the preamble.}
% Here's an example with |\begin{colsenum}{3}|:
%
% \exercise
@@ -643,9 +645,10 @@
% \texttt{tablitem}. It follows the same syntax as \texttt{colsenum}:
% |\begin{colsitem}|\oarg{opt}\marg{cols}. The optional parameter,
% passed to the underlying \texttt{itemize} environment,
-% permits the modification of the item label (bullet by default).
+% allow to change the item label (bullet by default).
% Furthermore, just like \texttt{colsenum*}, the \texttt{colsitem*} environment
% produces column alignment from the bottom.
+% \emph{The \textsf{multicol} package is also required and must be loaded in the preamble.}
%
% \section{Questions and solutions}
%
@@ -710,7 +713,8 @@
% \textsf{exframe} by Niklas Beisert,
% \textsf{exam} by Philip Hirschhorn,
% \textsf{answers} by Mike Piff and Joseph Wright,
-% \textsf{probsoln} by Nicola Talbot, and more.
+% \textsf{probsoln} by Nicola Talbot,
+% \textsf{eqexam} by D. P. Story\ldots
% They are briefly presented in section \ref{comparison}.
% \end{enumerate}
% \end{answers}
@@ -798,8 +802,8 @@
% Some teachers are accustomed to providing their students with documents
% where questions are typeset, leaving blank spaces instead of answers.
% This layout allows students to fill in their responses on the paper.
-% To achieve this, thanks to a suggestion from Maxime Chupin,
-% we offer the |\answerspace|\marg{height} macro,
+% Thanks to a suggestion from Maxime Chupin,
+% we achieve this with the |\answerspace|\marg{height} macro,
% in which the parameter \meta{height} is a valid length,
% \eg |\answerspace{3cm}|.
%
@@ -1184,7 +1188,7 @@
% answerspace & true, \textbf{false} & \ref{answerspace}\\
% display & \textbf{none}, pts, notes & \ref{pts}, \ref{margin} \\
% marginpos & \textbf{left} (inner), right (\textbf{outer}) & \ref{pts}, \ref{margin} \\
-% marginwidth & standard, \textbf{expand}, unset & \ref{margin} \\
+% marginwidth & standard, \textbf{expand}, unset & \ref{margin} \\
% noteragged & \textbf{left}, right, center, justify, twoside & \ref{margin} \\
% checkpts & true, \textbf{false} & \ref{scale} \\
% correct & true, \textbf{false}, conditional & \hyperlink{correct}{see below} \\
@@ -1225,11 +1229,10 @@
%
% Prior to version 2.0, we used specialized commands to configure
% output and display options.
-% Thanks to a suggestion from Maxime Chupin and Denis Bitouzé,
-% we have now implemented \emph{key=value} options.
-% Although the latter is more user-friendly,
+% We have now implemented \emph{key=value} options.
+% Although the latter are more user-friendly,
% one may prefer the old commands, so they are still supported,
-% but will trigger a warning message. They are presented below.
+% but will trigger a warning message. These commands are presented below.
%
% However, the previous options \texttt{nosetlist} and \texttt{notoc}
% are no longer supported.
@@ -1243,12 +1246,12 @@
% The commands |\displaypts| and |\displaypoints|
% are equivalent to setting \texttt{display=pts}.
%
-% \medskip
+% \bigskip
% \DescribeMacro{\displaynotes}\DescribeMacro{\displaynotesright}
% |\displaynotes| means \texttt{display=notes},
% and |\displaynotesright| corresponds to
% \texttt{display=notes,marginpos=right}.
-% These two commands have an optional argument |\displanotes|\marg{ragged}
+% These two commands have an optional argument |\displaynotes|\marg{ragged}
% where \meta{ragged} is an alignment command to work inside margin notes.
% By default it is |\RaggedLeft| with |\displaynotes| and |RaggedRight|
% \footnote{These commands come from the \textsf{ragged2e} package
@@ -1258,19 +1261,19 @@
% \subsection{Comparison with other packages}\label{comparison}
%
% In this section, we will provide an overview of the functionalities (as of today \today)
-% of various packages or classes found in the 'Exercise' or 'Exam' sections
+% of various packages or classes found in the `Exercise' or `Exam' sections
% of the CTAN archives
% (Comprehensive \TeX\ Archive Network).
% Considering the substantial number of packages in these sections,
% some omissions may have been unintentionally made.
% Those excluded are those with documentation not in English
% or primarily dedicated to producing multiple-choice questions
-% or random question generation. Are also excluded those with non-free license.
-% We have focused here on typesetting functionalities and not on managing exercise databases
-% as there are specialized packages or external softwares for that.
+% or random question generation.
+% We have focused here on typesetting functionalities and not on managing exercise
+% databases as there are specialized packages or external softwares for that.
%
% The following table is not a result of tests but presents a summary of information
-% obtained from the documentation of these packages.
+% collected from the documentation of these packages.
%
% \begin{multicols}{2}
% \begin{flushleft}
@@ -1279,42 +1282,44 @@
% \item \textsf{exercises}, Roger Jud~\cite{EXES}
% \item \textsf{xsim}, Clemens Niederberger~\cite{XSIM}
% \item \textsf{exframe}, Niklas Beisert~\cite{EXFR}
-% \item \textsf{exam}, Philip Hirschhorn~\cite{EXAM}.
+% \item \textsf{exam}, Philip Hirschhorn~\cite{EXAM}
% \item \textsf{answers}, Mike Piff and Joseph Wright~\cite{ANSW}
% \item \textsf{probsoln}, Nicola L.C.\@ Talbot~\cite{PROB}
% \item \textsf{exsol}, Walter Daems~\cite{EXSO}
% \item \textsf{exercisepoints}, Henning Kerstan~\cite{EXEP}
% \item \textsf{worksheet}, Benjamin Zöllner~\cite{WORK}
-% \item \textsf{exam-n}, Norman Gray, CTAN~\cite{EXAN}
+% \item \textsf{exam-n}, Norman Gray~\cite{EXAN}
% \item \textsf{eqexam}, D. P. Story~\cite{EQEX}
% \item \textsf{cesenaexam}, Alex Pacini~\cite{CESE}
+% \item \textsf{esami}, Grazia Messineo, Salvatore Vassallo~\cite{ESAMI}
+% \item \textsf{randexam}, Jianrui Lyu~\cite{RAND}
% \item \textsf{hideanswer}, Yukoh Kusakabe~\cite{HIDE}
-% \item \textsf{mathexam}, Jan Hlavacek~\cite{MATH}
+% ^^A\item \textsf{mathexam}, Jan Hlavacek~\cite{MATH}
% \item \textsf{exesheet}, Antoine Missier
% \end{enumerate}
% \end{flushleft}
% \end{multicols}
%
-% \newcommand\X{\textsf{X}}
+% \newcommand\X{\ding{56}}
% \setlength{\extrarowheight}{2pt}
-% \noindent\begin{tabular}{|@{\hspace{2pt}}l@{\hspace{4pt}}|%
-% *{16}{@{\hspace{2pt}}c@{\hspace{2pt}}|}}
+% \noindent\begin{tabular}{@{\hspace{1.8pt}}l@{\hspace{2pt}}|%
+% *{17}{@{\hspace{1.8pt}}c@{\hspace{1.8pt}}|}}
% \hline
-% Functionality &A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&P \\
+% Functionality &A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&P&Q \\
% \hline
-% optional text for exercise titles &\X&&\X&\X&\X&&&&\X&&&&&&&\X \\
-% subparts of exercises &\X&&&\X&\X&&&&&&\X&&\X&&&\X \\
-% annex title &&&&&&&&&&&&&&&&\X \\
-% exercise titles in TOC of PDF files &\X&&&&&&&&&&&&&&&\X \\
-% short labels for exercises &\X&&&&&&&&&&&&&&&\X \\
-% hiding questions or answers* &\X&*&\X&\X&\X&*&\X&\X&&&*&\X&&*&&\X \\
-% different placements for answers &\X&&\X&&&&&&&&&\X&&&&\X \\
-% changing answers placement in output &\X&&\X&\X&&\X&&&&&&\X&&&& \\
-% blank spacing in place of answers &&&&&\X&&&&&&&\X&&&\X&\X \\
-% marking scheme commands &&\X&\X&\X&\X&&&&\X&\X&\X&\X&&&&\X \\
-% various positions of points &&&&&\X&&&&&&&\X&&&&\X \\
-% marking scheme calculation/checking &&\X&\X&\X&\X&&&&\X&&&&&&&\X \\
-% detailed notes for scoring guide &&&&&&&&&&&&&&&&\X \\
+% Optional text for exercise titles &\X&&\X&\X&\X&&&&\X&&&&\X&&&&\X \\
+% Subparts of exercises &\X&&&\X&\X&&&&\X&&\X&\X&\X&\X&\X&&\X \\
+% Annex title or appendix &&&&&&&&&&&&&&&\X&&\X \\
+% Exercise titles in TOC of PDF files &\X&&&&&&&&&&&&&&&&\X \\
+% Short labels for exercises &\X&&\X&\X&&&&&&&&&&&&&\X \\
+% Hiding questions or answers* &\X&*&\X&\X&*&\X&\X&\X&&&*&\X&&\X&*&*&\X \\
+% Different placements for answers &\X&&&&&&&&&&\X&\X&&&&&\X \\
+% Change answers placement in output &\X&&&\X&&\X&&\X&&&&\X&&&&& \\
+% Blank spacing in place of answers &&\X&\X&&\X&&&&&&&\X&&\X&\X&&\X \\
+% Marking scheme commands &&\X&\X&\X&\X&&&&\X&\X&\X&\X&&\X&\X&&\X \\
+% Various positions of points &&&&\X&\X&&&&&&&\X&&\X&&&\X \\
+% Marking scheme calculation/checking &&\X&\X&\X&\X&&&&\X&&\X&\X&&&\X&&\X \\
+% Detailed notes for scoring guide &&&&&&&&&&&&&&&&&\X \\
% \hline
% \end{tabular}
% \medskip
@@ -1802,11 +1807,20 @@
\end{tablitem}}
% \end{macrocode}
-% \DescribeEnv{colsenum}
+% \DescribeEnv{colsenum}\DescribeEnv{colsenum*}
+% For items aligned by columns, we provide the \texttt{colsemnum} and \texttt{colsenum*}
+% environments. The \textsf{multicol} package is required and an error message
+% is produced if it has not been loaded.
+% |\multicolsep| is the amount of space that should be added above or below the
+% environment.
% \begin{macrocode}
-\newenvironment{colsenum}[2][]{%
+\newenvironment{colsenum*}[2][]{%
+ \ifexesheet@multicol \else
+ \PackageError{exesheet}{The environments colsenum and colsenum*
+ \MessageBreak need the multicol package}{
+ Add \string\usepackage{multicol}\space in the preamble.}
+ \fi
\setlength{\multicolsep}{2ex}
- \raggedcolumns % default is \flushcolumns
\begin{multicols}{#2} % #2 = number of columns
\begin{enumerate}[#1] % #1 = options of enumerate
}{
@@ -1814,41 +1828,36 @@
\end{multicols}
}
-% \end{macrocode}
-% \DescribeEnv{colsenum*}
-% \begin{macrocode}
-\newenvironment{colsenum*}[2][]{%
- \setlength{\multicolsep}{2ex}
- \begin{multicols}{#2} % #2 = number of columns
- \begin{enumerate}[#1] % #1 = options of enumerate
+\newenvironment{colsenum}[2][]{%
+ \raggedcolumns % default is \flushcolumns
+ \begin{colsenum*}[#1]{#2}
}{
- \end{enumerate}
- \end{multicols}
+ \end{colsenum*}
}
% \end{macrocode}
-% \DescribeEnv{colsitem}
+% \DescribeEnv{colsitem}\DescribeEnv{colsitem*}
+% The corresponding environments for itemize lists.
% \begin{macrocode}
-\newenvironment{colsitem}[2][]{%
+\newenvironment{colsitem*}[2][]{%
+ \ifexesheet@multicol \else
+ \PackageError{exesheet}{The environments colsitem and colsitem*
+ \MessageBreak need the multicol package}{
+ Add \string\usepackage{multicol}\space in the preamble.}
+ \fi
\setlength{\multicolsep}{2ex}
- \raggedcolumns
- \begin{multicols}{#2}
- \begin{itemize}[#1]
+ \begin{multicols}{#2} % #2 = number of columns
+ \begin{itemize}[#1] % #1 = options of itemize
}{
\end{itemize}
\end{multicols}
}
-% \end{macrocode}
-% \DescribeEnv{colsitem*}
-% \begin{macrocode}
-\newenvironment{colsitem*}[2][]{%
- \setlength{\multicolsep}{2ex}
- \begin{multicols}{#2}
- \begin{itemize}[#1]
+\newenvironment{colsitem}[2][]{%
+ \raggedcolumns % default is \flushcolumns
+ \begin{colsitem*}[#1]{#2}
}{
- \end{itemize}
- \end{multicols}
+ \end{colsitem*}
}
% \end{macrocode}
@@ -2024,8 +2033,8 @@
% \end{macrocode}
%
% \begin{macro}{\answerspace}
-% The |\answerspace| macro was suggested by Maxime Chupin
-% to allow students space for writing their answers on the provided paper.
+% The |\answerspace| macro leaves blank space to allow students for writing
+% their answers on the provided paper following a suggestion by Maxime Chupin.
% \begin{macrocode}
\newcommand\answerspace[1]{
\ifexesheet@answerspace \par\vspace{#1} \fi}
@@ -2563,11 +2572,13 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{thebibliography}{24}
+% \begin{thebibliography}{27}
% % \begin{raggedright}
+% \bibitem{SCHOOL} \emph{The \textsf{schooldocs} package}, Antoine Missier,
+% CTAN, v1.4 2023/12/28.
% \bibitem{GEOM} \emph{The \textsf{geometry} package},
% Hideo Umeki, CTAN, v5.9 2020/01/02.
-% \bibitem{ENUM} \emph{Customizing lists with teh \textsf{enumitem} package},
+% \bibitem{ENUM} \emph{Customizing lists with the \textsf{enumitem} package},
% Javier Bezos, CTAN, v3.9 2019/06/20.
% \bibitem{TASK} \emph{\textsf{tasks} -- lists with columns filled horizontally},
% Clemens Niederberger. CTAN, v1.4a, 2022/01/08.
@@ -2591,7 +2602,7 @@
% the official successor of the \textsf{exsheets} package}, Clemens Niederberger,
% CTAN, v0.21 2022/02/12.
% \bibitem{EXFR} \emph{The \textsf{exframe} package}, Niklas Beisert,
-% CTAN, v3.4 202/02/24.
+% CTAN, v3.4 2020/02/24.
% \bibitem{EXAM} \emph{Using the \textsf{exam} document class}, Philip Hirschhorn,
% CTAN, v2.704 2023/07/09.
% \bibitem{ANSW} \emph{\textsf{answers} Production of solution sheets in \LaTeXe},
@@ -2608,6 +2619,10 @@
% D. P. Story, CTAN, 5.2 2021/02/26.
% \bibitem{CESE} \emph{\textsf{cesenaexam} — class file to typeset exams}, Alex Pacini,
% CTAN, v2.0 2017/08/03.
+% \bibitem{ESAMI} \emph{Package \textsf{esami}}, Grazia Messineo, Salvatore Vassallo,
+% CTAN, v2.8 2023/07/21.
+% \bibitem{RAND} \emph{Teh \textsf{randexam} class for \LaTeX}, Jianrui Lyu,
+% CTAN, 2024D, 2024/02/03.
% \bibitem{HIDE} \emph{The \textsf{hideanswer} package: generate documents with
% and without answers by toggling a switch}, Yukoh Kusakabe, CTAN, v1.1 2022/07/09.
% \bibitem{MATH} \emph{The \textsf{mathexam} Package}, Jan Hlavacek, CTAN, v1.00 2007/07/30.
diff --git a/macros/latex/contrib/exesheet/exesheet.ins b/macros/latex/contrib/exesheet/exesheet.ins
index 4784c5b955..d1fc87865f 100644
--- a/macros/latex/contrib/exesheet/exesheet.ins
+++ b/macros/latex/contrib/exesheet/exesheet.ins
@@ -1,5 +1,5 @@
%%
-%% Copyright (C) 2020-2023 by Antoine Missier <antoine.missier@ac-toulouse.fr>
+%% Copyright (C) 2020-2024 by Antoine Missier <antoine.missier@ac-toulouse.fr>
%%
%% This file may be distributed and/or modified under the conditions of
%% the LaTeX Project Public License, either version 1.3 of this license
@@ -21,7 +21,7 @@
This is a generated file.
-Copyright (C) 2020-2023 by Antoine Missier <antoine.missier@ac-toulouse.fr>
+Copyright (C) 2020-2024 by Antoine Missier <antoine.missier@ac-toulouse.fr>
This file may be distributed and/or modified under the conditions of
the LaTeX Project Public License, either version 1.3 of this license
diff --git a/macros/latex/contrib/exesheet/exesheet.pdf b/macros/latex/contrib/exesheet/exesheet.pdf
index be92d96cc5..b18f1858e7 100644
--- a/macros/latex/contrib/exesheet/exesheet.pdf
+++ b/macros/latex/contrib/exesheet/exesheet.pdf
Binary files differ
diff --git a/macros/latex/contrib/hvqrurl/Changes b/macros/latex/contrib/hvqrurl/Changes
index a14d35f255..e7b6ca476c 100644
--- a/macros/latex/contrib/hvqrurl/Changes
+++ b/macros/latex/contrib/hvqrurl/Changes
@@ -1,4 +1,5 @@
hvqrurl.sty:
+0.06 2024-02-03 - fix for introduced bug with linktext
0.05a 2024-02-02 - modified documentation
0.05 2024-01-28 - added optional argument for alternative link text
0.04 2024-01-18 - fix for wrong text
diff --git a/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf b/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf
index 0ea564f2d7..b5103b9d16 100644
--- a/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf
+++ b/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf
Binary files differ
diff --git a/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex b/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex
index 5b0e10dc06..79c2c395ea 100644
--- a/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex
+++ b/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex
@@ -1,4 +1,4 @@
-%% $Id: hvqrurl.tex 867 2024-02-02 09:03:16Z herbert $
+%% $Id: hvqrurl.tex 870 2024-02-03 20:38:44Z herbert $
\listfiles
\errorcontextlines=100
\documentclass[twoside=on,usegeometry]{scrartcl}
@@ -82,6 +82,8 @@ QR codes not as a link when using \LPack{hyperref}:
\subsection{No link with \LPack{hyperref}}
+This needs package hyperref, which is loaded by default. With the optional argument
+\Lkeyword{nohyperref} you can prevent the loading of this package.
\begin{lstlisting}
With qrlink=nolink the QR code is no link: \hvqrurl[qrlink=nolink]{https://mirror.ctan.org/pkg/hvqrurl}.
@@ -89,7 +91,11 @@ The default setting is qrlink=link.
\end{lstlisting}
With \Lkeyset{qrlink=nolink} the QR code is no link: \hvqrurl[qrlink=nolink]{https://mirror.ctan.org/pkg/hvqrurl}.
The default setting is \Lkeyset{qrlink=link}. Without using \LPack{hyperref} this optional argument
-has no meaning.
+has no meaning. The optional argument \Lkeyword{linktext} is also only valid, if hyperref is aktive.
+
+
+
+
\subsection{Color of the QR code}
Without using \LPack{hyperref} the default color is \Lkeyval{black}. It can be changed by
diff --git a/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty b/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty
index 9786732d94..36f90a2638 100644
--- a/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty
+++ b/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty
@@ -1,4 +1,4 @@
-%% $Id: hvqrurl.sty 867 2024-02-02 09:03:16Z herbert $
+%% $Id: hvqrurl.sty 870 2024-02-03 20:38:44Z herbert $
%%
%% This file is distributed under the terms of the LaTeX Project Public
%% License from CTAN archives in directory macros/latex/base/lppl.txt.
@@ -7,7 +7,7 @@
% Copyright 2019,21,23,24 Herbert Voss hvoss@tug.org
%%
\ProvidesPackage{hvqrurl}[%
- 2024/02/02 v.0.05a (Herbert Voss) Supports qr images into the margin (hv)]
+ 2024/02/03 v.0.06 (Herbert Voss) Supports qr images into the margin (hv)]
%
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{url}
@@ -16,6 +16,12 @@
\RequirePackage{qrcode}
\RequirePackage{xkeyval}
+\newif\if@no@hyperref \@no@hyperreffalse
+\DeclareOption{nohyperref}{\@no@hyperreftrue}
+\ProcessOptions
+
+\if@no@hyperref\else\RequirePackage{hyperref}\fi
+
\newlength\qr@url@qrheight
\newlength\qr@url@qradjust
@@ -36,19 +42,22 @@
\def\hvqr@url*{\hvqr@@url}
+
\newcommand*\hvqr@@url[2][]{%
\begingroup
\providecommand*\qr@blank{0}%
\ifx\relax#1\relax \else\hvqrset{#1}\fi
+ % Set options for package qrcode
\expandafter\qrset\expandafter{\qr@url@qrlink,height=\qr@url@qrheight,level=\qr@url@qrlevel}%
\ifhv@qrreverse\reversemarginpar\fi
\if@tempswa
- \ifx\relax\qr@url@linktext\relax % alternative link text??
+ \ifx\@empty\qr@url@linktext % alternative link text
\edef\hv@foo{\detokenize\expandafter{#2}}%
+ \url{\hv@foo}%
\else
\edef\hv@foo{\detokenize\expandafter{\qr@url@linktext}}%
+ \href{#2}{\hv@foo}%
\fi
- \expandafter\url\expandafter{\hv@foo}%
\fi
\edef\reserved@a{\noexpand\marginnote{\noexpand\color{qr@url@qrcolor}\noexpand\qrcode{%
\detokenize\expandafter{#2}}}[\qr@url@qradjust]}%
diff --git a/macros/latex/contrib/projlib/ProjLib.dtx b/macros/latex/contrib/projlib/ProjLib.dtx
index fcac850e84..1172d3e4ad 100644
--- a/macros/latex/contrib/projlib/ProjLib.dtx
+++ b/macros/latex/contrib/projlib/ProjLib.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 2021-2023 by Jinwen XU
+% Copyright (C) 2021-2024 by Jinwen XU
% ------------------------------------
%
% This file may be distributed and/or modified under the conditions of the LaTeX
@@ -19,85 +19,85 @@
%<*ProjLib>
\ProvidesExplPackage
{ProjLib}
- {2023/11/05} {}
+ {2024/02/03} {}
{Collective interface of the ProjLib toolkit}
%</ProjLib>
%
%<*projlib-author>
\ProvidesExplPackage
{projlib-author}
- {2023/11/05} {}
+ {2024/02/03} {}
{Enhanced author information block}
%</projlib-author>
%
%<*projlib-datetime>
\ProvidesExplPackage
{projlib-datetime}
- {2023/11/05} {}
+ {2024/02/03} {}
{Convert numeric date-time string to natural language}
%</projlib-datetime>
%
%<*projlib-draft>
\ProvidesExplPackage
{projlib-draft}
- {2023/11/05} {}
+ {2024/02/03} {}
{Useful commands during draft stage}
%</projlib-draft>
%
%<*projlib-font>
\ProvidesExplPackage
{projlib-font}
- {2023/11/05} {}
+ {2024/02/03} {}
{Font selection and configuration}
%</projlib-font>
%
%<*projlib-language>
\ProvidesExplPackage
{projlib-language}
- {2023/11/05} {}
+ {2024/02/03} {}
{Multi-language configuration}
%</projlib-language>
%
%<*projlib-logo>
\ProvidesExplPackage
{projlib-logo}
- {2023/11/05} {}
+ {2024/02/03} {}
{The ProjLib logo}
%</projlib-logo>
%
%<*projlib-math>
\ProvidesExplPackage
{projlib-math}
- {2023/11/05} {}
+ {2024/02/03} {}
{Efficient math setup}
%</projlib-math>
%
%<*projlib-paper>
\ProvidesExplPackage
{projlib-paper}
- {2023/11/05} {}
+ {2024/02/03} {}
{Configuration of the paper style}
%</projlib-paper>
%
%<*projlib-text>
\ProvidesExplPackage
{projlib-text}
- {2023/11/05} {}
+ {2024/02/03} {}
{Text-related commands}
%</projlib-text>
%
%<*projlib-theorem>
\ProvidesExplPackage
{projlib-theorem}
- {2023/11/05} {}
+ {2024/02/03} {}
{Configuration of theorem-like environments}
%</projlib-theorem>
%
%<*projlib-titlepage>
\ProvidesExplPackage
{projlib-titlepage}
- {2023/11/05} {}
- {Commands for rendering the title page}
+ {2024/02/03} {}
+ {Interface for title page rendering}
%</projlib-titlepage>
%<*ProjLib>
@@ -5521,9 +5521,12 @@
\tl_set_eq:NN \thepage \l_projlib_titlepage_license_page_name_tl
\thispagestyle{empty}
\null\vfill
- \begin{flushleft}
+ % \begin{flushleft}
+ \group_begin:
+ \noindent
\tl_use:N \l_projlib_titlepage_info_tl
- \end{flushleft}
+ \group_end:
+ % \end{flushleft}
\group_begin:
\tl_use:N \l_projlib_titlepage_license_tl
\group_end:
@@ -5532,38 +5535,37 @@
\pagenumbering{roman}
}
+
\cs_new_protected:Nn \projlib_titlepage_render_with_style_default:
{
\begin{tikzpicture}[overlay,remember~picture]
- \fill [color=titlepage-main] ($(current~page.south~west)$) rectangle ($(current~page.north~east)+(0,-.3\paperheight)$);
- \fill [color=titlepage-back] ($(current~page.south~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$);
- \fill [color=titlepage-main] ($(current~page.north~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$);
- \fill [color=titlepage-back] ($(current~page.north~east)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$);
+ % \fill[color=white] ($(current~page.south~west)$) rectangle ($(current~page.north~east)$);
\node[text~width=.3\paperwidth, text~height=.2\paperheight, align=flush~left]
- at ($(current~page.north~west)+(.333\paperwidth,-.17\paperheight)$)
+ at ($(current~page.north~west)+(.32\paperwidth,-.1\paperheight)$)
{
\projlib_titlepage_show_logo:n { \scalebox { 2 } { \ProjLib } }
};
\node[text~width=.8\paperwidth, text~height=.5\paperheight, align=flush~left]
- at ($(current~page.north~west)+(.583\paperwidth,-.28\paperheight)$)
+ at ($(current~page.north~west)+(.57\paperwidth,-.15\paperheight)$)
{
- \color{titlepage-back}
\sffamily
\fontsize{24pt}{36pt}\selectfont
- \textsc{ \l_projlib_titlepage_title_tl }\\[1.5em]
+ \textsc{ \textbf{ \l_projlib_titlepage_title_tl } }\\[1.5em]
\fontsize{18pt}{27pt}\selectfont
\l_projlib_titlepage_subtitle_tl
};
- \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left]
- at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$)
+ % \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left]
+ % at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$)
+ \node[text~width=.8\paperwidth, text~height=.4\paperheight, align=flush~left]
+ at ($(current~page.south~west)+(.57\paperwidth,.45\paperheight)$)
{
- \color{titlepage-back}
- \begin{flushright}
+ % \color{.!50}
+ % \begin{flushright}
\fontsize{16pt}{24pt}\selectfont
\textsc{ \l_projlib_titlepage_author_tl }\\[1em]
\fontsize{12pt}{18pt}\selectfont
\l_projlib_titlepage_date_tl
- \end{flushright}
+ % \end{flushright}
};
\end{tikzpicture}
}
@@ -5634,36 +5636,38 @@
\end{tikzpicture}
}
-\cs_new_protected:Nn \projlib_titlepage_render_with_style_minimalist:
+\cs_new_protected:Nn \projlib_titlepage_render_with_style_fancy:
{
\begin{tikzpicture}[overlay,remember~picture]
- % \fill[color=white] ($(current~page.south~west)$) rectangle ($(current~page.north~east)$);
+ \fill [color=titlepage-main] ($(current~page.south~west)$) rectangle ($(current~page.north~east)+(0,-.3\paperheight)$);
+ \fill [color=titlepage-back] ($(current~page.south~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$);
+ \fill [color=titlepage-main] ($(current~page.north~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$);
+ \fill [color=titlepage-back] ($(current~page.north~east)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$);
\node[text~width=.3\paperwidth, text~height=.2\paperheight, align=flush~left]
- at ($(current~page.north~west)+(.32\paperwidth,-.2\paperheight)$)
+ at ($(current~page.north~west)+(.333\paperwidth,-.17\paperheight)$)
{
\projlib_titlepage_show_logo:n { \scalebox { 2 } { \ProjLib } }
};
\node[text~width=.8\paperwidth, text~height=.5\paperheight, align=flush~left]
- at ($(current~page.north~west)+(.57\paperwidth,-.22\paperheight)$)
+ at ($(current~page.north~west)+(.583\paperwidth,-.28\paperheight)$)
{
+ \color{titlepage-back}
\sffamily
\fontsize{24pt}{36pt}\selectfont
\textsc{ \l_projlib_titlepage_title_tl }\\[1.5em]
\fontsize{18pt}{27pt}\selectfont
\l_projlib_titlepage_subtitle_tl
};
- % \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left]
- % at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$)
- \node[text~width=.8\paperwidth, text~height=.4\paperheight, align=flush~left]
- at ($(current~page.south~west)+(.57\paperwidth,.45\paperheight)$)
+ \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left]
+ at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$)
{
- \color{.!50}
- % \begin{flushright}
+ \color{titlepage-back}
+ \begin{flushright}
\fontsize{16pt}{24pt}\selectfont
\textsc{ \l_projlib_titlepage_author_tl }\\[1em]
\fontsize{12pt}{18pt}\selectfont
\l_projlib_titlepage_date_tl
- % \end{flushright}
+ \end{flushright}
};
\end{tikzpicture}
}
diff --git a/macros/latex/contrib/projlib/ProjLib.ins b/macros/latex/contrib/projlib/ProjLib.ins
index 19afe26f96..67c129761e 100644
--- a/macros/latex/contrib/projlib/ProjLib.ins
+++ b/macros/latex/contrib/projlib/ProjLib.ins
@@ -1,5 +1,5 @@
%%
-%% Copyright (C) 2021-2023 by Jinwen XU
+%% Copyright (C) 2021-2024 by Jinwen XU
%%
%% This file may be distributed and/or modified under the conditions of
%% the LaTeX Project Public License, either version 1.3c of this license
@@ -20,7 +20,7 @@
\ds@heading% This is file... generated with the docstrip utility.
\MetaPrefix%
-Copyright (C) 2021-2023 by Jinwen XU
+Copyright (C) 2021-2024 by Jinwen XU
This is part of the ProjLib Toolkit.
}%
diff --git a/macros/latex/contrib/projlib/README.md b/macros/latex/contrib/projlib/README.md
index b9b4816d75..f7f7c70dbe 100644
--- a/macros/latex/contrib/projlib/README.md
+++ b/macros/latex/contrib/projlib/README.md
@@ -1,11 +1,11 @@
-<!-- Copyright (C) 2021-2023 by Jinwen XU -->
+<!-- Copyright (C) 2021-2024 by Jinwen XU -->
<!-- ![image](https://github.com/Jinwen-XU/ProjLib/raw/main/logo/ProjLib-logo.png) -->
<div align=center><img height="150" src="https://github.com/Jinwen-XU/ProjLib/raw/main/logo/ProjLib-logo.png"/></div>
# The `ProjLib` Toolkit
-> **This bundle is dated 2023/11/05.**
+> **This bundle is dated 2024/02/03.**
> **New documentations are still being written. For now, only the core code is included in TeX Live 2023 (old documentations have been removed from the distribution).**
@@ -63,8 +63,8 @@ The modules include:
- Supporting the modes `simple name` and `complex name` for the referencing names.
- `\SwitchTheoremNumbering` and `\DisableTheoremNumbering` for manipulating the numbering.
- Preset environments include: `application`, `assertion`, `assumption`, `axiom`, `claim`, `conclusion`, `conjecture`, `construction`, `convention`, `corollary`, `definition`, `definition-proposition`, `definition-theorem`, `example`, `exercise`, `fact`, `hypothesis`, `lemma`, `notation`, `observation`, `postulate`, `problem`, `property`, `proposition`, `question`, `recall`, `remark`, `theorem`, and the corresponding unnumbered version with an asterisk `*` in the name.
-1. module `titlepage` - *Commands for rendering the title page*
- - Currently support four title page styles: `default`, `academic`, `minimalist` and `simple`.
+1. module `titlepage` - *Interface for title page rendering*
+ - Currently support four title page styles: `default`, `academic`, `simple` and `fancy`.
> Since the module `theorem` uses `cleveref`, it should be loaded after `varioref` and `hyperref` (same for the main package `ProjLib`).
diff --git a/macros/latex/contrib/randexam/randexam-a-answer.pdf b/macros/latex/contrib/randexam/randexam-a-answer.pdf
index d7d570e9b2..6c62155246 100644
--- a/macros/latex/contrib/randexam/randexam-a-answer.pdf
+++ b/macros/latex/contrib/randexam/randexam-a-answer.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-a-answer.tex b/macros/latex/contrib/randexam/randexam-a-answer.tex
index fdfec30618..bd1cbc9f70 100644
--- a/macros/latex/contrib/randexam/randexam-a-answer.tex
+++ b/macros/latex/contrib/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/macros/latex/contrib/randexam/randexam-a-blank.pdf b/macros/latex/contrib/randexam/randexam-a-blank.pdf
index 1a85a26f4c..dcc54e2939 100644
--- a/macros/latex/contrib/randexam/randexam-a-blank.pdf
+++ b/macros/latex/contrib/randexam/randexam-a-blank.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-b-answer.pdf b/macros/latex/contrib/randexam/randexam-b-answer.pdf
index 349d3a80d9..c6be0a3b3d 100644
--- a/macros/latex/contrib/randexam/randexam-b-answer.pdf
+++ b/macros/latex/contrib/randexam/randexam-b-answer.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-b-blank.pdf b/macros/latex/contrib/randexam/randexam-b-blank.pdf
index 5ee6962d09..17ea5a41ab 100644
--- a/macros/latex/contrib/randexam/randexam-b-blank.pdf
+++ b/macros/latex/contrib/randexam/randexam-b-blank.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam.cls b/macros/latex/contrib/randexam/randexam.cls
index d103dfe558..105d3de168 100644
--- a/macros/latex/contrib/randexam/randexam.cls
+++ b/macros/latex/contrib/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
diff --git a/macros/latex/contrib/randexam/randexam.pdf b/macros/latex/contrib/randexam/randexam.pdf
index 2faabec1c8..307234cc1c 100644
--- a/macros/latex/contrib/randexam/randexam.pdf
+++ b/macros/latex/contrib/randexam/randexam.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam.tex b/macros/latex/contrib/randexam/randexam.tex
index feb1af2e14..382375dc11 100644
--- a/macros/latex/contrib/randexam/randexam.tex
+++ b/macros/latex/contrib/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/macros/latex/contrib/tagpdf/README.md b/macros/latex/contrib/tagpdf/README.md
index b64c5a23fa..96a566d03f 100644
--- a/macros/latex/contrib/tagpdf/README.md
+++ b/macros/latex/contrib/tagpdf/README.md
@@ -1,6 +1,6 @@
#tagpdf — A package to create tagged pdf
-Packageversion: 0.98t
-Packagedate: 2024/01/26
+Packageversion: 0.98u
+Packagedate: 2024/02/02
Author: Ulrike Fischer, LaTeX Project Team
## License
diff --git a/macros/latex/contrib/tagpdf/ex-AF-file.pdf b/macros/latex/contrib/tagpdf/ex-AF-file.pdf
index 8837751559..facd2a1003 100644
--- a/macros/latex/contrib/tagpdf/ex-AF-file.pdf
+++ b/macros/latex/contrib/tagpdf/ex-AF-file.pdf
@@ -1,11 +1,11 @@
%PDF-2.0
%
24 0 obj
-<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20240126205826+01'00') /Size 151 /CheckSum (885A66112CFA800687C687B2EED39FAC) >> /Length 151 >>
+<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<</ModDate (D:20240202223648+01'00') /Size 151 /CheckSum (4DDBEE0D3BD25827365AF72681239698) >> /Length 151 >>
stream
%% LaTeX2e file `example-input-file.tex'
%% generated by the `filecontents' environment
-%% from source `ex-AF-file' on 2024/01/26.
+%% from source `ex-AF-file' on 2024/02/02.
%%
Additional info!
@@ -15,7 +15,7 @@ endobj
<< /Type /Filespec /AFRelationship /Unspecified /F <FEFF006500780061006D0070006C0065002D0069006E007000750074002D00660069006C0065002E007400650078> /UF <FEFF006500780061006D0070006C0065002D0069006E007000750074002D00660069006C0065002E007400650078> /EF<</F 24 0 R/UF 24 0 R>> >>
endobj
27 0 obj
-<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20240126) >> /Length 19 >>
+<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20240202) >> /Length 19 >>
stream
Bär with teh shirt
endstream
@@ -24,7 +24,7 @@ endobj
<< /Type /Filespec /AFRelationship /Supplement /F <FEFF007400610067002D0041004600660069006C00650031002E007400780074> /UF <FEFF007400610067002D0041004600660069006C00650031002E007400780074> /EF<</F 27 0 R/UF 27 0 R>> >>
endobj
30 0 obj
-<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20240126) >> /Length 4 >>
+<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<</ModDate (D:20240202) >> /Length 4 >>
stream
Duck
endstream
@@ -242,17 +242,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T20:58:41+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:37:03+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-AF-file.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T20:58:41+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T20:58:41+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T20:58:41+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:37:03+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:37:03+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:37:03+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:38d5a844-2217-4081-87cc-b2129dc357a6</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:cb6cb011-153d-4b72-827d-6e20f4822861</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:35738719-0a61-4db5-8394-388b6fc161c2</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -353,7 +353,7 @@ endobj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/inline/2022) /RoleMapNS 20 0 R >>
endobj
21 0 obj
-<< /Type /Namespace /NS (data:,D665C3A0-56E-F551-A3B2-53B32DA0C704) >>
+<< /Type /Namespace /NS (data:,80B08CC2-52D3-4573-44F2-3D24ADA50C43) >>
endobj
8 0 obj
[ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R 21 0 R ]
@@ -455,7 +455,7 @@ endobj
<< /Type /Catalog /Pages 38 0 R /MarkInfo 39 0 R/Lang (de-DE)/Metadata 33 0 R/StructTreeRoot 5 0 R >>
endobj
48 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126205841+01'00')/ModDate (D:20240126205841+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223703+01'00')/ModDate (D:20240202223703+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 49
@@ -464,10 +464,10 @@ xref
0000000003 00000 f
0000000004 00000 f
0000000010 00000 f
-0000016877 00000 n
+0000016878 00000 n
0000013795 00000 n
0000014006 00000 n
-0000016300 00000 n
+0000016301 00000 n
0000014616 00000 n
0000000012 00000 f
0000014684 00000 n
@@ -482,34 +482,34 @@ xref
0000015902 00000 n
0000016212 00000 n
0000000000 00000 f
-0000016368 00000 n
+0000016369 00000 n
0000000020 00000 n
0000000382 00000 n
-0000016481 00000 n
+0000016482 00000 n
0000000673 00000 n
0000000828 00000 n
-0000016613 00000 n
+0000016614 00000 n
0000001062 00000 n
0000001202 00000 n
-0000016745 00000 n
+0000016746 00000 n
0000001436 00000 n
0000013649 00000 n
0000013514 00000 n
0000012908 00000 n
-0000020630 00000 n
-0000020984 00000 n
+0000020631 00000 n
+0000020985 00000 n
0000013759 00000 n
0000013852 00000 n
0000013969 00000 n
-0000016997 00000 n
-0000019446 00000 n
-0000017183 00000 n
-0000019667 00000 n
-0000020784 00000 n
-0000021046 00000 n
-0000021164 00000 n
+0000016998 00000 n
+0000019447 00000 n
+0000017184 00000 n
+0000019668 00000 n
+0000020785 00000 n
+0000021047 00000 n
+0000021165 00000 n
trailer
-<< /Size 49 /Root 47 0 R /Info 48 0 R /ID [ <6706A7F57FA2E57B6F29C1F4593BA810> <6706A7F57FA2E57B6F29C1F4593BA810> ] >>
+<< /Size 49 /Root 47 0 R /Info 48 0 R /ID [ <6F6CBA95E6A18A300BD05105D2CD9FCD> <6F6CBA95E6A18A300BD05105D2CD9FCD> ] >>
startxref
-21387
+21388
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf b/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf
index d2277fd590..5eedeb7ad7 100644
--- a/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf
+++ b/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf
Binary files differ
diff --git a/macros/latex/contrib/tagpdf/ex-attribute.pdf b/macros/latex/contrib/tagpdf/ex-attribute.pdf
index 406dff191a..10b045a81f 100644
--- a/macros/latex/contrib/tagpdf/ex-attribute.pdf
+++ b/macros/latex/contrib/tagpdf/ex-attribute.pdf
@@ -216,17 +216,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T20:59:27+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:37:47+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-attribute.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T20:59:27+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T20:59:27+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T20:59:27+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:37:47+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:37:47+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:37:47+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:7a9cf910-1c19-429a-8f24-339c62d8a57f</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:12b1f461-45c8-435e-80aa-5198be5aa29c</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:c0469dea-fd9d-4931-8af5-216a0c68dd97</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -449,7 +449,7 @@ endobj
<< /Type /Catalog /Pages 26 0 R /MarkInfo 27 0 R/Lang (de_DE)/Metadata 21 0 R/StructTreeRoot 5 0 R >>
endobj
38 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/Title (Title)/CreationDate (D:20240126205927+01'00')/ModDate (D:20240126205927+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/Title (Title)/CreationDate (D:20240202223747+01'00')/ModDate (D:20240202223747+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 39
@@ -493,7 +493,7 @@ xref
0000017720 00000 n
0000017838 00000 n
trailer
-<< /Size 39 /Root 37 0 R /Info 38 0 R /ID [ <D01DA1D59B8D51A0CC8554A95BED561F> <D01DA1D59B8D51A0CC8554A95BED561F> ] >>
+<< /Size 39 /Root 37 0 R /Info 38 0 R /ID [ <8C22E391CF2CF1A629F3902F8E80CCA6> <8C22E391CF2CF1A629F3902F8E80CCA6> ] >>
startxref
18075
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-formula-problem.pdf b/macros/latex/contrib/tagpdf/ex-formula-problem.pdf
index 0643e84ff8..cea631691f 100644
--- a/macros/latex/contrib/tagpdf/ex-formula-problem.pdf
+++ b/macros/latex/contrib/tagpdf/ex-formula-problem.pdf
@@ -239,17 +239,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T20:59:50+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:38:11+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-formula-problem.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T20:59:50+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T20:59:50+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T20:59:50+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:38:11+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:38:11+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:38:11+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:8eb2ce1d-b2ec-440a-8bc2-73733eb3eeb0</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:8970d22a-9e9e-4862-8221-c3ee6d0d9161</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:3fe0c564-0449-48d0-8aff-fb9f5180667e</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>2</prism:pageCount>
</rdf:Description>
@@ -425,7 +425,7 @@ endobj
<< /Type /Catalog /Pages 16 0 R /MarkInfo 23 0 R/Lang (de-DE)/Metadata 19 0 R/StructTreeRoot 5 0 R >>
endobj
33 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126205950+01'00')/ModDate (D:20240126205950+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223811+01'00')/ModDate (D:20240202223811+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 34
@@ -464,7 +464,7 @@ xref
0000018886 00000 n
0000019004 00000 n
trailer
-<< /Size 34 /Root 32 0 R /Info 33 0 R /ID [ <32DDD7A2A657D8573D42BD4BCB00A9DA> <32DDD7A2A657D8573D42BD4BCB00A9DA> ] >>
+<< /Size 34 /Root 32 0 R /Info 33 0 R /ID [ <63C41E7BFC8B747AC184EC4B36B85829> <63C41E7BFC8B747AC184EC4B36B85829> ] >>
startxref
19227
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-list.pdf b/macros/latex/contrib/tagpdf/ex-list.pdf
index ca3ab0e31a..c1fededd62 100644
--- a/macros/latex/contrib/tagpdf/ex-list.pdf
+++ b/macros/latex/contrib/tagpdf/ex-list.pdf
@@ -210,17 +210,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T21:00:13+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:38:38+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-list.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T21:00:13+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T21:00:13+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T21:00:13+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:38:38+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:38:38+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:38:38+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:4c749825-1de7-414c-879f-29e4d0bef66e</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:90b2a6de-94c7-4075-807e-0b97e2163383</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:5c417fb7-2a48-492e-8eee-ce0a6be433ad</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -653,7 +653,7 @@ endobj
<< /Type /Catalog /Pages 54 0 R /MarkInfo 55 0 R/Lang (en-US)/Metadata 48 0 R/StructTreeRoot 5 0 R >>
endobj
72 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210013+01'00')/ModDate (D:20240126210013+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223838+01'00')/ModDate (D:20240202223838+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 73
@@ -731,7 +731,7 @@ xref
0000029592 00000 n
0000029710 00000 n
trailer
-<< /Size 73 /Root 71 0 R /Info 72 0 R /ID [ <ED45731963D5B29C201FA1DF9FDBFFF2> <ED45731963D5B29C201FA1DF9FDBFFF2> ] >>
+<< /Size 73 /Root 71 0 R /Info 72 0 R /ID [ <2EE8B5792D28A5F75A1DF4D2AA3E2581> <2EE8B5792D28A5F75A1DF4D2AA3E2581> ] >>
startxref
29933
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf
index b751a6d102..2379e8ca20 100644
--- a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf
+++ b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf
@@ -243,17 +243,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T21:00:34+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:38:58+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-mc-manual-para-split-obsolete.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T21:00:34+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T21:00:34+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T21:00:34+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:38:58+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:38:58+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:38:58+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:c33d64b4-96ec-4e48-8f27-0b3edc831547</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:e3b2c8ed-e8fb-46b6-849f-75fd38b47579</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:e15069c5-de84-46d1-81d0-284e5e7b5202</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>2</prism:pageCount>
</rdf:Description>
@@ -413,7 +413,7 @@ endobj
<< /Type /Catalog /Pages 14 0 R /Lang (en-US)/Metadata 15 0 R >>
endobj
25 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210034+01'00')/ModDate (D:20240126210034+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223858+01'00')/ModDate (D:20240202223858+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 26
@@ -444,7 +444,7 @@ xref
0000023897 00000 n
0000023978 00000 n
trailer
-<< /Size 26 /Root 24 0 R /Info 25 0 R /ID [ <A530C63EDAA9942CF5746BD16B16A90B> <A530C63EDAA9942CF5746BD16B16A90B> ] >>
+<< /Size 26 /Root 24 0 R /Info 25 0 R /ID [ <F6E1F6F130362A92FE9BA815EF8209F6> <F6E1F6F130362A92FE9BA815EF8209F6> ] >>
startxref
24201
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf
index 95b1b31c08..31c494f059 100644
--- a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf
+++ b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf
@@ -210,17 +210,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T21:00:53+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:39:19+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-softhyphen.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T21:00:53+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T21:00:53+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T21:00:53+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:39:19+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:39:19+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:39:19+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:aa82e685-4098-469d-861c-3c45dfc700c7</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:8e3f9973-ca76-4bb0-885c-c462a238d3e9</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:ff06d09b-d1ff-4746-88cb-913348b6bed3</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -393,7 +393,7 @@ endobj
<< /Type /Catalog /Pages 19 0 R /MarkInfo 20 0 R/Lang (en-US)/Metadata 14 0 R/StructTreeRoot 5 0 R >>
endobj
30 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210053+01'00')/ModDate (D:20240126210053+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223919+01'00')/ModDate (D:20240202223919+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 31
@@ -429,7 +429,7 @@ xref
0000018116 00000 n
0000018234 00000 n
trailer
-<< /Size 31 /Root 29 0 R /Info 30 0 R /ID [ <5861020C59C64EDB711834443873AFAC> <5861020C59C64EDB711834443873AFAC> ] >>
+<< /Size 31 /Root 29 0 R /Info 30 0 R /ID [ <0E4E2750E80EA2B652B1FB8967503A62> <0E4E2750E80EA2B652B1FB8967503A62> ] >>
startxref
18457
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf
index 360b5fd2cf..1e31c89cfd 100644
--- a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf
+++ b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf
@@ -210,17 +210,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T21:01:12+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:39:39+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-spaceglyph-listings.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T21:01:12+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T21:01:12+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T21:01:12+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:39:39+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:39:39+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:39:39+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:acdc2435-bf29-4e54-8d09-1c9b6dc32038</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:2da7c0a8-0aad-46d2-8e28-b7f2a1930d27</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:106cffe6-9e83-4343-875e-bf36e39202e9</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -354,7 +354,7 @@ endobj
<< /Type /Catalog /Pages 15 0 R /MarkInfo 16 0 R/Lang (en-US)/Metadata 10 0 R/StructTreeRoot 5 0 R >>
endobj
26 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210112+01'00')/ModDate (D:20240126210112+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223939+01'00')/ModDate (D:20240202223939+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 27
@@ -386,7 +386,7 @@ xref
0000015484 00000 n
0000015602 00000 n
trailer
-<< /Size 27 /Root 25 0 R /Info 26 0 R /ID [ <4D137DF5E094011AB5CF6EF03BFCCE2C> <4D137DF5E094011AB5CF6EF03BFCCE2C> ] >>
+<< /Size 27 /Root 25 0 R /Info 26 0 R /ID [ <0FFF207E4920BBD2110B159C2D9324F6> <0FFF207E4920BBD2110B159C2D9324F6> ] >>
startxref
15825
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf b/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf
index 7ba830979b..d74c03578f 100644
--- a/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf
+++ b/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf
@@ -210,17 +210,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T21:01:31+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:39:59+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-structure-obsolete.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T21:01:31+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T21:01:31+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T21:01:31+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:39:59+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:39:59+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:39:59+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:bf5e4a2b-cfa9-4fc5-878c-8f9d2ee95445</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:58915d1b-721c-4e2f-8b60-999570652301</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:10235932-5d34-48f2-81ce-e522f266d343</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -526,7 +526,7 @@ endobj
<< /Type /Catalog /Pages 26 0 R /MarkInfo 27 0 R/Lang (en-US)/Metadata 20 0 R/StructTreeRoot 5 0 R >>
endobj
43 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210131+01'00')/ModDate (D:20240126210131+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223959+01'00')/ModDate (D:20240202223959+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 44
@@ -575,7 +575,7 @@ xref
0000023426 00000 n
0000023544 00000 n
trailer
-<< /Size 44 /Root 42 0 R /Info 43 0 R /ID [ <7E9B742ACCDBAEA64E0D4254DB9A148F> <7E9B742ACCDBAEA64E0D4254DB9A148F> ] >>
+<< /Size 44 /Root 42 0 R /Info 43 0 R /ID [ <1E58A57ED576731A14E6B7847804E1C7> <1E58A57ED576731A14E6B7847804E1C7> ] >>
startxref
23767
%%EOF
diff --git a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf
index 476a154f58..6dc444340a 100644
--- a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf
+++ b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf
@@ -210,17 +210,17 @@ stream
</dc:language>
<dc:date>
<rdf:Seq>
- <rdf:li>2024-01-26T21:01:51+01:00</rdf:li>
+ <rdf:li>2024-02-02T22:40:21+01:00</rdf:li>
</rdf:Seq>
</dc:date>
<dc:format>application/pdf</dc:format>
<dc:source>ex-tagpdf-template.tex</dc:source>
<xmp:CreatorTool>LaTeX</xmp:CreatorTool>
- <xmp:CreateDate>2024-01-26T21:01:51+01:00</xmp:CreateDate>
- <xmp:ModifyDate>2024-01-26T21:01:51+01:00</xmp:ModifyDate>
- <xmp:MetadataDate>2024-01-26T21:01:51+01:00</xmp:MetadataDate>
+ <xmp:CreateDate>2024-02-02T22:40:21+01:00</xmp:CreateDate>
+ <xmp:ModifyDate>2024-02-02T22:40:21+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2024-02-02T22:40:21+01:00</xmp:MetadataDate>
<xmpMM:DocumentID>uuid:f320abfc-f6ab-4d12-8719-d176f4d947cf</xmpMM:DocumentID>
- <xmpMM:InstanceID>uuid:a21419d2-023c-4512-8135-0ae4ab36b4bd</xmpMM:InstanceID>
+ <xmpMM:InstanceID>uuid:e9c2bc0c-c443-48b5-8ced-b99f15ae41a0</xmpMM:InstanceID>
<prism:complianceProfile>three</prism:complianceProfile>
<prism:pageCount>1</prism:pageCount>
</rdf:Description>
@@ -312,7 +312,7 @@ endobj
<< /Type /Namespace /NS (https://www.latex-project.org/ns/inline/2022) /RoleMapNS 20 0 R >>
endobj
21 0 obj
-<< /Type /Namespace /NS (data:,B029B424-4166-87C8-F620-397B784D410C) >>
+<< /Type /Namespace /NS (data:,D77936FE-8-5FAE-4338-D9DD76B7C691) >>
endobj
8 0 obj
[ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R 21 0 R ]
@@ -404,7 +404,7 @@ endobj
<< /Type /Catalog /Pages 33 0 R /MarkInfo 34 0 R/Lang (en-US)/Metadata 28 0 R/StructTreeRoot 5 0 R >>
endobj
44 0 obj
-<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210151+01'00')/ModDate (D:20240126210151+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
+<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202224021+01'00')/ModDate (D:20240202224021+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >>
endobj
xref
0 45
@@ -413,10 +413,10 @@ xref
0000000003 00000 f
0000000004 00000 f
0000000010 00000 f
-0000015155 00000 n
+0000015152 00000 n
0000012015 00000 n
0000012225 00000 n
-0000014583 00000 n
+0000014580 00000 n
0000012898 00000 n
0000000012 00000 f
0000012966 00000 n
@@ -431,30 +431,30 @@ xref
0000014184 00000 n
0000014494 00000 n
0000000000 00000 f
-0000014651 00000 n
-0000014748 00000 n
-0000014835 00000 n
-0000014922 00000 n
-0000015021 00000 n
+0000014648 00000 n
+0000014745 00000 n
+0000014832 00000 n
+0000014919 00000 n
+0000015018 00000 n
0000000020 00000 n
0000011869 00000 n
0000011734 00000 n
0000011500 00000 n
-0000017776 00000 n
-0000018130 00000 n
+0000017773 00000 n
+0000018127 00000 n
0000011979 00000 n
0000012056 00000 n
0000012188 00000 n
0000012835 00000 n
-0000015292 00000 n
-0000016733 00000 n
-0000015379 00000 n
-0000016954 00000 n
-0000017930 00000 n
-0000018192 00000 n
-0000018310 00000 n
+0000015289 00000 n
+0000016730 00000 n
+0000015376 00000 n
+0000016951 00000 n
+0000017927 00000 n
+0000018189 00000 n
+0000018307 00000 n
trailer
-<< /Size 45 /Root 43 0 R /Info 44 0 R /ID [ <CD8B7B610F3E857FEE2BD3930A7259D2> <CD8B7B610F3E857FEE2BD3930A7259D2> ] >>
+<< /Size 45 /Root 43 0 R /Info 44 0 R /ID [ <D7B7DCEE81905F9857C73FAFC3C9ADC9> <D7B7DCEE81905F9857C73FAFC3C9ADC9> ] >>
startxref
-18533
+18530
%%EOF
diff --git a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
index 809fb896fc..811da15758 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx
@@ -47,13 +47,13 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{implementation}
% \begin{macrocode}
%<@@=tag>
%<*luatex>
-\ProvidesExplFile {tagpdf-luatex.def} {2024-01-26} {0.98t}
+\ProvidesExplFile {tagpdf-luatex.def} {2024-02-02} {0.98u}
{tagpdf~driver~for~luatex}
% \end{macrocode}
% \section{Loading the lua}
@@ -158,8 +158,8 @@
local ProvidesLuaModule = {
name = "tagpdf",
- version = "0.98t", --TAGVERSION
- date = "2024-01-26", --TAGDATE
+ version = "0.98u", --TAGVERSION
+ date = "2024-02-02", --TAGDATE
description = "tagpdf lua code",
license = "The LATEX Project Public License 1.3c"
}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx
index 5205df1cf6..83586fb20c 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx
@@ -48,7 +48,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% \section{Commands}
@@ -327,7 +327,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-checks-code} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-checks-code} {2024-02-02} {0.98u}
{part of tagpdf - code related to checks, conditionals, debugging and messages}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-code.pdf b/macros/latex/contrib/tagpdf/tagpdf-code.pdf
index 67914b3a80..6cb075911a 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-code.pdf
+++ b/macros/latex/contrib/tagpdf/tagpdf-code.pdf
Binary files differ
diff --git a/macros/latex/contrib/tagpdf/tagpdf-data.dtx b/macros/latex/contrib/tagpdf/tagpdf-data.dtx
index e9f0d14790..6405215297 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-data.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-data.dtx
@@ -47,7 +47,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% This files contains a various data files which are read in
@@ -60,7 +60,7 @@
% It lists the new tag, the rolemap and the namespace of the rolemap.
% \begin{macrocode}
%<*ns-latex>
-%% \ProvidesExplFile {tagpdf-ns-latex.def} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-ns-latex.def} {2024-02-02} {0.98u}
%% {latex} {https://www.latex-project.org/ns/dflt/2022}{}
title, Title, pdf2,
part, Title, pdf2,
@@ -92,7 +92,7 @@ text, P, pdf2,
% It is bound to change
% \begin{macrocode}
%<*ns-latex-book>
-%% \ProvidesExplFile {tagpdf-ns-latex-book.def} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-ns-latex-book.def} {2024-02-02} {0.98u}
%% {latex-book} {https://www.latex-project.org/ns/book/2022}{}
chapter, H1,pdf2,
section, H2,pdf2,
@@ -108,7 +108,7 @@ subparagraph, H6,pdf2,
% loaded.
% \begin{macrocode}
%<*ns-latex-inline>
-%% \ProvidesExplFile {tagpdf-ns-latex-inline.def} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-ns-latex-inline.def} {2024-02-02} {0.98u}
%% {latex-inline} {https://www.latex-project.org/ns/inline/2022}{}
chapter, Span, pdf2,
section, Span, pdf2,
@@ -122,7 +122,7 @@ P, Span, pdf2,
% \section{The pdf namespace data}
% \begin{macrocode}
%<*ns-pdf>
-%% \ProvidesExplFile {tagpdf-ns-pdf.def} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-ns-pdf.def} {2024-02-02} {0.98u}
%% {pdf} {http://iso.org/pdf/ssn}{}
StructTreeRoot,StructTreeRoot,pdf,D,
Document,Document,pdf,D,
@@ -190,7 +190,7 @@ Strong,Span,pdf,I,
% \section{The pdf 2.0 namespace data}
% \begin{macrocode}
%<*ns-pdf2>
-%% \ProvidesExplFile {tagpdf-ns-pdf2.def} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-ns-pdf2.def} {2024-02-02} {0.98u}
%% {pdf2} {http://iso.org/pdf2/ssn}{}
StructTreeRoot,StructTreeRoot,pdf2,D,
Document,Document,pdf2,D,
@@ -247,7 +247,7 @@ Strong,Strong,pdf2,I,
% \section{The mathml namespace data}
% \begin{macrocode}
%<*ns-mathml>
-%% \ProvidesExplFile {tagpdf-ns-mathml.def} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-ns-mathml.def} {2024-02-02} {0.98u}
% {mathml}{http://www.w3.org/1998/Math/MathML}{}
abs,abs,mathml,
and,and,mathml,
@@ -482,7 +482,7 @@ xor,xor,mathml,
% This will perhaps change in future.
% \begin{macrocode}
%<*parent-child>
-%% \ProvidesExplFile {tagpdf-parent-child.csv} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-parent-child.csv} {2024-02-02} {0.98u}
,,,StructTreeRoot,Document,Art,Part,Div,Sect,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,MC
Document,both,document level,1,0..n,∅,‡,‡,∅,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅
Art,1.7,grouping,∅,0..n,∅,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,∅,0..n,∅,∅,∅,0..1,0..1,∅,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,∅,∅
@@ -537,7 +537,7 @@ MC,both,---,∅,∅,∅,∅,∅,∅,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0..
% This will perhaps change in future.
% \begin{macrocode}
%<*parent-child-2>
-%% \ProvidesExplFile {tagpdf-parent-child-2.csv} {2024-01-26} {0.98t}
+%% \ProvidesExplFile {tagpdf-parent-child-2.csv} {2024-02-02} {0.98u}
,,,StructTreeRoot,Document,DocumentFragment,Art,Part,Div,Sect,Aside,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Title,Sub,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Em,Strong,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,FENote,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,math,mathml,Artifact,MC
Document,both,document level,1,0..n,0..n,∅,‡,‡,∅,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅
DocumentFragment,2.0,document level,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,0..n,∅
diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx
index 3764e92d11..04f5501657 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% \end{documentation}
@@ -55,11 +55,11 @@
% \begin{macrocode}
%<@@=tag>
%<*generic>
-\ProvidesExplPackage {tagpdf-mc-code-generic} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-mc-code-generic} {2024-02-02} {0.98u}
{part of tagpdf - code related to marking chunks - generic mode}
%</generic>
%<*debug>
-\ProvidesExplPackage {tagpdf-debug-generic} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-debug-generic} {2024-02-02} {0.98u}
{part of tagpdf - debugging code related to marking chunks - generic mode}
%</debug>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx
index 20dd45ecc2..8f9678e55a 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{implementation}
% The code is splitted into three parts: code shared by all engines,
@@ -86,11 +86,11 @@
% \begin{macrocode}
%<@@=tag>
%<*luamode>
-\ProvidesExplPackage {tagpdf-mc-code-lua} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-mc-code-lua} {2024-02-02} {0.98u}
{tagpdf - mc code only for the luamode }
%</luamode>
%<*debug>
-\ProvidesExplPackage {tagpdf-debug-lua} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-debug-lua} {2024-02-02} {0.98u}
{part of tagpdf - debugging code related to marking chunks - lua mode}
%</debug>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx
index db7c727770..8799df3d4c 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% \section{Public Commands}
@@ -181,7 +181,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-mc-code-shared} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-mc-code-shared} {2024-02-02} {0.98u}
{part of tagpdf - code related to marking chunks -
code shared by generic and luamode }
%</header>
diff --git a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx
index 682c4e387a..98750fa461 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% \begin{function}
@@ -98,7 +98,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-roles-code} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-roles-code} {2024-02-02} {0.98u}
{part of tagpdf - code related to roles and structure names}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-space.dtx b/macros/latex/contrib/tagpdf/tagpdf-space.dtx
index feff45c173..3e3b3de7e6 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-space.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-space.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% \begin{function}{interwordspace (setup-key)}
@@ -64,7 +64,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-space-code} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-space-code} {2024-02-02} {0.98u}
{part of tagpdf - code related to real space chars}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx
index bcc9083ae2..8f0dd1e717 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% \section{Public Commands}
@@ -285,7 +285,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-struct-code} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-struct-code} {2024-02-02} {0.98u}
{part of tagpdf - code related to storing structure}
%</header>
% \end{macrocode}
@@ -1905,7 +1905,7 @@
% \section{Attributes and attribute classes}
% \begin{macrocode}
%<*header>
-\ProvidesExplPackage {tagpdf-attr-code} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-attr-code} {2024-02-02} {0.98u}
{part of tagpdf - code related to attributes and attribute classes}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx
index 362f3ecf7e..d9ed68f31f 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx
@@ -47,13 +47,13 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{implementation}
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-tree-code} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-tree-code} {2024-02-02} {0.98u}
{part of tagpdf - code related to writing trees and dictionaries to the pdf}
%</header>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf-user.dtx b/macros/latex/contrib/tagpdf/tagpdf-user.dtx
index ebdc8cece2..aea543ba40 100644
--- a/macros/latex/contrib/tagpdf/tagpdf-user.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf-user.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Version 0.98t, released 2024-01-26}
+% \date{Version 0.98u, released 2024-02-02}
% \maketitle
% \begin{documentation}
% \section{Setup commands}
@@ -303,7 +303,7 @@
% \begin{macrocode}
%<@@=tag>
%<*header>
-\ProvidesExplPackage {tagpdf-user} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-user} {2024-02-02} {0.98u}
{tagpdf - user commands}
%</header>
% \end{macrocode}
@@ -736,6 +736,7 @@
% \g_@@_para_end_int,
% \g_@@_para_main_begin_int,
% \g_@@_para_main_end_int,
+% \g_@@_para_main_struct_tl,
% \l_@@_para_tag_default_tl,
% \l_@@_para_tag_tl,
% \l_@@_para_main_tag_tl,
@@ -752,6 +753,10 @@
\int_new:N \g_@@_para_end_int
\int_new:N \g_@@_para_main_begin_int
\int_new:N \g_@@_para_main_end_int
+% \end{macrocode}
+% this will hold the structure number of the current text-unit.
+% \begin{macrocode}
+\tl_new:N \g_@@_para_main_struct_tl
\tl_new:N \l_@@_para_tag_default_tl
\tl_set:Nn \l_@@_para_tag_default_tl { text }
\tl_new:N \l_@@_para_tag_tl
@@ -795,7 +800,6 @@
}
% \end{macrocode}
% \end{macro}
-
% \begin{macro}{\@@_start_para_ints:,\@@_stop_para_ints:}
% \begin{macrocode}
\cs_new_protected:Npn \@@_start_para_ints:
@@ -827,21 +831,31 @@
% \end{macrocode}
% \end{macro}
%
+% We want to be able to inspect the current para main structure, so
+% we need a command to store its structure number
+% \begin{macro}{\@@_para_main_store_struct:}
+% \begin{macrocode}
+\cs_new:Npn \@@_para_main_store_struct:
+ {
+ \tl_gset:Ne \g_@@_para_main_struct_tl {\int_use:N \c@g_@@_struct_abs_int }
+ }
+% \end{macrocode}
+% \end{macro}
% TEMPORARLY FIX (2023-11-17). Until latex-lab is updated we must adapt a sec command:
% \begin{macrocode}
\AddToHook{package/latex-lab-testphase-sec/after}
{
\cs_set_protected:Npn \@kernel@tag@hangfrom #1
{
- \tagstructbegin{tag=\l__tag_para_tag_tl}
- \__tag_gincr_para_begin_int:
+ \tagstructbegin{tag=\l_@@_para_tag_tl}
+ \@@_gincr_para_begin_int:
\tagstructbegin{tag=Lbl}
\setbox\@tempboxa
\hbox
{
\bool_lazy_and:nnT
{\tag_if_active_p:}
- {\g__tag_mode_lua_bool}
+ {\g_@@_mode_lua_bool}
{\tagmcbegin{tag=Lbl}}
{#1}
}
@@ -852,7 +866,7 @@
}
}
% \end{macrocode}
-% and two adaptions from the block module:
+% and one temporary adaptions for the block module:
% \begin{macrocode}
\AddToHook{package/latex-lab-testphase-block/after}
{
@@ -860,49 +874,6 @@
{
\tl_set:Nn \l_@@_para_attr_class_tl { \l_tag_para_attr_class_tl }
}
- \cs_set_protected:Npn \__block_start_para_structure:n #1 {
- \__block_debug_typeout:n
- { @endpe = \legacy_if:nTF { @endpe }{true}{false}
- \on@line }
- \legacy_if:nF { @endpe }
- {
- \bool_if:NF \l__tag_para_flattened_bool
- {
- \@@_gincr_para_main_begin_int:
- \tag_struct_begin:n
- {
- tag=\l_@@_para_main_tag_tl,
- attribute-class=\l_@@_para_main_attr_class_tl,
- }
- }
- }
- \@@_gincr_para_begin_int:
- \__block_debug_typeout:n{increment~ P \on@line }
- \tag_struct_begin:n
- {
- tag=\l__tag_para_tag_tl
- ,attribute-class=\l_@@_para_attr_class_tl
- }
- \__tag_check_para_begin_show:nn {green}{#1}
- \tag_mc_begin:n {}
- }
- \RemoveFromHook{para/end}[latex-lab-testphase-block]
- \AddToHook{para/end}[latex-lab-testphase-block]
- {
- \bool_if:NT \l__tag_para_bool
- {
- \__tag_gincr_para_end_int:
- \__block_debug_typeout:n{increment~ /P \on@line }
- \tag_mc_end:
- \__tag_check_para_end_show:nn {red}{}
- \tag_struct_end:
- \bool_if:NF \l__tag_para_flattened_bool
- {
- \__tag_gincr_para_main_end_int:
- \tag_struct_end:
- }
- }
- }
}
% \end{macrocode}
@@ -934,7 +905,7 @@
}
% \end{macrocode}
% \end{macro}
-% This fills the para hooks with the needed code.
+% Helper command for debugging:
% \begin{macrocode}
\cs_new_protected:Npn \@@_check_para_begin_show:nn #1 #2
%#1 color, #2 prefix
@@ -957,30 +928,82 @@
\tag_mc_end:
}
}
-
-\AddToHook{para/begin}
- {
+% \end{macrocode}
+%
+% The para/begin and para/end code.
+% We have two variants here: a simpler one, which must be used
+% if the block code is not used (and so probably will disappear
+% at some time) and a more sophisticated one that must
+% be used if the block code is used.
+% It is possible that we will need more variants, so
+% we setup a socket so that the code can be easily switched.
+% \begin{macrocode}
+\socket_new:nn {tagsupport/para/begin}{0}
+\socket_new:nn {tagsupport/para/end}{0}
+
+\socket_new_plug:nnn{tagsupport/para/begin}{plain}
+ {
\bool_if:NT \l_@@_para_bool
{
\bool_if:NF \l_@@_para_flattened_bool
+ {
+ \@@_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l_@@_para_main_tag_tl,
+ }
+ \@@_para_main_store_struct:
+ }
+ \@@_gincr_para_begin_int:
+ \tag_struct_begin:n {tag=\l_@@_para_tag_tl}
+ \@@_check_para_begin_show:nn {green}{}
+ \tag_mc_begin:n {}
+ }
+ }
+\socket_new_plug:nnn{tagsupport/para/begin}{block}
+ {
+ \bool_if:NT \l_@@_para_bool
+ {
+ \legacy_if:nF { @inlabel }
{
- \@@_gincr_para_main_begin_int:
- \tag_struct_begin:n
- {
- tag=\l_@@_para_main_tag_tl,
+ \@@_check_typeout_v:n
+ {==>~ @endpe = \legacy_if:nTF { @endpe }{true}{false} \on@line }
+ \legacy_if:nF { @endpe }
+ {
+ \bool_if:NF \l_@@_para_flattened_bool
+ {
+ \@@_gincr_para_main_begin_int:
+ \tag_struct_begin:n
+ {
+ tag=\l_@@_para_main_tag_tl,
+ attribute-class=\l_@@_para_main_attr_class_tl,
+ }
+ \@@_para_main_store_struct:
+ }
}
- }
- \@@_gincr_para_begin_int:
- \tag_struct_begin:n {tag=\l_@@_para_tag_tl}
- \@@_check_para_begin_show:nn {green}{}
- \tag_mc_begin:n {}
- }
- }
-\AddToHook{para/end}
+ \@@_gincr_para_begin_int:
+ \@@_check_typeout_v:n {==>~increment~ P \on@line }
+ \tag_struct_begin:n
+ {
+ tag=\l_@@_para_tag_tl
+ ,attribute-class=\l_@@_para_attr_class_tl
+ }
+ \@@_check_para_begin_show:nn {green}{\PARALABEL}
+ \tag_mc_begin:n {}
+ }
+ }
+ }
+% \end{macrocode}
+% there was no real difference between the original and
+% in the block variant, only a debug message. We therefore
+% define only a plain variant.
+% \begin{macrocode}
+\socket_new_plug:nnn{tagsupport/para/end}{plain}
{
\bool_if:NT \l_@@_para_bool
{
\@@_gincr_para_end_int:
+ \@@_check_typeout_v:n {==>~increment~ /P \on@line }
\tag_mc_end:
\@@_check_para_end_show:nn {red}{}
\tag_struct_end:
@@ -989,9 +1012,43 @@
\@@_gincr_para_main_end_int:
\tag_struct_end:
}
- }
+ }
}
% \end{macrocode}
+% By default we assign the plain plug:
+% \begin{macrocode}
+\socket_assign_plug:nn { tagsupport/para/begin}{plain}
+\socket_assign_plug:nn { tagsupport/para/end}{plain}
+% \end{macrocode}
+% And use the sockets in the hooks. Once tagging sockets exist, this
+% can be adapted.
+% \begin{macrocode}
+\AddToHook{para/begin}{ \socket_use:n { tagsupport/para/begin }
+ }
+\AddToHook{para/end} { \socket_use:n { tagsupport/para/end } }
+% \end{macrocode}
+%
+% If the block code is loaded we must ensure that it doesn't overwrite
+% the hook again. And we must reassign the para/begin plug.
+% This can go once the block code no longer tries to adapt the hooks.
+% \begin{macrocode}
+\AddToHook{package/latex-lab-testphase-block/after}
+ {
+ \RemoveFromHook{para/begin}[tagpdf]
+ \RemoveFromHook{para/end}[latex-lab-testphase-block]
+ \AddToHook{para/begin}[tagpdf]
+ {
+ \socket_use:n { tagsupport/para/begin }
+ }
+ \AddToHook{para/end}[tagpdf]
+ {
+ \socket_use:n { tagsupport/para/end }
+ }
+ \socket_assign_plug:nn { tagsupport/para/begin}{block}
+ }
+
+% \end{macrocode}
+%
% We check the para count at the end. If tagging is not active it is not a error,
% but we issue a warning as it perhaps indicates that the testphase code didn't guard
% everything correctly.
diff --git a/macros/latex/contrib/tagpdf/tagpdf.dtx b/macros/latex/contrib/tagpdf/tagpdf.dtx
index 71585725aa..d1ccff926c 100644
--- a/macros/latex/contrib/tagpdf/tagpdf.dtx
+++ b/macros/latex/contrib/tagpdf/tagpdf.dtx
@@ -84,7 +84,7 @@
% \begin{macrocode}
%<@@=tag>
%<*package>
-\ProvidesExplPackage {tagpdf} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf} {2024-02-02} {0.98u}
{ A package to experiment with pdf tagging }
\bool_if:nF
@@ -110,7 +110,7 @@
% \end{macrocode}
%<*debug>
% \begin{macrocode}
-\ProvidesExplPackage {tagpdf-debug} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-debug} {2024-02-02} {0.98u}
{ debug code for tagpdf }
\@ifpackageloaded{tagpdf}{}{\PackageWarning{tagpdf-debug}{tagpdf~not~loaded,~quitting}\endinput}
% \end{macrocode}
@@ -133,7 +133,7 @@
% we define a base package with dummy functions
% \begin{macrocode}
%<*base>
-\ProvidesExplPackage {tagpdf-base} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdf-base} {2024-02-02} {0.98u}
{part of tagpdf - provide base, no-op versions of the user commands }
%</base>
% \end{macrocode}
diff --git a/macros/latex/contrib/tagpdf/tagpdf.pdf b/macros/latex/contrib/tagpdf/tagpdf.pdf
index 61f0c3e3c3..92d19dd6ff 100644
--- a/macros/latex/contrib/tagpdf/tagpdf.pdf
+++ b/macros/latex/contrib/tagpdf/tagpdf.pdf
Binary files differ
diff --git a/macros/latex/contrib/tagpdf/tagpdf.tex b/macros/latex/contrib/tagpdf/tagpdf.tex
index 2d9ab2ef1b..0b94e9406f 100644
--- a/macros/latex/contrib/tagpdf/tagpdf.tex
+++ b/macros/latex/contrib/tagpdf/tagpdf.tex
@@ -16,8 +16,8 @@
}
\DebugBlocksOff
\makeatletter
-\def\UlrikeFischer@package@version{0.98t}
-\def\UlrikeFischer@package@date{2024-01-26}
+\def\UlrikeFischer@package@version{0.98u}
+\def\UlrikeFischer@package@date{2024-02-02}
\makeatother
\documentclass[bibliography=totoc,a4paper]{article}
diff --git a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty
index 90418591a0..bc74eb1bc9 100644
--- a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty
+++ b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty
@@ -1,5 +1,5 @@
%\RequirePackage[enable-debug]{expl3}[2018/06/14]
-\ProvidesExplPackage {tagpdfdocu-patches} {2024-01-26} {0.98t}
+\ProvidesExplPackage {tagpdfdocu-patches} {2024-02-02} {0.98u}
{patches/commands for the tagpdf documentation}
\RequirePackage{etoolbox,xpatch}
diff --git a/macros/latex/contrib/wargame/README.md b/macros/latex/contrib/wargame/README.md
index 3de32ab4d0..70eb286498 100644
--- a/macros/latex/contrib/wargame/README.md
+++ b/macros/latex/contrib/wargame/README.md
@@ -1,6 +1,6 @@
# A package to make Hex'n'Counter wargames in LaTeX
-## Version 0.5
+## Version 0.6
This package can help make classic [Hex'n'Counter
wargames](https://en.wikipedia.org/wiki/Wargame) using LaTeX. The
diff --git a/macros/latex/contrib/wargame/doc/compat.pdf b/macros/latex/contrib/wargame/doc/compat.pdf
index 2ba344d4ab..8f70ab6b2e 100644
--- a/macros/latex/contrib/wargame/doc/compat.pdf
+++ b/macros/latex/contrib/wargame/doc/compat.pdf
Binary files differ
diff --git a/macros/latex/contrib/wargame/doc/symbols.pdf b/macros/latex/contrib/wargame/doc/symbols.pdf
index cd8f0d3ddc..9722803067 100644
--- a/macros/latex/contrib/wargame/doc/symbols.pdf
+++ b/macros/latex/contrib/wargame/doc/symbols.pdf
Binary files differ
diff --git a/macros/latex/contrib/wargame/doc/tutorial/export.tex b/macros/latex/contrib/wargame/doc/tutorial/export.tex
index 6d6722d9ac..390b8785ae 100644
--- a/macros/latex/contrib/wargame/doc/tutorial/export.tex
+++ b/macros/latex/contrib/wargame/doc/tutorial/export.tex
@@ -77,9 +77,9 @@
% counter.
%
% \begin{macrocode}
-\doublechitimages[A]{\alla}
-\doublechitimages[B]{\allb}
-\doublechitimages[Markers]{{game turn chit}}
+\doublechitimages[A][chit drop shadows]{\alla}
+\doublechitimages[B][chit drop shadows]{\allb}
+\doublechitimages[Markers][chit drop shadows]{{game turn chit}}
% \end{macrocode}
%
% Again, the macros we made for the counters comes in handy. Note
@@ -96,7 +96,9 @@
% can.}.
%
% \begin{macrocode}
-\battlemarkers{12}
+\tikzset{}
+\battlemarkers[marker drop shadows]{12}
+\tikzset{every battle marker/.style={}}
% \end{macrocode}
%
% Furthermore, we can add ``odds'' and battle result markers. Odds
@@ -108,14 +110,14 @@
% in the markers.
%
% \begin{macrocode}
-\oddsmarkers{%
+\oddsmarkers[marker drop shadows]{%
1:3/red!25!white,%
1:2/red!15!white,%
1:1/orange!15!white,%
2:1/white,%
3:1/green!15!white,%
4:1/green!25!white}
-\resultmarkers{
+\resultmarkers[marker drop shadows]{
AE/red!50!white,
AR/red!25!white,
EX/white,
diff --git a/macros/latex/contrib/wargame/doc/tutorial/game.pdf b/macros/latex/contrib/wargame/doc/tutorial/game.pdf
index f4e8a22e2a..63ea8b0733 100644
--- a/macros/latex/contrib/wargame/doc/tutorial/game.pdf
+++ b/macros/latex/contrib/wargame/doc/tutorial/game.pdf
Binary files differ
diff --git a/macros/latex/contrib/wargame/doc/wargame.pdf b/macros/latex/contrib/wargame/doc/wargame.pdf
index 01a58c597b..9b608b4144 100644
--- a/macros/latex/contrib/wargame/doc/wargame.pdf
+++ b/macros/latex/contrib/wargame/doc/wargame.pdf
Binary files differ
diff --git a/macros/latex/contrib/wargame/source/Makefile b/macros/latex/contrib/wargame/source/Makefile
index e11c477bf7..8320c42419 100644
--- a/macros/latex/contrib/wargame/source/Makefile
+++ b/macros/latex/contrib/wargame/source/Makefile
@@ -2,7 +2,7 @@
#
#
NAME := wargame
-VERSION := 0.5
+VERSION := 0.6
LATEX_FLAGS := -interaction=nonstopmode \
-file-line-error \
--synctex=15 \
diff --git a/macros/latex/contrib/wargame/source/chit/battle.dtx b/macros/latex/contrib/wargame/source/chit/battle.dtx
index 5057d620a5..381f4e4aba 100644
--- a/macros/latex/contrib/wargame/source/chit/battle.dtx
+++ b/macros/latex/contrib/wargame/source/chit/battle.dtx
@@ -41,7 +41,7 @@
minimum size=8mm,
draw=black,
fill=#2,
- every odds marker/.try] at (.2,-.2) {#1};
+ every odds marker/.try] at (.16,-.16) {#1};
}
},
odds marker/.style args={#1,#2}{
diff --git a/macros/latex/contrib/wargame/source/chit/misc.dtx b/macros/latex/contrib/wargame/source/chit/misc.dtx
index a5b9a79b24..e5d4b4b708 100644
--- a/macros/latex/contrib/wargame/source/chit/misc.dtx
+++ b/macros/latex/contrib/wargame/source/chit/misc.dtx
@@ -4,6 +4,58 @@
% \fi
% \subsubsection{Some utilities}
%
+% This style allows us to add a fading drop-shadow to chits.
+%
+% \begin{macrocode}
+\usetikzlibrary{shadows.blur}
+\newif\ifwg@chit@drop\wg@chit@dropfalse
+\tikzset{
+ chit has drop/.is if=wg@chit@drop,
+ chit has drop/.default=true,
+ chit has drop/.initial=false,
+ /tikz/render blur shadow/.add code={%
+ \chit@dbg{2}{Number of blur steps: \pgfbs@steps}%
+ \ifnum\pgfbs@steps=0\else
+ \chit@dbg{2}{Making shadow blur}%
+ }{\fi}}
+\tikzset{%
+ chit drop/.code={%
+ %% \message{^^J Args `#1'}%
+ \pgfkeysalso{%
+ chit has drop=true,
+ /tikz/blur shadow={shadow blur steps=5,
+ shadow opacity=25,
+ shadow xshift=.05cm,
+ shadow yshift=-.05cm,
+ shadow blur radius=.05cm,
+ #1}}%
+ \ifnum\pgfbs@steps=0%
+ \gdef\wg@drop@margin{0pt}%
+ \else%
+ \ifwg@chit@drop%
+ \pgfmathparse{
+ \pgfbs@radius+
+ veclen(
+ \pgfkeysvalueof{/tikz/shadow xshift},
+ \pgfkeysvalueof{/tikz/shadow yshift})}
+ \xdef\wg@drop@margin{\pgfmathresult pt}%
+ \else%
+ \gdef\wg@drop@margin{0pt}%
+ \fi
+ %% \message{^^J Drop margin is `\wg@drop@margin'
+ %% `\pgfbs@radius'
+ %% `\pgfkeysvalueof{/tikz/shadow xshift}',
+ %% `\pgfkeysvalueof{/tikz/shadow yshift}'}%
+ \fi%
+ },%
+ chit drop/.default=,%
+ no chit drop/.code={%
+ \pgfkeysalso{
+ /tikz/blur shadow={shadow blur steps=0}}
+ \gdef\wg@drop@margin{0pt}%
+ }
+}%
+% \end{macrocode}
%
% Game turn marker
%
diff --git a/macros/latex/contrib/wargame/source/chit/modifiers.dtx b/macros/latex/contrib/wargame/source/chit/modifiers.dtx
index b42ee5790f..f2f47ee3a8 100644
--- a/macros/latex/contrib/wargame/source/chit/modifiers.dtx
+++ b/macros/latex/contrib/wargame/source/chit/modifiers.dtx
@@ -14,7 +14,7 @@
code={%
\path[fill=white,opacity=#1,pic actions] (-.6,-.6) rectangle(.6,.6);}},
pics/chit/eliminate/.style={
- code={%
+ code={%
\path[fill=red,opacity=#1,pic actions] (-.6,-.6) rectangle(.6,.6);}},
pics/chit/shade/.default=0.5,
pics/chit/eliminate/.default=0.25,
diff --git a/macros/latex/contrib/wargame/source/chit/oob.dtx b/macros/latex/contrib/wargame/source/chit/oob.dtx
index d640dadebf..9e5f0c4f93 100644
--- a/macros/latex/contrib/wargame/source/chit/oob.dtx
+++ b/macros/latex/contrib/wargame/source/chit/oob.dtx
@@ -37,8 +37,9 @@
\def\chit@oob@rowupdate(#1,#2)#3#4{%
\chit@dbg{2}{ Row update c=`#1',r=`#2',s=`#3',e=`#4'}
%\pgfmathparse{ifthenelse(#1>0,#2-#3,#2)}%
- \pgfmathparse{#2-#3)}%
+ \pgfmathparse{#2-#3-#4}%
\xdef#2{\pgfmathresult}%
+ \xdef#1{0}%\pgfmathresult}%
%\xdef#1{0}
\chit@dbg{2}{ \space\space-> update `\string#2'=#2}
}
@@ -71,6 +72,7 @@
% \begin{macrocode}
\newif\ifwg@oob@inv\wg@oob@invfalse
\def\chit@oob@spacer{hspace}
+\def\chit@oob@vspacer{vspace}
\def\wg@star@oob{\wg@oob@invtrue\wg@oob}
\def\wg@nostar@oob{\wg@oob@invfalse\wg@oob}
\def\oob{%
@@ -91,6 +93,8 @@
% \begin{macrocode}
\def\wg@oob#1#2#3#4{
\def\r{0}
+ \pgfmathparse{#3*(#2-1)}%
+ \edef\a{\pgfmathresult}
\chit@dbg{2}{OOB: `#1'}
\foreach[count=\ti from 0] \t/\y in #1{
\xdef\o{\r}
@@ -109,20 +113,28 @@
\ifx\m\@empty\def\m{1}\fi
\ifx\u\m\def\m{1}\fi
\foreach \n in {1,...,\m}{%
- \chit@dbg{2}{OOB Chit is `\u'}%
+ \chit@dbg{2}{OOB Chit is `\u' `\chit@oob@spacer'}%
\ifx\u\chit@oob@spacer%
\chit@dbg{3}{Chit `\u' is spacer `\chit@oob@spacer'}
\pgfmathparse{\c+#4}%
\xdef\c{\pgfmathresult}%
- \else
- \ifnum\chitdbglvl>2%
- \node[minimum width=#3cm,minimum height=#3cm,
- draw,transform shape] at (\c,\r) {};
+ \else%
+ \ifx\u\chit@oob@vspacer%
+ \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'}
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
+ \xdef\ll{\pgfmathresult}
+ \chit@dbg{2}{\string\ll=`\ll'}
+ \chit@oob@rowupdate(\c,\r){\ll}{#4}
+ \else
+ \ifnum\chitdbglvl>2%
+ \node[minimum width=#3cm,minimum height=#3cm,
+ draw,transform shape] at (\c,\r) {};
+ \fi
+ \ifx\u\chit@blank\else%
+ \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
+ \fi%
+ \chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
\fi
- \ifx\u\chit@blank\else%
- \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
- \fi%
- \chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
\fi
}
\fi
@@ -153,7 +165,7 @@
% \chit@dbg{2}{ \space Breaking loop \rr\space > \y}%
% \breakforeach%
%\else%
- \chit@oob@rowupdate(\c,\r){#3}{#4}
+ \chit@oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
%\fi
}
\fi
@@ -166,6 +178,169 @@
\@ifnextchar;{\@gobble}{}}
% \end{macrocode}
%
+% Horizontal flow OOB
+%
+% \begin{macrocode}
+\def\wg@star@hoob{\wg@oob@invtrue\wg@hoob}
+\def\wg@nostar@hoob{\wg@oob@invfalse\wg@hoob}
+\def\hoob{%
+ \@ifstar{\wg@star@hoob%
+ }{\wg@nostar@hoob%
+ }%
+}
+% \end{macrocode}
+%
+% The inner macro of \cs{hoob}. The arguments are
+% \begin{enumerate}
+% \item The list of lists of chits styles
+% \item The maximum number of columns
+% \item The width of each cell
+% \item Additional row spacing between turns
+% \end{enumerate}
+%
+% \begin{macrocode}
+\def\wg@hoob#1#2#3#4{
+ \def\r{0}
+ \def\c{0}
+ \pgfmathparse{#3*(#2-1)}%
+ \edef\a{\pgfmathresult}
+ \chit@dbg{2}{OOB: `#1'}
+ \foreach[count=\ti from 0] \t/\y in #1{
+ \xdef\o{\r}
+ % \def\c{0}
+ \ifx\t\y\def\y{0}\fi
+ \chit@dbg{2}{Turn \ti\space(\r,\t,y=\y):'}
+ \ifx\t\empty\else
+ % Count how many are left for this turn
+ \chit@dbg{2}{At start of turn \t\space\string\c=\c}
+ \def\l{\c}%
+ \let\ig\empty
+ \foreach \u/\m in \t{
+ \ifx\ig\empty
+ \ifx\u\empty\else
+ \ifx\u\m\def\m{1}\fi
+ \ifx\u\chit@oob@spacer%
+ \pgfmathparse{\l+\m*#4}\xdef\l{\pgfmathresult}
+ \chit@dbg{2}{Got \m\space hspace (#4) -> \l}
+ \else
+ \ifx\u\chit@oob@vspace%
+ \xdef\ig{1}
+ \chit@dbg{2}{Got vspace -> \l (\ig)}
+ \else
+ \pgfmathparse{\l+\m*#3}
+ \xdef\l{\pgfmathresult}
+ \chit@dbg{2}{Got \m\space units -> \l}
+ \fi
+ \fi
+ \fi
+ \fi}
+ % Check if there's enough room
+ \chit@dbg{2}{To fill the rest of turn needs `\l' compared to
+ `\a' (#3*(#2-1))}
+ \pgfmathparse{ifthenelse(abs(\l)>=#3*(#2-1),0,1}%
+ \xdef\l{\pgfmathresult}%
+ \chit@dbg{2}{Break or not `\l'}
+ \ifnum\l=0\chit@oob@turnupdate(\c,\r){#3}{#4}\fi
+ \fi
+ \ifwg@oob@inv%
+ \pic[transform shape] at (\c+.5*#3,\r) {chit/oob turn=\ti};% was dx=0.5
+ \else
+ \pic[transform shape] at (\c+-.5*#3,\r) {chit/oob turn=\ti};% was dx=-0.5
+ \fi%
+ %\chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \ifx\t\empty\else%
+ \def\lv{0}
+ \foreach \u/\m in \t{
+ %% \chit@dbg{2}{ `\u'=`\m'}
+ \ifx\u\empty\else
+ \ifx\m\@empty\def\m{1}\fi
+ \ifx\u\m\def\m{1}\fi
+ \foreach \n in {1,...,\m}{%
+ \chit@dbg{2}{OOB Chit is `\u' `\chit@oob@spacer'}%
+ \ifx\u\chit@oob@spacer%
+ \chit@dbg{3}{Chit `\u' is spacer `\chit@oob@spacer'}
+ \pgfmathparse{\c+#4}%
+ \xdef\c{\pgfmathresult}%
+ \else%
+ \ifx\u\chit@oob@vspacer%
+ \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'}
+ \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)}
+ \xdef\ll{\pgfmathresult}
+ \chit@dbg{2}{\string\ll=`\ll'}
+ \chit@oob@rowupdate(\c,\r){\ll}{#4}
+ \xdef\lv{1}
+ \else
+ \ifnum\chitdbglvl>2%
+ \node[minimum width=#3cm,minimum height=#3cm,
+ draw,transform shape] at (\c,\r) {};
+ \fi
+ \ifx\u\chit@blank\else%
+ \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);%
+ \fi%
+ \chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \fi
+ \fi
+ }
+ \fi
+ }
+ \fi
+ \chit@dbg{2}{ End of chits in turn
+ \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ % --- Not relevant, I think
+ % IF no units where given, then we force \c to be non-zero so that
+ % \chit@oob@turnupdate increments the row
+ % \ifx\t\@empty
+ % \def\c{#3}
+ % \chit@dbg{2}{ Turn is empty, set c=`\c'}
+ % \fi
+ % ---
+ %\ifnum\y<0% No explicit number of rows given
+ % \def\c{#3}
+ % \chit@dbg{2}{ No explicit number of rows given, set c=`\c'}
+ %\fi
+ % In case the user gave and explicit number of rows, add the rows
+ % that are missing. \y is initially set to the number of
+ % requested rows, and then decremented every time we go down one
+ % row. So if the number of rows we did so far is N, and the
+ % requested number of rows is M, then the loop below adds M-N
+ % rows.
+ \ifnum\y>0%
+ \chit@dbg{2}{ Looping rows from 2 to \y, break when row > \y}%
+ \foreach \rr in {2,...,\y}{
+ %\ifnum\rr>\y% A little funny, but \y can be negative!
+ % \chit@dbg{2}{ \space Breaking loop \rr\space > \y}%
+ % \breakforeach%
+ %\else%
+ \chit@oob@rowupdate(\c,\r){#3}{0}% Extra spacing?
+ %\fi
+ }
+ \fi
+ % --- Not relevant I think
+ % This will zero \c. However, if on entry |\c|>0, then we also
+ % increment the row
+ % \chit@oob@turnupdate(\c,\r){#3}{#4}
+ % ---
+ % Horizontal spacer
+
+ %\pgfmathparse{ifthenelse(abs(\c)>=\a,1,0)}\xdef\l{\pgfmathresult}
+ \pgfmathparse{\c+1.5*#4}%
+ \xdef\c{\pgfmathresult}%
+ \ifnum\lv=1%
+ \pgfmathparse{\r-#4}
+ \chit@oob@rowupdate(\c,\r){0}{#4}
+ \else
+ \chit@oob@cellupdate(\c,\r){#2}{#3}{\y}
+ \ifnum\y<0
+ \chit@oob@turnupdate(\c,\r){#3}{#4}
+ \else
+ \fi
+ \fi
+ % \xdef\y{0}
+ \chit@dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')}
+ }
+ \chit@dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')}
+ \@ifnextchar;{\@gobble}{}}
+% \end{macrocode}
% \iffalse
% </chit>
% --------------------------------------------------------------------
diff --git a/macros/latex/contrib/wargame/source/chit/shape.dtx b/macros/latex/contrib/wargame/source/chit/shape.dtx
index 8a3d70fbd0..f68ea25a44 100644
--- a/macros/latex/contrib/wargame/source/chit/shape.dtx
+++ b/macros/latex/contrib/wargame/source/chit/shape.dtx
@@ -92,7 +92,7 @@
chit/symbol/.style={scale=.4,transform shape},
chit/parts/.style={shape=rectangle,transform shape},
chit/factors/.style={chit/parts,anchor=south},
- chit/left/.style={chit/parts,anchor=south,rotate=90},
+ chit/left/.style={chit/parts,anchor=base,rotate=90},%Anchor was south
chit/right/.style={chit/parts,anchor=north,rotate=90},
chit/upper left/.style={chit/parts,anchor=north west},
chit/upper right/.style={chit/parts,anchor=north east},
@@ -141,7 +141,8 @@
% \begin{macrocode}
\tikzset{%
chit/.code={%
- \pgfkeys{/tikz/transform shape,/tikz/shape=chit}
+ \chit@dbg{2}{chit arguments are `#1'}%
+ \pgfkeys{/tikz/transform shape,/tikz/shape=chit}%
\pgfkeys{/chit/.cd,#1}}}
% \end{macrocode}
% \end{TikzKey}
@@ -657,7 +658,11 @@
%
% The work horse. This simply makes a \cs{node} with the shape
% \texttt{chit}. Note, we allow for a trailing semi-colon
-% (\texttt{;}) to have a similar feel to other \TikZ{} macros.
+% (\texttt{;}) to have a similar feel to other \TikZ{} macros.
+%
+% The macro will execute the style \texttt{/tikz/every chit} if
+% defined. Note that this will be executed \emph{before} the usual
+% \texttt{every chip node} style.
%
% \begin{macrocode}
\def\chit@@@#1#2(#3){%
@@ -667,7 +672,7 @@
^^J Name: `#3'}
\let\name\pgfutil@empty%
\chit@dbg{1}{=== Before chit node}%
- \node[chit={every chit/.try,id=#3,#1}] (tmp) at (#2) {};
+ \node[chit={/tikz/every chit/.try,id=#3,#1}] (tmp) at (#2) {};
\chit@dbg{2}{=== After chit node}%
\ifx|#3|\relax%
\else%
diff --git a/macros/latex/contrib/wargame/source/chit/table.dtx b/macros/latex/contrib/wargame/source/chit/table.dtx
index 7094e436ed..f99236119e 100644
--- a/macros/latex/contrib/wargame/source/chit/table.dtx
+++ b/macros/latex/contrib/wargame/source/chit/table.dtx
@@ -7,7 +7,9 @@
% \begin{macrocode}
\tikzset{
chit/cell background/.style={fill=black},
+ %chit/cell background flipped/.style={fill=black},
blank chit/.style={/chit/frame={draw=none,fill=none}},
+ chit/grid lines/.style={dashed},
}
% \end{macrocode}
%
@@ -20,6 +22,10 @@
\def\chit@cellbg(#1,#2)#3{%
\draw[chit/cell background](#1-#3/2,#2-#3/2) rectangle++(#3,#3);
}
+\def\chit@celldblbg(#1,#2)#3{%
+ \draw[chit/cell background,chit/cell background flipped/.try]%
+ (#1-#3/2,#2-#3/2) rectangle++(#3,#3);
+}
% \end{macrocode}
%
% \begin{Macro}{\ifchits@reset}
@@ -83,6 +89,27 @@
\@ifnextchar;{\@gobble}{}}
% \end{macrocode}
% \end{Macro}
+% \begin{Macro}{\chitgrid}
+% \begin{enumerate}
+% \item columns
+% \item rows
+% \item cell-size
+% \end{enumerate}
+%
+% \begin{macrocode}
+\def\chitgrid#1#2#3{%
+ \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}%
+ %\draw[red](-#3/2,\rmin)rectangle(#3*#1-#3/2,-\rmax);
+ \foreach \cc in {0,...,#1}{
+ \draw[chit/grid lines] (\cc*#3-#3/2,3*#3/4)--(\cc*#3-#3/2,-\rmax-#3/4);}
+ %\chit@dbg{0}{Drawing horizontal lines from `\rmin, `-\rmin', ..., `-\rmax'}
+ \foreach \rr in {\rmin,-\rmin,...,-\rmax}{
+ %\chit@dbg{0}{Horizontal line at `\rr'}
+ \draw[chit/grid lines] (-3*#3/4,\rr)--(#1*#3-#3/4,\rr);}
+}
+% \end{macrocode}
+% \end{Macro}
%
% \begin{Macro}{\doublechits,
% \@doublechits,
@@ -154,7 +181,7 @@
\chit@cellbg(\c,\r){#3}
\chit[\u=\ti](\c,\r)
\chit@dbl@flip(\c,\r){#3}
- \chit@cellbg(\mc,\r){#3}
+ \chit@celldblbg(\mc,\r){#3}
\chit[\u\space flipped=\ti,zone turn=\t,zone mult=\n](\mc,\r)
\chit@dbl@cellupdate(\c,\r){#2}{#3}
\fi
@@ -166,10 +193,39 @@
\draw[dashed](0,-3*#3/4)--(0,\r-#3/4);%
\draw[dashed,<-] (#3/5,-2*#3/3)--(#3/2,-2*#3/3) node[transform shape,anchor=west]{Back};%
\draw[dashed,<-] (-#3/5,-2*#3/3)--(-#3/2,-2*#3/3) node[transform shape,anchor=east]{Front};%
+ % \foreach \cc in {0,...,#2}{
+ % \draw[dashed] (\cc*#3,-3*#3/4)--(\cc*#3,\r-#3/4);
+ % \draw[dashed] (-\cc*#3,-3*#3/4)--(-\cc*#3,\r-#3/4);}
+ % \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ % \chit@dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\r'}
+ % \foreach \rr in {-\rmin,\rmin,...,\r}{
+ % \chit@dbg{0}{Horizontal line at `\rr'}
+ % \draw[dashed] (-#2*#3-#3/4,\rr)--(#2*#3+#3/4,\rr);}
\@ifnextchar;{\@gobble}{}}
% \end{macrocode}
% \end{Macro}
%
+% \begin{Macro}{\doublechitgrid}
+% \begin{enumerate}
+% \item columns
+% \item rows
+% \item cell-size
+% \end{enumerate}
+%
+% \begin{macrocode}
+\def\doublechitgrid#1#2#3{%
+ \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}%
+ \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}%
+ \foreach \cc in {0,...,#1}{
+ \draw[chit/grid lines] (\cc*#3,-3*#3/4)--(\cc*#3,\rmax+#3/4);
+ \draw[chit/grid lines] (-\cc*#3,-3*#3/4)--(-\cc*#3,\rmax+#3/4);}
+ %\chit@dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\rmax'}
+ \foreach \rr in {-\rmin,\rmin,...,\rmax}{
+ %\chit@dbg{0}{Horizontal line at `\rr'}
+ \draw[chit/grid lines] (-#1*#3-#3/4,\rr)--(#1*#3+#3/4,\rr);}
+}
+% \end{macrocode}
+% \end{Macro}
% \iffalse
% </chit>
% --------------------------------------------------------------------
diff --git a/macros/latex/contrib/wargame/source/hex/labels.dtx b/macros/latex/contrib/wargame/source/hex/labels.dtx
index 7767dcc661..f622bf6cda 100644
--- a/macros/latex/contrib/wargame/source/hex/labels.dtx
+++ b/macros/latex/contrib/wargame/source/hex/labels.dtx
@@ -132,7 +132,7 @@
%
% \begin{macrocode}
\def\hex@do@label{%
- \hex@dbg{1}{Hex label: `\meaning\hex@label'}%
+ \hex@dbg{3}{Hex label: `\meaning\hex@label'}%
\edef\hex@l@tmp{[%
/hex/label/.cd,%
rotate=0,%
diff --git a/macros/latex/contrib/wargame/source/hex/ridges.dtx b/macros/latex/contrib/wargame/source/hex/ridges.dtx
index 24552e36e2..658f55888b 100644
--- a/macros/latex/contrib/wargame/source/hex/ridges.dtx
+++ b/macros/latex/contrib/wargame/source/hex/ridges.dtx
@@ -157,11 +157,12 @@
\xdef\hex@r@p{\hex@r@p ($(300:\hex@r@r)+(-120:\hex@r@t/2)$)}
\fi
\ifhex@r@ne
- \xdef\hex@r@p{\hex@r@p --cycle}
+ %\xdef\hex@r@p{\hex@r@p --cycle}
+ \xdef\hex@r@p{\hex@r@p -- (0:\hex@r@r)}
\else
\xdef\hex@r@p{\hex@r@p --(.5:\hex@r@r)}
\fi
- \hex@dbg{4}{Ridge along se: `\hex@r@p'}
+ \hex@dbg{4}{Ridge along south east: `\hex@r@p'}
\fi
\hex@dbg{3}{ Ridges path: \hex@r@p}
% \draw[red] \hex@r@p;
diff --git a/macros/latex/contrib/wargame/source/hex/terrain.dtx b/macros/latex/contrib/wargame/source/hex/terrain.dtx
index 4c486adf77..9d15a555ec 100644
--- a/macros/latex/contrib/wargame/source/hex/terrain.dtx
+++ b/macros/latex/contrib/wargame/source/hex/terrain.dtx
@@ -37,6 +37,7 @@
% select the common terrains.
%
% \begin{macrocode}
+\newif\if@hex@t@rot\@hex@t@rotfalse%
\tikzset{%
/hex/terrain/.search also={/tikz},%
/hex/terrain/.cd,%
@@ -44,6 +45,7 @@
image/.store in=\hex@t@image,%
code/.store in=\hex@t@code,%
clip/.store in=\hex@t@clip,%
+ random rotation/.is if=@hex@t@rot,
pic/.default=,
image/.default=,
code/.default=,
@@ -137,8 +139,23 @@
\@ifundefined{hex@t@code}{\let\hex@t@code\empty}{}
% \end{macrocode}
%
+% Possible make rotation. We define a scope and rotate within that.
+%
+% \begin{macrocode}
+ \def\hex@t@angle{0}%
+ \if@hex@t@rot%
+ \pgfmathrandominteger{\hex@t@angle}{0}{5}
+ \pgfmathparse{int(60*\hex@t@angle)}\edef\hex@t@angle{\pgfmathresult}%
+ \fi%
+ \hex@dbg{5}{Will rotate terrain by `\hex@t@angle'}%
+% \end{macrocode}
+%
+% If we have specified code for the terrain, then execute that.
+%
% \begin{macrocode}
- \ifx\hex@t@code\empty\else\hex@t@code\fi%
+ \scope[rotate=\hex@t@angle]%
+ \ifx\hex@t@code\empty\else\hex@t@code\fi%
+ \endscope% End rotate code
% \end{macrocode}
% First we check if we have not got terrain images, but terrain
% pictures. If we have that, we process these in turn. Note, the
@@ -154,7 +171,9 @@
\hex@dbg{5}{Terrain pictures}%
\pgfpointorigin\wg@tmpa=\pgf@x\wg@tmpb=\pgf@y%
\foreach \i in \hex@t@pic{%
- \wg@pic@all{\i}{}{\the\wg@tmpa,\the\wg@tmpb}{}}%
+ \wg@pic@all{\i}{}{\the\wg@tmpa,\the\wg@tmpb}{%
+ rotate=\hex@t@angle,
+ transform shape}}%
\fi% We have pictures.
% \end{macrocode}
%
@@ -172,6 +191,7 @@
\expandafter\wg@node{%
\includegraphics[width=2cm]{\i}}\@endwg@node %
{}{\wg@tmpa,\wg@tmpb}{%
+ rotate=\hex@t@angle,%
shape=rectangle,%
anchor=center,%
transform shape,%
diff --git a/macros/latex/contrib/wargame/source/tests/chits.dtx b/macros/latex/contrib/wargame/source/tests/chits.dtx
index 7dcf26c50d..966e3b4a9f 100644
--- a/macros/latex/contrib/wargame/source/tests/chits.dtx
+++ b/macros/latex/contrib/wargame/source/tests/chits.dtx
@@ -6,7 +6,11 @@
% Some chits for testing stuff
%
% \begin{macrocode}
-\def\firstchit{
+\makeatletter
+\def\firstchit{%
+ \@ifnextchar[{\@firstchit}{\@firstchit[]}%]
+}%
+\def\@firstchit[#1]{
% \chitdbglvl=5
% \natoappdbglvl=5
\chit[symbol={
@@ -17,13 +21,14 @@
left={text=A},
frame={fill=yellow!50!black},
ultra thick,
- command=land},
+ command=land,
+ },
left={chit/identifier={1}},
right={chit/identifier={2}},
factors={chit/2 factors={4,8}},
frame={draw=black},
- color=white,text=yellow,fill={blue}]}
-\makeatletter
+ color=white,text=yellow,fill={blue},
+ #1]}
\def\secondchit{%
\@ifnextchar({\second@chit}{\second@chit(0,0)}%)
}
@@ -34,6 +39,7 @@
command=air](0,-.15)},
left={[{red,font=\noexpand\sffamily}]chit/identifier={Fighter}},
right={chit/identifier={USAF}},
+ fill=white,
factors={chit/1 factor=3}}] at (#1){};}
\def\thirdchit{
\chit[symbol={[echelon=battalion,
diff --git a/macros/latex/contrib/wargame/source/tests/test.tex b/macros/latex/contrib/wargame/source/tests/test.tex
index 5833d679f2..49062b70f0 100644
--- a/macros/latex/contrib/wargame/source/tests/test.tex
+++ b/macros/latex/contrib/wargame/source/tests/test.tex
@@ -2,6 +2,7 @@
\usepackage{wargame}
\usetikzlibrary{decorations.markings}
+\usetikzlibrary{shadows.blur}
\title{A test of \textsf{wargame}}
\author{}
\date{}
@@ -28,7 +29,7 @@
\section{Some chits}
-\begin{tikzpicture}
+\begin{tikzpicture}[every chit node/.style={blur shadow={shadow blur steps=5}}]
\fill[red!50] (1,-1) rectangle (3,1);
\firstchit(0,0)%
%\secondchit(2,0)%
@@ -45,18 +46,20 @@
\end{tikzpicture}
\section{Chits on a board}
-\begin{tikzpicture}
+\begin{tikzpicture}[every chit/.style={chit drop}]
+ \chitdbglvl=5
\begin{scope}[every hex/.style={/hex/label=auto},transform shape]
\boardframe[0.5](c=0,r=0)(c=3,r=3)
\boardclip(c=0,r=0)(c=3,r=3){fill=white}
\testmap{}
- \firstchit(hex cs:c=2,r=1)
- \secondchit(hex cs:c=3,r=0)
+ \firstchit[no chit drop](hex cs:c=2,r=2)
+ %\secondchit(hex cs:c=3,r=0)
\thirdchit(hex cs:c=0,r=3)
\stackchits(hex cs:c=0,r=1)(.3,.3){
\noexpand\firstchit,
- \noexpand\secondchit/\noexpand\chit[{full=chit/eliminate}]}
+ \noexpand\secondchit%/\noexpand\eliminatechit
+ }
\begin{scope}[m/.style={hex/long move=green}]
\path[m] (hex cs:c=3,r=0) -- (hex cs:c=3,r=1)--(hex cs:c=3,r=2);
diff --git a/macros/latex/contrib/wargame/source/util/export.dtx b/macros/latex/contrib/wargame/source/util/export.dtx
index fde067dfe8..09f74c0513 100644
--- a/macros/latex/contrib/wargame/source/util/export.dtx
+++ b/macros/latex/contrib/wargame/source/util/export.dtx
@@ -72,6 +72,7 @@
%
% Preceed all images (\textsf{tikzpicture}) with this command
%
+%
% First argument is the name of the image. This can be anything.
% Note that for counters, if the name ends in \texttt{flipped} then it
% is considered the backside of a counter.
@@ -140,13 +141,32 @@
%
% Make separate images for each counter (single sided).
%
+% First optional argument is the group to put the chits into.
+% Second optional argument is options to give to each Tikz picture
+% environment. Third, mandatory, argument is the list of chit
+% identifiers to render.
+%
% \begin{macrocode}
-\newcommand\chitimages[2][]{%
+\def\wg@add@drop@margin{%
+ \@ifundefined{wg@drop@margin}{}{
+ \dimen0=\wg@drop@margin
+ % \ifwg@chit@drop
+ \ifdim\dimen0>0pt%
+ \path ($(current bounding box.north east)+(45:\wg@drop@margin)$)
+ -- ($(current bounding box.south west)+(225:\wg@drop@margin)$);
+ \fi}}
+\def\chitimages{%
+ \@ifnextchar[{\@chitimages}{\chitimages[]}%]
+}%
+\def\@chitimages[#1]{%
+ \@ifnextchar[{\@@chitimages[#1]}{\@@chitimages[#1][]}%]
+}%
+\def\@@chitimages[#1][#2]#3{%
\begingroup%
\let\chit@report\do@chit@report%
\let\natoapp@report\do@natoapp@report%
- \chit@dbg{2}{chits to make images of `#2'}%
- \foreach[count=\ti from 0] \t/\x in #2{%
+ \chit@dbg{2}{chits to make images of `#3'}%
+ \foreach[count=\ti from 0] \t/\x in #3{%
\chit@dbg{2}{^^JRow: `\t' (`\x')}
\ifx\t\empty\else% Ignore empty rows
\chit@dbg{5}{^^JSubcategory: `\x' (default `#1')}
@@ -156,14 +176,17 @@
\ifx\u\empty\else% Ignore empty cells
\ifx\u\chit@blank\else%
\chit@dbg{2}{Next chit `\u' with possible multiplicity `\m'}%
- \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined
+ \ifx\m\@empty\def\m{1}\fi% If no multiplicity defined
\ifx\u\m\def\m{1}\fi% If the same as unit
\chit@dbg{2}{Next chit `\u' multiplicity `\m'}%
%% We only make one copy of the chit, since we can duplicate
%% it in VASSAL
\info*{\u}{counter}{\x}
- \begin{tikzpicture}
+ \nopagecolor%
+ \gdef\wg@drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]
\chit[\u=\ti]%
+ \wg@add@drop@margin%
\end{tikzpicture}
\end@info%
%% \foreach \n in {1,...,\m}{% Make a number of copies
@@ -189,14 +212,25 @@
%
% Make separate images for each counter (double sided). The back-side
% counters must be defined by append `\texttt{ flipped}' the front
-% face name
+% face name.
+%
+% First optional argument is the group to put the chits into.
+% Second optional argument is options to give to each Tikz picture
+% environment. Third, mandatory, argument is the list of chit
+% identifiers to render.
%
% \begin{macrocode}
-\newcommand\doublechitimages[2][]{%
+\def\doublechitimages{%
+ \@ifnextchar[{\@doublechitimages}{\doublechitimages[]}%]
+}%
+\def\@doublechitimages[#1]{%
+ \@ifnextchar[{\@@doublechitimages[#1]}{\@@doublechitimages[#1][]}%]
+}%
+\def\@@doublechitimages[#1][#2]#3{%
\begingroup%
\let\chit@report\do@chit@report%
\let\natoapp@report\do@natoapp@report%
- \foreach[count=\ti from 0] \t/\x in #2{%
+ \foreach[count=\ti from 0] \t/\x in #3{%
\ifx\t\empty\else% Ignore empty rows
\chit@dbg{5}{^^JSubcategory: `\x' (default `#1')}
% Take sub-category or default
@@ -213,13 +247,18 @@
%% We only make one copy of the chit, since we can duplicate
%% it in VASSAL
\info*{\u}{counter}{\x}%
- \begin{tikzpicture}%
+ \nopagecolor%
+ \gdef\wg@drop@margin{0pt}%
+ \begin{tikzpicture}[chit has drop=false,#2]%
\chit[\u=\ti]%
+ \wg@add@drop@margin%
\end{tikzpicture}%
\end@info%
\info*{\s}{counter}{\x}%
- \begin{tikzpicture}%
+ \nopagecolor%
+ \begin{tikzpicture}[chit has drop=false,#2]%
\chit[\s=\ti]%
+ \wg@add@drop@margin%
\end{tikzpicture}%
\end@info%
%% \foreach \n in {1,...,\m}{% Make a number of copies
@@ -414,7 +453,7 @@
\def\hex@col{0}%
\def\hex@row{0}%
\node[hex,inner sep=0,outer sep=0]{%
- \message{^^JHex label: `\meaning\hex@label'}%
+ %\message{^^JHex label: `\meaning\hex@label'}%
\global\let\mk@label\hex@label}}}%
% \end{macrocode}
%
@@ -427,7 +466,7 @@
\edef\mk@i{\mk@i\space}
%% Everything is made into centimeters
\mk@w{ \mk@i "units": "cm",}
- \hex@dbg{0}{Label: `\meaning\mk@label'}
+ \hex@dbg{3}{Label: `\meaning\mk@label'}
\@ifundefined{mk@label}{}{\mk@w{ \mk@i "labels": "\mk@label",}}
%% Write out coordinate options as "coords" object
\mk@w{ \mk@i"coords": \@lbchar}%
@@ -577,7 +616,7 @@
% optional is the group to add the markers to.
%
% \begin{macrocode}
-\def\wg@gennumberm@rkers#1#2#3{
+\def\wg@gennumberm@rkers#1#2#3#4{
\message{^^JNumbered markers: Type=`#1' Max=`#2' Category=`#3'}
\def\markers{}
\def\keys{}
@@ -585,24 +624,37 @@
\xdef\keys{/tikz/#1 \i/.style={/tikz/#1=\i},\keys}
\xdef\markers{\markers,#1 \i}}
{%
- \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}%
+ \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3][#4]{\markers}}}%
\tikzset{
wg hidden unit/.pic={},
wg hidden unit/.style={
chit={
+ no chit drop,
frame={draw=none,fill=none},
full=wg hidden unit}}}
-\DeclareRobustCommand\battlemarkers[2][BattleMarkers]{%
- \wg@gennumberm@rkers{battle marker}{#2}{#1}%
+%
+% First optional argument are extra styles
+% Second is category
+% Third is number of markers
+%
+\def\battlemarkers{%
+ \@ifnextchar[{\@battlemarkers}{\battlemarkers[]}%]
+}%
+\def\@battlemarkers[#1]{%
+ \@ifnextchar[{\@@battlemarkers[#1]}{\battlemarkers[#1][BattleMarkers]}%]
+}%
+\def\@@battlemarkers[#1][#2]#3{%
+ \wg@gennumberm@rkers{battle marker}{#3}{#2}{#1}%
\message{^^JMake a hidden unit and add to Markers category}
{%
\nopagecolor%
\chitimages[Markers]{{wg hidden unit}}%
%
\info{battle-marker-icon}{icon}{}%
- \tikz[scale=.7,transform shape]{\pic{battle marker=0};}%
+ \tikz[scale=.7,transform shape,auto icon more/.try]{%
+ \pic{battle marker=0};}%
\info{clear-battles-icon}{icon}{}
- \tikz[scale=.4,transform shape]{%
+ \tikz[scale=.4,transform shape,auto icon more/.try]{%
\pic{eliminate icon};
\pic[scale=.7,transform shape] at (-.3,0) {battle marker=0};}%
}%
@@ -613,21 +665,40 @@
% Optional is the group to add the markers to.
%
% \begin{macrocode}
-\def\wg@gencolorm@rkers#1#2#3{%
+\def\wg@gencolorm@rkers#1#2#3#4{%
\def\markers{}
\def\keys{}
- \foreach \o/\f in {#2}{%
+ \foreach \o/\f/\n [count=\i] in {#2}{%
+ \ifx\n\f\def\n{\o}\fi%
\ifx\o\f\def\f{white}\fi%
- \message{^^JOdds marker `#1 \o' w/fill `\f'}%
- \xdef\keys{/tikz/#1 \o/.style={/tikz/#1={\o,\f}},\keys}
- \xdef\markers{\markers,#1 \o}}
- {\nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}%
-\DeclareRobustCommand\oddsmarkers[2][OddsMarkers]{%
- \wg@gencolorm@rkers{odds marker}{#2}{#1}%
+ \message{^^JColour no \i marker `#1 \n' w/fill `\f' text `\o'}%
+ \protected@xdef\keys{/tikz/#1 \n/.style={/tikz/#1={\o,\f}},\keys}
+ \xdef\markers{\markers,#1 \n}
+ }%
+ {%
+ \nopagecolor%
+ \pgfkeysalsofrom{\keys}%
+ \chitimages[#3][#4]{\markers}%
+ }%
+}%
+%
+% First optional argument are extra styles
+% Second is category
+% Third is marker list
+%
+\def\oddsmarkers{%
+ \@ifnextchar[{\@oddsmarkers}{\oddsmarkers[]}%]
+}%
+\def\@oddsmarkers[#1]{%
+ \@ifnextchar[{\@@oddsmarkers[#1]}{\oddsmarkers[#1][OddsMarkers]}%]
+}%
+\def\@@oddsmarkers[#1][#2]#3{%
+ \wg@gencolorm@rkers{odds marker}{#3}{#2}{#1}%
\info{odds-battles-icon}{icon}{}
- \tikz[scale=.5,transform shape]{\pic{odds marker={?:?,white}}}
+ \tikz[scale=.5,transform shape,auto icon more/.try]{%
+ \pic{odds marker={?:?,white}}}
\info{resolve-battles-icon}{icon}{}
- \tikz[scale=.3,transform shape]{%
+ \tikz[scale=.3,transform shape,auto icon more/.try]{%
\pic{dice};
\pic[scale=1.2,transform shape] at (-.2,-.2) {battle marker=0};}%
}
@@ -636,40 +707,51 @@
% Make results markers. Mandatory argument is a list of results and
% fill colours. Optional is the group to add the markers to.
%
+%
+% First optional argument are extra styles
+% Second is category
+% Third is marker list
+%
% \begin{macrocode}
-\DeclareRobustCommand\resultmarkers[2][ResultMarkers]{%
- \wg@gencolorm@rkers{result marker}{#2}{#1}}
+\def\resultmarkers{%
+ \@ifnextchar[{\@resultmarkers}{\resultmarkers[]}%]
+}%
+\def\@resultmarkers[#1]{%
+ \@ifnextchar[{\@@resultmarkers[#1]}{\resultmarkers[#1][ResultMarkers]}%]
+}%
+\def\@@resultmarkers[#1][#2]#3{%
+ \wg@gencolorm@rkers{result marker}{#3}{#2}{#1}}%
% \end{macrocode}
%
% Common icons used by many modules
%
% \begin{macrocode}
-\DeclareRobustCommand\commonicons[2]{%
+\DeclareRobustCommand\commonicons[3][]{%
\begingroup%
\nopagecolor%
- \tikzset{icon/.style={scale=.4,transform shape}}%
+ \tikzset{auto icon/.style={scale=.4,transform shape,#1}}%
%
\info{pool-icon}{icon}{}
- \tikz[icon]{\pic{pool icon};}
+ \tikz[auto icon,auto icon more/.try]{\pic{pool icon};}
%
\info{oob-icon}{icon}{}%
- \tikz[icon]{\pic{oob icon={#1}{#2}};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{oob icon={#2}{#3}};}%
%
\info{flip-icon}{icon}{}%
- \tikz[icon]{\pic{flip icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{flip icon};}%
%
\info{eliminate-icon}{icon}{}%
- \tikz[icon]{\pic{eliminate icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{eliminate icon};}%
%
\info{restore-icon}{icon}{}%
- \tikz[icon]{\pic{restore icon};}%
+ \tikz[auto icon,auto icon more/.try]{\pic{restore icon};}%
%
\info{dice-icon}{icon}{}%
- \tikz[icon,scale=.9]{\pic{dice};}%
+ \tikz[auto icon,scale=.9,auto icon more/.try]{\pic{dice};}%
%
\info{unit-icon}{icon}{}%
- \tikz[icon,scale=.7]{%
- \chit[fill=#1,
+ \tikz[auto icon,scale=.7,auto icon more/.try]{%
+ \chit[fill=#2,
symbol={[
scale line widths,
line width=1pt,
@@ -677,7 +759,29 @@
command=land,
main=infantry,
scale=1.3](0,-.15)}]}%
- \endgroup%
+ %
+ \info{layer-icon}{icon}{}%
+ \begin{tikzpicture}[scale=.25]
+ \foreach \i in {-1,0,1}{
+ \scoped[shift={(0,\i*.15)}]{
+ \draw[black,fill=white] (-.5,0)
+ --(0,.3)--(.5,0)--(0,-.3)--cycle;
+ }
+ }
+ \end{tikzpicture}%
+ %
+ \info{los-icon}{icon}{}
+ \begin{tikzpicture}[scale=.25]
+ \draw[scale line widths,line width=2pt,fill=white](-.5,0)
+ to[out=70,in=110] (.5,0)
+ to[out=-110,in=-70] cycle;
+ \begin{scope}[even odd rule]
+ \clip circle(.2);
+ \fill circle(.2) (125:.18) circle(.1);
+ \end{scope}
+ \end{tikzpicture}%
+ %
+ \endgroup%
}
% \end{macrocode}
%
@@ -708,9 +812,11 @@
\foreach \v/\p in {#5}{%
\info{#3-\v}{die-roll}{#3}
\tikz[#1]{
- \node[shape=#4,transform shape,draw=none,fill=black,opacity=.5]
- at (.05,-.03){};
- \node[shape=#4,#2,transform shape]{\p};}}}
+ %\node[shape=#4,transform shape,draw=none,fill=black,opacity=.5]
+ %at (.05,-.03){};
+ \node[shape=#4,#2,transform shape,
+ chit drop
+ ]{\p};\wg@add@drop@margin{}}}}
% \end{macrocode}
%
% \subsubsection{Hooks into chits, etc.}
@@ -809,6 +915,28 @@
\mk@w{ \mk@i\space "end": 0}
\mk@w{ \mk@i \@rbchar}
}
+\tikzset{
+ chit drop margin/.store in=\wg@drop@margin,
+ chit drop shadows/.code={
+ \pgfkeysalso{%
+ /tikz/every chit node/.prefix style={chit drop={#1}},
+ /tikz/chit has drop=true}
+ },
+ chit drop shadows/.default=,
+ marker drop shadows/.code={
+ \pgfkeysalso{%
+ /tikz/every battle marker/.prefix style={chit drop={#1}},
+ /tikz/every odds marker/.prefix style={chit drop={#1}},
+ /tikz/every result marker/.prefix style={chit drop={#1}},
+ /tikz/auto icon more/.prefix style={no chit drop}}},
+ marker drop shadows/.default={
+ chit has drop=false,
+ shadow xshift=0.04cm,
+ shadow yshift=-0.04cm,
+ shadow blur radius=0.04cm}
+}
+
+
% \end{macrocode}
%
%
diff --git a/macros/latex/contrib/wargame/source/util/tikz.dtx b/macros/latex/contrib/wargame/source/util/tikz.dtx
index fa31a7b58c..2f6dbefc17 100644
--- a/macros/latex/contrib/wargame/source/util/tikz.dtx
+++ b/macros/latex/contrib/wargame/source/util/tikz.dtx
@@ -86,12 +86,17 @@
% Save pgf rounded corners macro
% \let\wg@pgfsetcornersarced\pgfsetcornersarced
\def\wg@setcornersarched#1{%
- \ifx|#1|\else%
- \edef\pgf@corner@arc{{#1}{#1}}%
- \pgf@arccornerstrue%
- \ifdim#1=0pt%
- \pgf@arccornersfalse%
- \fi\fi}
+ \def\arg{#1}%
+ \let\isarched\relax% Cannot set \ifpgf@arccorners directly inside
+ % other \if
+ \ifx\arg\@empty\else%
+ \edef\pgf@corner@arc{{#1}{#1}}%
+ \let\isarched\pgf@arccornerstrue%
+ \ifdim#1=0pt%
+ \let\isarched\pgf@arccornersfalse%
+ \fi%
+ \fi%
+ \isarched}
\newdimen\wg@lw@scaled\wg@lw@scaled=1pt
\def\wg@getscale{%
\pgfgettransformentries{%
diff --git a/macros/latex/contrib/wargame/source/utils/wgexport.py b/macros/latex/contrib/wargame/source/utils/wgexport.py
index a09a7e4257..d573b63d36 100755
--- a/macros/latex/contrib/wargame/source/utils/wgexport.py
+++ b/macros/latex/contrib/wargame/source/utils/wgexport.py
@@ -208,6 +208,8 @@ CTRL_SHIFT = CTRL+SHIFT
ALT_SHIFT = ALT+SHIFT
NONE = '\ue004'
NONE_MOD = 0
+
+# --------------------------------------------------------------------
def key(let,mod=CTRL):
'''Encode a key sequence
@@ -220,6 +222,8 @@ def key(let,mod=CTRL):
Modifier mask
'''
return f'{ord(let)},{mod}'
+
+# --------------------------------------------------------------------
#
def hexcolor(s):
if isinstance(s,str):
@@ -241,6 +245,7 @@ def hexcolor(s):
return rgb(int(r*256),int(g*256),int(b*256))
+# --------------------------------------------------------------------
# Colour encoding
def rgb(r,g,b):
'''Encode RGB colour
@@ -261,6 +266,7 @@ def rgb(r,g,b):
'''
return ','.join([str(r),str(g),str(b)])
+# --------------------------------------------------------------------
def rgba(r,g,b,a):
'''Encode RGBA colour
@@ -282,6 +288,7 @@ def rgba(r,g,b,a):
'''
return ','.join([str(r),str(g),str(b),str(a)])
+# --------------------------------------------------------------------
def dumpTree(node,ind=''):
'''Dump the tree of nodes
@@ -296,6 +303,12 @@ def dumpTree(node,ind=''):
for c in node.childNodes:
dumpTree(c,ind+' ')
+# --------------------------------------------------------------------
+def registerElement(cls):
+
+ Element.known_tags[cls.TAG] = cls
+
+
#
# EOF
#
@@ -310,6 +323,8 @@ class Element:
MAP = MODULE + 'map.'
PICKER = MAP + 'boardPicker.'
BOARD = PICKER + 'board.'
+ known_tags = {}
+
def __init__(self,parent,tag,node=None,**kwargs):
'''Create a new element
@@ -429,9 +444,14 @@ class Element:
return {c[key] : c for c in cand}
return cand
- def getParent(self,cls,checkTag=True):
+ def getParent(self,cls=None,checkTag=True):
if self._node.parentNode is None:
return None
+ if cls is None:
+ cls = self.getTagClass(self._node.parentNode.tagName)
+ checkTag = False
+ if cls is None:
+ return None
if checkTag and self._node.parentNode.tagName != cls.TAG:
return None
return cls(self,node=self._node.parentNode)
@@ -440,6 +460,10 @@ class Element:
'''Searches back until we find the parent with the right
class, or none
'''
+ try:
+ iter(cls)
+ except:
+ cls = [cls]
t = {c.TAG: c for c in cls}
p = self._node.parentNode
while p is not None:
@@ -447,6 +471,11 @@ class Element:
if c is not None: return c(self,node=p)
p = p.parentNode
return None
+
+ def getTagClass(self,tag):
+ '''Get class corresponding to the tag'''
+ if tag not in self.known_tags: return None;
+ return self.known_tags[tag]
# ----------------------------------------------------------------
# Adders
@@ -518,7 +547,83 @@ class DummyElement(Element):
'''
super(DummyElement,self).__init__(parent,'Dummy',node=node)
+# --------------------------------------------------------------------
+class ToolbarElement(Element):
+ def __init__(self,
+ parent,
+ tag,
+ node = None,
+ name = '', # Toolbar element name
+ tooltip = '', # Tool tip
+ text = '', # Button text
+ icon = '', # Button icon,
+ hotkey = '', # Named key or key stroke
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ **kwargs):
+ '''Base class for toolbar elements.
+ Parameters
+ ----------
+ parent : Element
+ Parent element if any
+ tag : str
+ Element tag
+ node : XMLNode
+ Possible node - when reading back
+ name : str
+ Name of element (user reminder). If not set, and tooltip is set,
+ set to tooltip
+ toolttip : str
+ Tool tip when hovering. If not set, and name is set, then
+ use name as tooltip.
+ text : str
+ Text of button
+ icon : str
+ Image path for button image
+ hotkey : str
+ Named key or key-sequence
+ canDisable : bool
+ If true, then the element can be disabled
+ propertyGate : str
+ Name of a global property. When this property is `true`,
+ then this element is _disabled_. Note that this _must_ be
+ the name of a property - it cannot be a BeanShell
+ expression.
+ disabledIcon : str
+ Path to image to use when the element is disabled.
+ kwargs : dict
+ Other attributes to set on the element
+ '''
+ if name == '' and tooltip != '': name = tooltip
+ if name != '' and tooltip == '': tooltip = name
+
+ # Build arguments for super class
+ args = {
+ 'node': node,
+ 'name': name,
+ 'icon': icon,
+ 'tooltip': tooltip,
+ 'hotkey': hotkey,
+ 'canDisable': canDisable,
+ 'propertyGate': propertyGate,
+ 'disabledIcon': disabledIcon }
+ bt = kwargs.pop('buttonText',None)
+ # If the element expects buttonText attribute, then do not set
+ # the text attribute - some elements interpret that as a
+ # legacy name attribute,
+ if bt is not None:
+ args['buttonText'] = bt
+ else:
+ args['text'] = text
+ args.update(kwargs)
+
+ super(ToolbarElement,self).__init__(parent,
+ tag,
+ **args)
+ # print('Attributes\n','\n'.join([f'- {k}="{v}"' for k,v in self._node.attributes.items()]))
+
#
# EOF
#
@@ -526,26 +631,28 @@ class DummyElement(Element):
# From globalkey.py
# --------------------------------------------------------------------
-class GlobalKey(Element):
+class GlobalKey(ToolbarElement):
SELECTED = 'MAP|false|MAP|||||0|0||true|Selected|true|EQUALS'
def __init__(self,
parent,
tag,
node = None,
name = '',
+ icon = '',
+ tooltip = '',
buttonHotkey = '',
- hotkey = '',
buttonText = '',
canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ # Local
+ hotkey = '',
deckCount = '-1',
filter = '',
- propertyGate = '',
reportFormat = '',
reportSingle = False,
singleMap = True,
- target = SELECTED,
- tooltip = '',
- icon = ''):
+ target = SELECTED):
'''
Parameters
----------
@@ -569,28 +676,26 @@ class GlobalKey(Element):
Default targets are selected units
'''
- nme = (name if len(name) > 0 else
- tooltip if len(tooltip) > 0 else '')
- tip = (tooltip if len(tooltip) > 0 else
- name if len(name) > 0 else '')
+
super(GlobalKey,self).\
__init__(parent,
tag,
node = node,
- name = nme,
+ name = name,
+ icon = icon,
+ tooltip = tooltip,
buttonHotkey = buttonHotkey, # This hot key
- hotkey = hotkey, # Target hot key
buttonText = buttonText,
canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ hotkey = hotkey, # Target hot key
deckCount = deckCount,
filter = filter,
- propertyGate = propertyGate,
reportFormat = reportFormat,
reportSingle = reportSingle,
singleMap = singleMap,
- target = target,
- tooltip = tip,
- icon = icon)
+ target = target)
#
# EOF
#
@@ -600,7 +705,7 @@ class GlobalKey(Element):
# --------------------------------------------------------------------
class GameElementService:
def getGame(self):
- return self.getParent(Game)
+ return self.getParentOfClass(Game)
# --------------------------------------------------------------------
class GameElement(Element,GameElementService):
@@ -608,23 +713,34 @@ class GameElement(Element,GameElementService):
super(GameElement,self).__init__(game,tag,node=node,**kwargs)
# --------------------------------------------------------------------
-class Notes(GameElement):
+class Notes(ToolbarElement,GameElementService):
TAG = Element.MODULE+'NotesWindow'
def __init__(self,elem,node=None,
- name = 'Notes',
- buttonText = '',
- hotkey = key('N',ALT),
- icon = '/images/notes.gif',
- tooltip = 'Show notes window'):
- super(Notes,self).__init__(elem,self.TAG,node=node,
- name = name,
- buttonText = buttonText,
- hotkey = hotkey,
- icon = icon,
- tooltip = tooltip)
+ name = 'Notes', # Toolbar element name
+ tooltip = 'Show notes window', # Tool tip
+ text = '', # Button text
+ icon = '/images/notes.gif', # Button icon,
+ hotkey = key('N',ALT), # Named key or key stroke
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ description = ''):
+ super(Notes,self).__init__(elem,self.TAG,
+ node = node,
+ name = name,
+ tooltip = tooltip,
+ text = text,
+ icon = icon,
+ hotkey = hotkey,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ description = description)
def encode(self):
return ['NOTES\t\\','PNOTES']
+registerElement(Notes)
+
# --------------------------------------------------------------------
class PredefinedSetup(GameElement):
TAG = Element.MODULE+'PredefinedSetup'
@@ -673,6 +789,7 @@ class PredefinedSetup(GameElement):
+registerElement(PredefinedSetup)
# --------------------------------------------------------------------
class GlobalTranslatableMessages(GameElement):
@@ -690,11 +807,15 @@ class GlobalTranslatableMessages(GameElement):
super(GlobalTranslatableMessages,self).\
__init__(elem,self.TAG,node=node)
+registerElement(GlobalTranslatableMessages)
+
# --------------------------------------------------------------------
class Language(GameElement):
TAG = 'VASSAL.i18n.Language'
def __init__(self,elem,node=None,**kwargs):
super(Languate,self).__init__(sele,self.TAG,node=none,**kwargs)
+
+registerElement(Language)
# --------------------------------------------------------------------
class Chatter(GameElement):
@@ -712,6 +833,8 @@ class Chatter(GameElement):
Attributes
'''
super(Chatter,self).__init__(elem,self.TAG,node=node,**kwargs)
+
+registerElement(Chatter)
# --------------------------------------------------------------------
class KeyNamer(GameElement):
@@ -730,6 +853,8 @@ class KeyNamer(GameElement):
'''
super(KeyNamer,self).__init__(elem,self.TAG,node=node,**kwargs)
+registerElement(KeyNamer)
+
# --------------------------------------------------------------------
# <VASSAL.build.module.GlobalOptions
@@ -883,6 +1008,7 @@ class GlobalOptions(GameElement):
return retd
+registerElement(GlobalOptions)
# --------------------------------------------------------------------
class Option(Element):
@@ -894,6 +1020,8 @@ class Option(Element):
def getGlobalOptions(self):
return self.getParent(GlobalOptions)
+registerElement(Option)
+
# --------------------------------------------------------------------
class Preference(Element):
PREFS = 'VASSAL.preferences.'
@@ -947,6 +1075,9 @@ class IntPreference(Preference):
default = str(default),
desc = desc,
tab = tab)
+
+registerElement(IntPreference)
+
# --------------------------------------------------------------------
class FloatPreference(Preference):
TAG = Preference.PREFS+'DoublePreference'
@@ -964,6 +1095,9 @@ class FloatPreference(Preference):
default = str(default),
desc = desc,
tab = tab)
+
+registerElement(FloatPreference)
+
# --------------------------------------------------------------------
class BoolPreference(Preference):
TAG = Preference.PREFS+'BooleanPreference'
@@ -982,6 +1116,9 @@ class BoolPreference(Preference):
else 'false'),
desc = desc,
tab = tab)
+
+registerElement(BoolPreference)
+
# --------------------------------------------------------------------
class StrPreference(Preference):
TAG = Preference.PREFS+'StringPreference'
@@ -999,6 +1136,9 @@ class StrPreference(Preference):
default = default,
desc = desc,
tab = tab)
+
+registerElement(StrPreference)
+
# --------------------------------------------------------------------
class TextPreference(Preference):
TAG = Preference.PREFS+'TextPreference'
@@ -1017,6 +1157,9 @@ class TextPreference(Preference):
.replace('\n','&#10;')),
desc = desc,
tab = tab)
+
+registerElement(TextPreference)
+
# --------------------------------------------------------------------
class EnumPreference(Preference):
TAG = Preference.PREFS+'EnumPreference'
@@ -1042,39 +1185,42 @@ class EnumPreference(Preference):
tab = tab,
list = sl)
+
+registerElement(EnumPreference)
+
# --------------------------------------------------------------------
# CurrentMap == &quot;Board&quot;
-class Inventory(GameElement):
+class Inventory(ToolbarElement,GameElementService):
TAG = Element.MODULE+'Inventory'
def __init__(self,doc,node=None,
- canDisable = False,
- centerOnPiece = True,
- disabledIcon = '',
- drawPieces = True,
- foldersOnly = False,
- forwardKeystroke = True,
- groupBy = '',
- hotkey = key('I',ALT),
- icon = '/images/inventory.gif',
- include = '{}',
- launchFunction = 'functionHide',
- leafFormat = '$PieceName$',
- name = '',
- nonLeafFormat = '$PropertyValue$',
- pieceZoom = '0.33',
- pieceZoom2 = '0.5',
- pieceZoom3 = '0.6',
- propertyGate = '',
- refreshHotkey = key('I',ALT_SHIFT),
- showMenu = True,
- sides = '',
- sortFormat = '$PieceName$',
- sortPieces = True,
- sorting = 'alpha',
- text = '',
- tooltip = 'Show inventory of all pieces',
- zoomOn = False):
+ name = '',
+ icon = '/images/inventory.gif',
+ text = '',
+ tooltip = 'Show inventory of all pieces',
+ hotkey = key('I',ALT),
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ centerOnPiece = True,
+ drawPieces = True,
+ foldersOnly = False,
+ forwardKeystroke = True,
+ groupBy = '',
+ include = '{}',
+ launchFunction = 'functionHide',
+ leafFormat = '$PieceName$',
+ nonLeafFormat = '$PropertyValue$',
+ pieceZoom = '0.33',
+ pieceZoom2 = '0.5',
+ pieceZoom3 = '0.6',
+ refreshHotkey = key('I',ALT_SHIFT),
+ showMenu = True,
+ sides = '',
+ sortFormat = '$PieceName$',
+ sortPieces = True,
+ sorting = 'alpha',
+ zoomOn = False):
super(Inventory,self).__init__(doc,self.TAG,node=node,
canDisable = canDisable,
centerOnPiece = centerOnPiece,
@@ -1104,16 +1250,7 @@ class Inventory(GameElement):
tooltip = tooltip,
zoomOn = zoomOn)
-
-
-
-
-
-
-
-
-
-
+registerElement(Inventory)
# --------------------------------------------------------------------
class Prototypes(GameElement):
@@ -1149,17 +1286,21 @@ class Prototypes(GameElement):
'''
return self.getElementsByKey(Prototype,'name',asdict=asdict)
-
-
+registerElement(Prototypes)
# --------------------------------------------------------------------
-class DiceButton(GameElement):
+class DiceButton(ToolbarElement,GameElementService):
TAG=Element.MODULE+'DiceButton'
def __init__(self,elem,node=None,
- addToTotal = 0,
- canDisable = False,
- hotkey = key('6',ALT),
+ name = '1d6',
+ tooltip = 'Roll a 1d6',
+ text = '1d6',
icon = '/images/die.gif',
+ hotkey = key('6',ALT),
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ addToTotal = 0,
keepCount = 1,
keepDice = False,
keepOption = '>',
@@ -1169,19 +1310,16 @@ class DiceButton(GameElement):
lockSides = False,
nDice = 1,
nSides = 6,
- name = '1d6',
plus = 0,
prompt = False,
- propertyGate = '',
- reportFormat = '** $name$ = $result$ *** <$PlayerName$>;',
+ reportFormat = '$name$ = $result$',
reportTotal = False,
- sortDice = False,
- text = '1d6',
- tooltip = 'Roll a 1d6'):
+ sortDice = False):
super(DiceButton,self).\
__init__(elem,self.TAG,node=node,
addToTotal = addToTotal,
canDisable = canDisable,
+ disabledIcon = disabledIcon,
hotkey = hotkey,
icon = icon,
keepCount = keepCount,
@@ -1203,24 +1341,27 @@ class DiceButton(GameElement):
text = text,
tooltip = tooltip)
+registerElement(DiceButton)
+
# --------------------------------------------------------------------
class GameMassKey(GlobalKey,GameElementService):
TAG = Element.MODULE+'GlobalKeyCommand'
def __init__(self,map,node=None,
name = '',
- buttonHotkey = '',
- hotkey = '',
buttonText = '',
+ tooltip = '',
+ icon = '',
canDisable = False,
+ propertyGate = '',
+ disabledIcon = '',
+ buttonHotkey = '',
+ hotkey = '',
deckCount = '-1',
filter = '',
- propertyGate = '',
reportFormat = '',
reportSingle = False,
singleMap = True,
- target = GlobalKey.SELECTED,
- tooltip = '',
- icon = ''):
+ target = GlobalKey.SELECTED):
'''Default targets are selected units'''
super(GameMassKey,self).\
__init__(map,
@@ -1241,6 +1382,8 @@ class GameMassKey(GlobalKey,GameElementService):
tooltip = tooltip,
icon = icon)
+registerElement(GameMassKey)
+
# --------------------------------------------------------------------
class StartupMassKey(GlobalKey,GameElementService):
TAG = Element.MODULE+'StartupGlobalKeyCommand'
@@ -1287,21 +1430,24 @@ class StartupMassKey(GlobalKey,GameElementService):
if node is None:
self['whenToApply'] = whenToApply
+registerElement(StartupMassKey)
+
# --------------------------------------------------------------------
class Menu(GameElement):
TAG = Element.MODULE+'ToolbarMenu'
def __init__(self,
game,
node = None,
+ name = '',
+ tooltip = '',
+ text = '', # Menu name
canDisable = False,
- description = '',
+ propertyGate = '',
disabledIcon = '',
+ description = '',
hotkey = '',
icon = '',
- menuItems = [],# Button texts
- propertyGate = '',
- text = '',# Menu name
- tooltip = ''):
+ menuItems = []):
if len(description) <= 0 and len(tooltip) > 0:
description = tooltip
if len(tooltip) <= 0 and len(description) > 0:
@@ -1310,6 +1456,7 @@ class Menu(GameElement):
__init__(game,
self.TAG,
node = node,
+ name = name,
canDisable = canDisable,
description = description,
disabledIcon = disabledIcon,
@@ -1320,6 +1467,8 @@ class Menu(GameElement):
text = text,
tooltip = tooltip)
+registerElement(Menu)
+
# --------------------------------------------------------------------
class SymbolicDice(GameElement):
@@ -1370,6 +1519,8 @@ class SymbolicDice(GameElement):
def getSymbolicDice(self):
return self.getParent(SymbolicDice)
+registerElement(SymbolicDice)
+
# --------------------------------------------------------------------
class SpecialDie(GameElement):
@@ -1399,8 +1550,7 @@ class SpecialDie(GameElement):
def getSymbolicDice(self):
return self.getParent(SymbolicDice)
-
-
+registerElement(SpecialDie)
# --------------------------------------------------------------------
class DieFace(GameElement):
@@ -1421,6 +1571,9 @@ class DieFace(GameElement):
def getSpecialDie(self):
return self.getParent(SpecialDie)
+
+registerElement(DieFace)
+
#
# EOF
#
@@ -1451,6 +1604,223 @@ class MapElement(Element,MapElementService):
# --------------------------------------------------------------------
+class PieceLayers(MapElement):
+ TAG=Element.MAP+'LayeredPieceCollection'
+ def __init__(self,map,node=None,
+ property = 'PieceLayer',
+ description = '',
+ layerOrder = []):
+ super(PieceLayers,self).__init__(map,self.TAG,node=node,
+ property = property,
+ description = description,
+ layerOrder = ','.join(layerOrder))
+
+ def addControl(self,**kwargs):
+ '''Add `LayerControl` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : LayerControl
+ The added element
+ '''
+ return self.add(LayerControl,**kwargs)
+ def getControls(self,asdict=True):
+ '''Get all `LayerControl` element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps name to
+ `LayerControl` elements. If `False`, return a list of all
+ `LayerControl` children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `LayerControl` children
+
+ '''
+ return self.getElementsByKey(LayerControl,'name',asdict)
+
+registerElement(PieceLayers)
+
+# --------------------------------------------------------------------
+class LayerControl(MapElement):
+ TAG=Element.MAP+'LayerControl'
+ CYCLE_UP='Rotate Layer Order Up'
+ CYCLE_DOWN='Rotate Layer Order Down'
+ ENABLE='Make Layer Active'
+ DISABLE='Make Layer Inactive'
+ TOGGLE='Switch Layer between Active and Inactive'
+ RESET='Reset All Layers'
+ def __init__(self,col,node=None,
+ name = '',
+ tooltip = '',
+ text = '',
+ hotkey = '',
+ icon = '',
+ canDisable = False,
+ propertyGate = '', #Property name, disable when property false
+ disabledIcon = '',
+ command = TOGGLE,
+ skip = False,
+ layers = [],
+ description = ''):
+ super(LayerControl,self).__init__(col,self.TAG,node=node,
+ name = name,
+ tooltip = tooltip,
+ text = text,
+ buttonText = text,
+ hotkey = hotkey,
+ icon = icon,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon,
+ command = command,
+ skip = skip,
+ layers = ','.join(layers),
+ description = description)
+
+ def getLayers(self):
+ '''Get map - either a Map or WidgetMap'''
+ return self.getParentOfClass([PieceLayers])
+
+registerElement(LayerControl)
+
+
+# --------------------------------------------------------------------
+class LineOfSight(MapElement):
+ TAG=Element.MAP+'LOS_Thread'
+ ROUND_UP = 'Up'
+ ROUND_DOWN = 'Down'
+ ROUND_NEAREST = 'Nearest whole number'
+ FROM_LOCATION = 'FromLocation'
+ TO_LOCATION = 'ToLocation'
+ CHECK_COUNT = 'NumberOfLocationsChecked'
+ CHECK_LIST = 'AllLocationsChecked'
+ RANGE = 'Range'
+ NEVER = 'Never'
+ ALWAYS = 'Always'
+ WHEN_PERSISTENT = 'When persistent'
+ CTRL_CLICK = 'Cltr-Click & Drag'
+
+ def __init__(self,map,
+ node=None,
+ threadName = 'LOS',
+ hotkey = key('L',ALT),
+ tooltip = 'Trace line of sight',
+ iconName = '/images/thread.gif', #'los-icon.png',
+ label = '',
+ snapLOS = False,
+ snapStart = True,
+ snapEnd = True,
+ report = (f'{{"Range from "+{FROM_LOCATION}'
+ f'+" to "+{TO_LOCATION}+" is "'
+ f'+{RANGE}+" (via "+{CHECK_LIST}+")"}}'),
+ persistent = CTRL_CLICK,
+ persistentIconName = '/images/thread.gif',
+ globl = ALWAYS,
+ losThickness = 3,
+ threadColor = rgb(255,0,0),
+ drawRange = True,
+ # rangeBg = rgb(255,255,255),
+ # rangeFg = rgb(0,0,0),
+ rangeScale = 0,
+ hideCounters = True,
+ hideOpacity = 50,
+ round = ROUND_UP,
+ canDisable = False,
+ propertyGate = '',
+ disabledIcon = ''):
+ '''Make Line of Sight interface
+
+ Parameters
+ ----------
+ threadName : str
+ Name of interface
+ hotkey : str
+ Start LOS key
+ tooltip : str
+ Tool tip text
+ iconName : str
+ Path to button icon
+ label : str
+ Button text
+ snapLOS : bool
+ Wether to snap both ends
+ snapStart : bool
+ Snap to start
+ snapEnd: bool
+ Snap to end
+ report : str
+ Report format
+ persistent : str
+ When persistent
+ persistentIconName : str
+ Icon when persistent(?)
+ globl : str
+ Visisble to opponents
+ losThickness : int
+ Thickness in pixels
+ losColor : str
+ Colour of line
+ drawRange : bool
+ Draw the range next to LOST thread
+ rangeBg : str
+ Range backgroung colour
+ rangeFg : str
+ Range foregrond colour
+ rangeScale : int
+ Scale of range - pixels per unit
+ round : str
+ How to round range
+ hideCounters :bool
+ If true, hide counters while making thread
+ hideOpacity : int
+ Opacity of hidden counters (percent)
+ canDisable : bool
+ IF true, then can be hidden
+ propertyGate : str
+ Name of property. When that property is TRUE, then the
+ interface is disabled. Must be a property name, not an expression.
+ disabledIcon : str
+ Icon to use when disabled
+ '''
+ super(LineOfSight,self).__init__(map,self.TAG,
+ node = node,
+ threadName = threadName,
+ hotkey = hotkey,
+ tooltip = tooltip,
+ iconName = iconName,
+ label = label,
+ snapLOS = snapLOS,
+ snapStart = snapStart,
+ snapEnd = snapEnd,
+ report = report,
+ persistent = persistent,
+ persistentIconName = persistentIconName,
+ losThickness = losThickness,
+ threadColor = threadColor,
+ drawRange = drawRange,
+ #rangeBg = rangeBg,
+ #rangeFg = rangeFg,
+ rangeScale = rangeScale,
+ hideCounters = hideCounters,
+ hideOpacity = hideOpacity,
+ round = round,
+ canDisable = canDisable,
+ propertyGate = propertyGate,
+ disabledIcon = disabledIcon)
+ self.setAttribute('global',globl)
+
+
+registerElement(LineOfSight)
+
+# --------------------------------------------------------------------
class StackMetrics(MapElement):
TAG=Element.MAP+'StackMetrics'
def __init__(self,map,node=None,
@@ -1474,6 +1844,8 @@ class StackMetrics(MapElement):
unexSepY = unexSepY,
up = up)
+registerElement(StackMetrics)
+
# --------------------------------------------------------------------
class ImageSaver(MapElement):
TAG=Element.MAP+'ImageSaver'
@@ -1491,6 +1863,9 @@ class ImageSaver(MapElement):
icon = icon,
propertyGate = propertyGate,
tooltip = tooltip)
+
+registerElement(ImageSaver)
+
# --------------------------------------------------------------------
class TextSaver(MapElement):
TAG=Element.MAP+'TextSaver'
@@ -1509,6 +1884,7 @@ class TextSaver(MapElement):
propertyGate = propertyGate,
tooltip = tooltip)
+registerElement(TextSaver)
# --------------------------------------------------------------------
class ForwardToChatter(MapElement):
@@ -1516,30 +1892,40 @@ class ForwardToChatter(MapElement):
def __init__(self,map,node=None,**kwargs):
super(ForwardToChatter,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(ForwardToChatter)
+
# --------------------------------------------------------------------
class MenuDisplayer(MapElement):
TAG=Element.MAP+'MenuDisplayer'
def __init__(self,map,node=None,**kwargs):
super(MenuDisplayer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(MenuDisplayer)
+
# --------------------------------------------------------------------
class MapCenterer(MapElement):
TAG=Element.MAP+'MapCenterer'
def __init__(self,map,node=None,**kwargs):
super(MapCenterer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(MapCenterer)
+
# --------------------------------------------------------------------
class StackExpander(MapElement):
TAG=Element.MAP+'StackExpander'
def __init__(self,map,node=None,**kwargs):
super(StackExpander,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(StackExpander)
+
# --------------------------------------------------------------------
class PieceMover(MapElement):
TAG=Element.MAP+'PieceMover'
def __init__(self,map,node=None,**kwargs):
super(PieceMover,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(PieceMover)
+
# --------------------------------------------------------------------
class SelectionHighlighters(MapElement):
TAG=Element.MAP+'SelectionHighlighters'
@@ -1547,12 +1933,16 @@ class SelectionHighlighters(MapElement):
super(SelectionHighlighters,self).\
__init__(map,self.TAG,node=node,**kwargs)
+registerElement(SelectionHighlighters)
+
# --------------------------------------------------------------------
class KeyBufferer(MapElement):
TAG=Element.MAP+'KeyBufferer'
def __init__(self,map,node=None,**kwargs):
super(KeyBufferer,self).__init__(map,self.TAG,node=node,**kwargs)
+registerElement(KeyBufferer)
+
# --------------------------------------------------------------------
class HighlightLastMoved(MapElement):
TAG=Element.MAP+'HighlightLastMoved'
@@ -1565,6 +1955,8 @@ class HighlightLastMoved(MapElement):
enabled = enabled,
thickness = thickness)
+registerElement(HighlightLastMoved)
+
# --------------------------------------------------------------------
class CounterDetailViewer(MapElement):
TAG=Element.MAP+'CounterDetailViewer'
@@ -1587,7 +1979,7 @@ class CounterDetailViewer(MapElement):
extraTextPadding = 0,
fgColor = rgb(0,0,0),
fontSize = 9,
- graphicsZoom = 1.0,
+ graphicsZoom = 1.0,# Zoom on counters
hotkey = key('\n',0),
layerList = '',
minDisplayPieces = 2,
@@ -1649,6 +2041,8 @@ class CounterDetailViewer(MapElement):
verticalTopText = verticalTopText,
zoomlevel = zoomlevel)
+registerElement(CounterDetailViewer)
+
# --------------------------------------------------------------------
class GlobalMap(MapElement):
TAG=Element.MAP+'GlobalMap'
@@ -1668,6 +2062,8 @@ class GlobalMap(MapElement):
scale = scale,
tooltip = 'Show/Hide overview window')
+registerElement(GlobalMap)
+
# --------------------------------------------------------------------
class Zoomer(MapElement):
TAG = Element.MAP+'Zoomer'
@@ -1687,6 +2083,7 @@ class Zoomer(MapElement):
zoomOutKey = key('-'),
zoomPickKey = key('='),
zoomStart = 3):
+
'''Zoom start is counting from the back (with default zoom levels,
and zoom start, the default zoom is 1'''
lvls = ','.join([str(z) for z in zoomLevels])
@@ -1707,6 +2104,8 @@ class Zoomer(MapElement):
zoomPickKey = zoomPickKey,
zoomStart = zoomStart)
+registerElement(Zoomer)
+
# --------------------------------------------------------------------
class HidePiecesButton(MapElement):
TAG=Element.MAP+'HidePiecesButton'
@@ -1724,6 +2123,8 @@ class HidePiecesButton(MapElement):
showingIcon = showingIcon,
tooltip = tooltip)
+registerElement(HidePiecesButton)
+
# --------------------------------------------------------------------
class MassKey(GlobalKey,MapElementService):
TAG = Element.MAP+'MassKeyCommand'
@@ -1760,6 +2161,7 @@ class MassKey(GlobalKey,MapElementService):
tooltip = tooltip,
icon = icon)
+registerElement(MassKey)
# --------------------------------------------------------------------
class Flare(MapElement):
@@ -1783,10 +2185,13 @@ class Flare(MapElement):
flarePulsesPerSec = flarePulsesPerSec,
reportFormat = '')
+registerElement(Flare)
+
# --------------------------------------------------------------------
class AtStart(MapElement):
TAG = Element.MODULE+'map.SetupStack'
- def __init__(self,map,node=None,
+ def __init__(self,map,
+ node = None,
name = '',
location = '',
useGridLocation = True,
@@ -1861,6 +2266,8 @@ class AtStart(MapElement):
'''
return self.getElementsWithKey(PieceSlot,'entryName',asdict)
+registerElement(AtStart)
+
#
# EOF
#
@@ -1894,6 +2301,7 @@ class GlobalProperties(Element):
def getProperties(self):
return getElementsByKey(GlobalProperty,'name')
+registerElement(GlobalProperties)
# --------------------------------------------------------------------
class GlobalProperty(Element):
@@ -1919,6 +2327,7 @@ class GlobalProperty(Element):
def getGlobalProperties(self):
return self.getParent(GlobalProperties)
+registerElement(GlobalProperty)
#
# EOF
@@ -2099,7 +2508,8 @@ class TurnTrack(TurnLevel):
return []
-
+registerElement(TurnTrack)
+
# --------------------------------------------------------------------
class TurnCounter(TurnLevel):
TAG = Element.MODULE+"turn.CounterTurnLevel"
@@ -2118,6 +2528,8 @@ class TurnCounter(TurnLevel):
loopLimit = loopLimit,
turnFormat = turnFormat)
+registerElement(TurnCounter)
+
# --------------------------------------------------------------------
class TurnList(TurnLevel):
TAG = Element.MODULE+"turn.ListTurnLevel"
@@ -2135,6 +2547,8 @@ class TurnList(TurnLevel):
configList = configList,
turnFormat = turnFormat)
+registerElement(TurnList)
+
# --------------------------------------------------------------------
class TurnGlobalHotkey(Element):
TAG = Element.MODULE+'turn.TurnGlobalHotkey'
@@ -2172,6 +2586,8 @@ class TurnGlobalHotkey(Element):
'''Get the turn track'''
return self.getParent(TurnTrack)
+registerElement(TurnGlobalHotkey)
+
#
# EOF
#
@@ -2316,6 +2732,7 @@ class Documentation(GameElement):
return txt
+registerElement(Documentation)
# --------------------------------------------------------------------
class AboutScreen(Element):
@@ -2343,6 +2760,8 @@ class AboutScreen(Element):
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(AboutScreen)
+
# --------------------------------------------------------------------
class BrowserPDFFile(Element):
TAG = Element.MODULE+'documentation.BrowserPDFFile'
@@ -2368,6 +2787,8 @@ class BrowserPDFFile(Element):
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(BrowserPDFFile)
+
# --------------------------------------------------------------------
class HelpFile(Element):
TAG = Element.MODULE+'documentation.HelpFile'
@@ -2400,6 +2821,8 @@ class HelpFile(Element):
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(HelpFile)
+
# --------------------------------------------------------------------
class BrowserHelpFile(Element):
TAG = Element.MODULE+'documentation.BrowserHelpFile'
@@ -2427,7 +2850,9 @@ class BrowserHelpFile(Element):
def getDocumentation(self):
'''Get Parent element'''
return self.getParent(Documentation)
-
+
+registerElement(BrowserHelpFile)
+
# --------------------------------------------------------------------
class Tutorial(Element):
TAG = Element.MODULE+'documentation.Tutorial'
@@ -2468,6 +2893,8 @@ class Tutorial(Element):
'''Get Parent element'''
return self.getParent(Documentation)
+registerElement(Tutorial)
+
#
# EOF
@@ -2517,6 +2944,8 @@ class PlayerRoster(GameElement):
'''Encode for save'''
return ['PLAYER\ta\ta\t<observer>']
+registerElement(PlayerRoster)
+
# --------------------------------------------------------------------
class PlayerSide(Element):
TAG = 'entry'
@@ -2540,6 +2969,8 @@ class PlayerSide(Element):
'''Get Parent element'''
return self.getParent(PlayerRoster)
+registerElement(PlayerSide)
+
#
# EOF
@@ -2614,7 +3045,9 @@ class ChessClock(Element):
def getControl(self):
'''Get Parent element'''
return self.getParent(ChessClockControl)
-
+
+registerElement(ChessClock)
+
# ====================================================================
class ChessClockControl(GameElement):
TAG=Element.MODULE+'ChessClockControl'
@@ -2727,6 +3160,7 @@ class ChessClockControl(GameElement):
'''Return dictionary of clocs'''
return self.getElementsByKey(ChessClock,'side',asdict)
+registerElement(ChessClockControl)
#
# EOF
@@ -2961,6 +3395,8 @@ class PieceWindow(GameElement,WidgetElement):
tooltip = tooltip,
icon = icon)
+registerElement(PieceWindow)
+
# --------------------------------------------------------------------
class ComboWidget(Element,WidgetElement):
TAG=Element.WIDGET+'BoxWidget'
@@ -2972,6 +3408,8 @@ class ComboWidget(Element,WidgetElement):
width = width,
height = height)
+registerElement(ComboWidget)
+
# --------------------------------------------------------------------
class TabWidget(Element,WidgetElement):
TAG=Element.WIDGET+'TabWidget'
@@ -2981,6 +3419,8 @@ class TabWidget(Element,WidgetElement):
node = node,
entryName = entryName)
+registerElement(TabWidget)
+
# --------------------------------------------------------------------
class ListWidget(Element,WidgetElement):
TAG=Element.WIDGET+'ListWidget'
@@ -2997,6 +3437,8 @@ class ListWidget(Element,WidgetElement):
scale = scale,
divider = divider)
+registerElement(ListWidget)
+
# --------------------------------------------------------------------
class PanelWidget(Element,WidgetElement):
TAG=Element.WIDGET+'PanelWidget'
@@ -3011,6 +3453,8 @@ class PanelWidget(Element,WidgetElement):
nColumns = nColumns,
vert = vert)
+registerElement(PanelWidget)
+
# --------------------------------------------------------------------
class MapWidget(Element):
TAG=Element.WIDGET+'MapWidget'
@@ -3046,6 +3490,8 @@ class MapWidget(Element):
'''
return self.getElementsByKey(WidgetMap,'mapName',asdict=asdict)
+registerElement(MapWidget)
+
#
# EOF
#
@@ -3258,6 +3704,8 @@ class HexGrid(BaseGrid):
width = self.getZone().getWidth()
return floor(width / self.getDeltaY() + .5)
+registerElement(HexGrid)
+
# --------------------------------------------------------------------
class SquareGrid(BaseGrid):
TAG = Element.BOARD+'SquareGrid'
@@ -3307,6 +3755,8 @@ class SquareGrid(BaseGrid):
width = self.getZone().getWidth()
return floor(width / self.getDeltaX() + .5)
+registerElement(SquareGrid)
+
# --------------------------------------------------------------------
class HexNumbering(BaseNumbering):
TAG = Element.BOARD+'mapgrid.HexGridNumbering'
@@ -3368,6 +3818,8 @@ class HexNumbering(BaseNumbering):
return x,y
+registerElement(HexNumbering)
+
# --------------------------------------------------------------------
class SquareNumbering(BaseNumbering):
TAG = Element.BOARD+'mapgrid.SquareGridNumbering'
@@ -3395,6 +3847,7 @@ class SquareNumbering(BaseNumbering):
return x,y
+registerElement(SquareNumbering)
# --------------------------------------------------------------------
class RegionGrid(Element):
@@ -3452,6 +3905,8 @@ class RegionGrid(Element):
return None
+registerElement(RegionGrid)
+
# --------------------------------------------------------------------
class Region(Element):
TAG = Element.BOARD+'Region'
@@ -3527,6 +3982,8 @@ class Region(Element):
return b.getMap()
return None
+registerElement(Region)
+
#
# EOF
#
@@ -3579,7 +4036,7 @@ class ZonedGrid(Element):
children : list
List of `Highligter` children (even if `single=True`)
'''
- return self.getAllElements(ZonedGridHighliger,single=single)
+ return self.getAllElements(ZonedGridHighlighter,single=single)
def addZone(self,**kwargs):
'''Add a `Zone` element to this
@@ -3607,6 +4064,8 @@ class ZonedGrid(Element):
'''
return self.getElementsByKey(Zone,'name',asdict=asdict)
+registerElement(ZonedGrid)
+
# --------------------------------------------------------------------
class ZonedGridHighlighter(Element):
TAG=Element.BOARD+'mapgrid.ZonedGridHighlighter'
@@ -3614,6 +4073,96 @@ class ZonedGridHighlighter(Element):
super(ZonedGridHighlighter,self).__init__(zoned,self.TAG,node=node)
def getZonedGrid(self): return self.getParent(ZonedGrid)
+ def addZoneHighlight(self,**kwargs):
+ '''Add a `ZoneHighlight` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : ZoneHighlight
+ The added element
+ '''
+ return self.add(ZoneHighlight,**kwargs)
+ def getZoneHighlights(self,asdict=True):
+ '''Get all ZoneHighlight element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children.
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Zone` children
+ '''
+ return self.getElementsByKey(ZoneHighlight,'name',asdict=asdict)
+
+registerElement(ZonedGridHighlighter)
+
+# --------------------------------------------------------------------
+class ZoneHighlight(Element):
+ TAG=Element.BOARD+'mapgrid.ZoneHighlight'
+ FULL='Entire Zone',
+ BORDER='Zone Border',
+ PLAIN='Plain',
+ STRIPED='Striped'
+ CROSS='Crosshatched',
+ TILES='Tiled Image'
+ def __init__(self,
+ highlighters,
+ node = None,
+ name = '',
+ color = rgb(255,0,0),
+ coverage = FULL,
+ width = 1,
+ style = PLAIN,
+ image = '',
+ opacity = 50):
+ super(ZoneHighlight,self).__init__(highlighters,
+ self.TAG,
+ node = node,
+ name = name,
+ color = color,
+ coverage = coverage,
+ width = width,
+ style = style,
+ image = image,
+ opacity = int(opacity))
+ def getZonedGridHighlighter(self):
+ return self.getParent(ZonedGridHighlighter)
+
+
+registerElement(ZoneHighlight)
+
+
+# --------------------------------------------------------------------
+class ZoneProperty(Element):
+ TAG = Element.MODULE+'properties.ZoneProperty'
+ def __init__(self,zone,node=None,
+ name = '',
+ initialValue = '',
+ isNumeric = False,
+ min = "null",
+ max = "null",
+ wrap = False,
+ description = ""):
+ super(ZoneProperty,self).__init__(zone,self.TAG,
+ node = node,
+ name = name,
+ initialValue = initialValue,
+ isNumeric = isNumeric,
+ min = min,
+ max = max,
+ wrap = wrap,
+ description = description)
+
+ def getZone(self):
+ return self.getParent(Zone)
+
+registerElement(ZoneProperty)
# --------------------------------------------------------------------
class Zone(Element):
@@ -3693,6 +4242,19 @@ class Zone(Element):
The added element
'''
return self.add(RegionGrid,**kwargs)
+ def addProperty(self,**kwargs):
+ '''Add a `Property` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Property
+ The added element
+ '''
+ return self.add(ZoneProperty,**kwargs)
def getHexGrids(self,single=True):
'''Get all or a sole `HexGrid` element(s) from this
@@ -3758,6 +4320,17 @@ class Zone(Element):
if g is not None: return g
return g
+ def getProperties(self):
+ '''Get all `Property` element from this
+
+ Parameters
+ ----------
+ Returns
+ -------
+ children : dict
+ dict of `Property` children
+ '''
+ return getElementsByKey(ZoneProperty,'name')
def getPath(self):
p = self['path'].split(';')
@@ -3785,6 +4358,8 @@ class Zone(Element):
def getYOffset(self):
return self.getBB()[1]
+registerElement(Zone)
+
#
# EOF
#
@@ -3879,6 +4454,8 @@ class BoardPicker(MapElement):
return ret
+registerElement(BoardPicker)
+
# --------------------------------------------------------------------
class Setup(Element):
TAG = 'setup'
@@ -3901,7 +4478,9 @@ class Setup(Element):
self.addText(txt)
def getPicker(self): return self.getParent(BoardPicker)
-
+
+registerElement(Setup)
+
# --------------------------------------------------------------------
class Board(Element):
TAG = Element.PICKER+'Board'
@@ -3982,6 +4561,7 @@ class Board(Element):
return int(self['height'])
return 0
+registerElement(Board)
#
# EOF
@@ -4340,6 +4920,57 @@ class BaseMap(Element):
picker = self.getPicker()
if picker is None: return None
return picker[0].getBoards(asdict=asdict)
+ def getLayers(self,asdict=True):
+ '''Get all `PieceLayer` element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps property name
+ `PieceLayers` elements. If `False`, return a list of all
+ `PieceLayers` children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `PieceLayers` children
+
+ '''
+ return self.getElementsByKey(PieceLayers,'property',asdict)
+ def getMenus(self,asdict=True):
+ '''Get all Menu element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Board`
+ elements. If `False`, return a list of all Board`
+ children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Board` children
+
+ '''
+ return self.getElementsByKey(Menu,'name',asdict)
+ def getLOSs(self,asdict=True):
+ '''Get all Menu element(s) from this
+
+ Parameters
+ ----------
+ asdict : bool
+ If `True`, return a dictonary that maps key to `Board`
+ elements. If `False`, return a list of all Board`
+ children.
+
+ Returns
+ -------
+ children : dict or list
+ Dictionary or list of `Board` children
+
+ '''
+ return self.getElementsByKey(LineOfSight,'threadName',asdict)
def addBoardPicker(self,**kwargs):
'''Add a `BoardPicker` element to this
@@ -4600,6 +5231,47 @@ class BaseMap(Element):
The added element
'''
return self.add(AtStart,**kwargs)
+
+
+ def addLayers(self,**kwargs):
+ '''Add `PieceLayers` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : PieceLayers
+ The added element
+ '''
+ return self.add(PieceLayers,**kwargs)
+ def addMenu(self,**kwargs):
+ '''Add a `Menu` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Menu
+ The added element
+ '''
+ return self.add(Menu,**kwargs)
+ def addLOS(self,**kwargs):
+ '''Add a `Menu` element to this
+
+ Parameters
+ ----------
+ kwargs : dict
+ Dictionary of attribute key-value pairs
+ Returns
+ -------
+ element : Menu
+ The added element
+ '''
+ return self.add(LineOfSight,**kwargs)
# --------------------------------------------------------------------
class Map(BaseMap):
@@ -4657,7 +5329,9 @@ class Map(BaseMap):
def getGame(self):
return self.getParent(Game)
-
+
+registerElement(Map)
+
# --------------------------------------------------------------------
class WidgetMap(BaseMap):
TAG = Element.WIDGET+'WidgetMap'
@@ -4669,6 +5343,8 @@ class WidgetMap(BaseMap):
def getMapWidget(self):
return self.getParent(MapWidget)
+registerElement(WidgetMap)
+
#
# EOF
@@ -4721,7 +5397,7 @@ class ChartWindow(GameElement,WidgetElement):
'''
return self.getElementsById(Chart,'chartName',asdict=asdict)
-
+registerElement(ChartWindow)
# --------------------------------------------------------------------
class Chart(Element):
@@ -4735,6 +5411,8 @@ class Chart(Element):
description = description,
fileName = fileName)
+registerElement(Chart)
+
#
# EOF
#
@@ -4766,7 +5444,7 @@ class Trait:
this actually holds state that isn't reflected elsewhere in
the DOM. This means that the data here is local to the
object. So when we do
-
+
piece = foo.getPieceSlots()[0]
traits = p.getTraits()
for trait in traits:
@@ -5040,6 +5718,15 @@ class WithTraits(Element):
Identifier
'''
+ last = traits[-1]
+ # A little hackish to use the name of the class, but needed
+ # because of imports into patch scripts.
+ if not isinstance(last,BasicTrait) and \
+ not last.__class__.__name__.endswith('BasicTrait'):
+ from sys import stderr
+ print(f'Warning - last trait NOT a BasicTrait, but a {type(last)}',
+ file=stderr)
+
types = []
states = []
for trait in traits:
@@ -5165,7 +5852,9 @@ class DummyWithTraits(WithTraits):
if parent is not None:
parent.remove(self)
-
+
+registerElement(DummyWithTraits)
+
# --------------------------------------------------------------------
class PieceSlot(WithTraits):
TAG = Element.WIDGET+'PieceSlot'
@@ -5226,6 +5915,7 @@ class PieceSlot(WithTraits):
piece.setTraits(*traits)
return piece
+registerElement(PieceSlot)
# --------------------------------------------------------------------
class Prototype(WithTraits):
@@ -5255,6 +5945,8 @@ class Prototype(WithTraits):
name = name,
description = description)
+registerElement(Prototype)
+
#
# EOF
#
@@ -5262,16 +5954,21 @@ class Prototype(WithTraits):
# From traits/dynamicproperty.py
# --------------------------------------------------------------------
-# Base class for property (piece or global) change traits. Encodes
-# constraints and commands.
+#
+#
class ChangePropertyTrait(Trait):
DIRECT = 'P'
+ INCREMENT = 'I'
def __init__(self,
*commands,
numeric = False,
min = 0,
max = 100,
wrap = False):
+ '''Base class for property (piece or global) change traits.
+
+ Encodes constraints and commands.
+ '''
# assert name is not None and len(name) > 0, \
# 'No name specified for ChangePropertyTriat'
super(ChangePropertyTrait,self).__init__()
@@ -5293,8 +5990,11 @@ class ChangePropertyTrait(Trait):
# print(cmd)
com = cmd[0] + ':' + cmd[1].replace(',',r'\,') + ':' + cmd[2]
if cmd[2] == self.DIRECT:
- com += f'\,'+cmd[3].replace(':',r'\:')
+ com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
+ elif cmd[2] == self.INCREMENT:
+ com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:')
cmds.append(com)
+ # print(cmds)
return ','.join(cmds)
def decodeCommands(self,commands):
@@ -5305,6 +6005,8 @@ class ChangePropertyTrait(Trait):
# print('parts',parts)
if parts[-1][0] == self.DIRECT:
parts = parts[:-1]+Trait.decodeKeys(parts[-1],',')
+ if parts[-1][0] == self.INCREMENT:
+ parts = parts[:-1]+Trait.decodeKeys(parts[-1],',')
ret.append(parts)
# print(commands,parts)
return ret
@@ -5840,7 +6542,7 @@ class NoStackTrait(Trait):
canStack = False,
ignoreGrid = False,
description = ''):
-
+ '''No stacking trait'''
selectionOptions = (select +
(self.IGNORE_GRID if ignoreGrid else '') +
bandSelect)
@@ -7319,6 +8021,7 @@ class Game(Element):
'''
return self.getAllElements(AtStart,single)
+registerElement(Game)
# --------------------------------------------------------------------
class BasicCommandEncoder(GameElement):
@@ -7326,6 +8029,8 @@ class BasicCommandEncoder(GameElement):
def __init__(self,doc,node=None):
super(BasicCommandEncoder,self).__init__(doc,self.TAG,node=node)
+registerElement(BasicCommandEncoder)
+
#
# EOF
#
@@ -8446,7 +9151,8 @@ class LaTeXExporter(Exporter):
vassalVersion = '3.6.7',
nonato = False,
nochit = False,
- counterScale = 1):
+ counterScale = 1,
+ resolution = 150):
'''Exports a PDF and associated JSON files to a VASSAL module.
Parameters
@@ -8473,6 +9179,8 @@ class LaTeXExporter(Exporter):
Make grids visible
vassalVersion : str
VASSAL version to encode this module for
+ resolution : int
+ Resolution for images (default 150)
'''
self._vmodname = vmodname
self._pdfname = pdfname
@@ -8487,6 +9195,7 @@ class LaTeXExporter(Exporter):
self._vassalVersion = vassalVersion
self._nonato = nonato
self._nochit = nochit
+ self._resolution = resolution
self._counterScale = counterScale
self._battleMark = 'wgBattleMarker'
self._battleMarks = []
@@ -8572,6 +9281,7 @@ class LaTeXExporter(Exporter):
v(f'Tutorial log: {self._tutorial}')
v(f'Patch scripts: {self._patch}')
v(f'Visible grids: {self._visible}')
+ v(f'Resolution: {self._resolution}')
v(f'Scale of counters: {self._counterScale}')
def setup(self):
@@ -8704,6 +9414,7 @@ class LaTeXExporter(Exporter):
args = ['pdftocairo',
'-transp',
'-singlefile',
+ '-r', str(self._resolution),
'-f', str(page),
'-l', str(page),
'-png' ]
@@ -8772,9 +9483,9 @@ class LaTeXExporter(Exporter):
imgsinfo = self.getImagesInfo()
if len(imgsinfo) - 1 != docinfo['Pages']:
- raise RuntimeError(f'Number of pages in {pdfname} '
- f'(doc["Pages"]) not matched in JSON '
- f'{self._infoname} -> {len(imagesinfo)}')
+ raise RuntimeError(f'Number of pages in {self._pdfname} '
+ f'{docinfo["Pages"]} not matched in JSON '
+ f'{self._infoname} -> {len(imgsinfo)}')
with VerboseGuard(f'Converting {docinfo["Pages"]} '
f'pages in {self._pdfname}') as v:
@@ -9126,10 +9837,16 @@ class LaTeXExporter(Exporter):
'property': 'Phase',
'names': self._sides } })
turns.addHotkey(hotkey = self._clearMoved+'Phase',
- name = 'Clear moved markers')
+ name = 'Clear moved markers',
+ reportFormat = (f'{{{self._verbose}?('
+ f'"`Clear all moved markers, "+'
+ f'""):""}}'))
if len(self._battleMarks) > 0:
turns.addHotkey(hotkey = self._clearBattlePhs,
- name = 'Clear battle markers')
+ name = 'Clear battle markers',
+ reportFormat = (f'{{{self._verbose}?('
+ f'"`Clear all battle markers, "+'
+ f'""):""}}'))
self._dice = self._categories\
.get('die-roll',{})
@@ -9153,7 +9870,9 @@ class LaTeXExporter(Exporter):
# f'+" <img src=\'{die}-"+result1'
# f'+".png\' width=24 height=24>"'
f'}}'),
- resultWindow = True);
+ resultWindow = True,
+ windowX = str(int(67 * self._resolution/150)),
+ windowY = str(int(65 * self._resolution/150)));
sdie = symb.addDie(name = die);
for face, fdata in faces.items():
fn = fdata['filename']
@@ -10186,13 +10905,14 @@ class LaTeXExporter(Exporter):
# ----------------------------------------------------------------
def factionTraits(self,faction):
- traits = [ReportTrait(self._eliminateKey,
- self._restoreKey,
- self._trailKey),
+ offX = 36 * self._counterScale * self._resolution/150
+ offY = -38 * self._counterScale * self._resolution/150
+ traits = [#ReportTrait(self._eliminateKey,
+ # self._restoreKey,
+ # self._trailKey),
TrailTrait(),
RotateTrait(),
- MovedTrait(xoff = int( 36 * self._counterScale),
- yoff = int(-38 * self._counterScale)),
+ MovedTrait(xoff = int(offX),yoff = int(offY)),
DeleteTrait(),
SendtoTrait(mapName = 'DeadMap',
boardName = f'{faction} pool',
@@ -11308,7 +12028,10 @@ class LaTeXExporter(Exporter):
pc = p["coords"]
if j == 0: vv(f'',end='')
vv(f'[{pn}] ',end='',flush=True,noindent=True)
-
+
+ if pn.endswith(' flipped'):
+ pn = pn[:-len(' flipped')]
+
x, y = tran(*pc)
r = grid.addRegion(name = pn,
originx = x,
@@ -11499,7 +12222,7 @@ class LaTeXExporter(Exporter):
def addDie(self):
'''Add a `Die` element to the module
'''
- if self._dice is not None:
+ if self._dice is not None and len(self._dice) > 0:
return
self._game.addDiceButton(name = '1d6',
hotkey = self._diceKey)
@@ -11568,6 +12291,9 @@ if __name__ == '__main__':
ap.add_argument('-S','--counter-scale',
type=float, default=1,
help='Scale counters by factor')
+ ap.add_argument('-R','--resolution',
+ type=int, default=150,
+ help='Resolution of images')
args = ap.parse_args()
@@ -11600,6 +12326,7 @@ if __name__ == '__main__':
vassalVersion = args.vassal_version,
nonato = args.no_nato_prototypes,
nochit = args.no_chit_information,
+ resolution = args.resolution,
counterScale = args.counter_scale)
exporter.run()
except Exception as e: