\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 % \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}{}]% }