85 lines
2.7 KiB
TeX
Executable File
85 lines
2.7 KiB
TeX
Executable File
\NeedsTeXFormat{LaTeX2e}
|
|
\ProvidesPackage{problemlib}[2023/05/17 ORMC Problem Library]
|
|
|
|
|
|
% Defines a new problem.
|
|
% See problem definition files for usage examples.
|
|
\long\def\problemdef#1#2#3{
|
|
\ifcsname#1:problem:#2\endcsname
|
|
\PackageError{problemlib}{Problem #1:#2 is already defined}{}
|
|
\fi
|
|
|
|
% Use a group to limit scope of special commands.
|
|
\begingroup
|
|
|
|
% \gdef = \global\def
|
|
% This makes problem definitions global, and not restricted to this group.
|
|
%
|
|
% ##1: used to define parametrized macros in a parametrized macro.
|
|
% When \problemdef is expanded, ##1 becomes #1.
|
|
%
|
|
% \long\def: like \def, but allows multi-paragraph arguments
|
|
% \def\name#1{def: #1}: define a macro \name with one arg. TeX primitive.
|
|
%
|
|
% We don't use \newcommand or \renewcommand here because they will fail if
|
|
% a macro is defined/not defined. \def will always work, defining a new name
|
|
% in this group, temporarily redefining existing commands.
|
|
%
|
|
% \expandafter <macro> <tokens>
|
|
% \expandafter command delays expanding a macro until its arguments have been expanded.
|
|
\long\def\difficulty##1{\expandafter\gdef\csname#1:difficulty:#2\endcsname{##1}}
|
|
\long\def\statement##1{\expandafter\gdef\csname#1:problem:#2\endcsname{##1}}
|
|
\long\def\solution##1{\expandafter\gdef\csname#1:solution:#2\endcsname{##1}}
|
|
\long\def\answer##1{\expandafter\gdef\csname#1:answer:#2\endcsname{##1}}
|
|
|
|
#3
|
|
|
|
\endgroup
|
|
|
|
% Optional hook to run after each problem definition.
|
|
% Must be defined BEFORE problems are included.
|
|
\ifdefined\postproblem
|
|
\postproblem{#1}{#2}
|
|
\fi
|
|
}
|
|
|
|
% Gets problem data.
|
|
% Arguments:
|
|
% #1: Category
|
|
% #2: Problem id
|
|
% #3: Field to get
|
|
\NewDocumentCommand{\get}{ m m m }{%
|
|
\ifcsname#1:#3:#2\endcsname%
|
|
\csname#1:#3:#2\endcsname%
|
|
\else%
|
|
\PackageError{problemlib}{Problem #1:#2 is not defined}{}
|
|
\fi%
|
|
}
|
|
\NewDocumentCommand{\getdifficulty}{ m m }{\get{#1}{#2}{difficulty}}
|
|
\NewDocumentCommand{\getproblem}{ m m }{\get{#1}{#2}{problem}}
|
|
|
|
|
|
% #1: Category
|
|
% #2: Problem id
|
|
% #3: attribute to check
|
|
% #4: Show if true
|
|
% #5: Show if false
|
|
\NewDocumentCommand{\ifattribute}{ m m m m d[] }{%
|
|
\ifcsname#1:#3:#2\endcsname#4%
|
|
\else%
|
|
\IfNoValueF{#5}{#5}%
|
|
\fi%
|
|
}
|
|
\NewDocumentCommand{\ifanswer}{ m m m d[] }{\ifattribute{#1}{#2}{answer}{#3}[#4]}
|
|
\NewDocumentCommand{\ifsolution}{ m m m d[] }{\ifattribute{#1}{#2}{solution}{#3}[#4]}
|
|
\NewDocumentCommand{\ifdifficulty}{ m m m d[] }{\ifattribute{#1}{#2}{difficulty}{#3}[#4]}
|
|
|
|
\NewDocumentCommand{\getanswer}{ m m }{%
|
|
\ifanswer{#1}{#2}{\get{#1}{#2}{answer}}%
|
|
[\PackageError{problemlib}{Problem #1:#2 has no answer}{}]%
|
|
}
|
|
|
|
\NewDocumentCommand{\getsolution}{ m m }{
|
|
\ifsolution{#1}{#2}{\get{#1}{#2}{solution}}%
|
|
[\PackageError{problemlib}{Problem #1:#2 has no solution}{}]%
|
|
} |