summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/exercisepoints/exercisepoints.sty
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/exercisepoints/exercisepoints.sty
Initial commit
Diffstat (limited to 'macros/latex/contrib/exercisepoints/exercisepoints.sty')
-rw-r--r--macros/latex/contrib/exercisepoints/exercisepoints.sty330
1 files changed, 330 insertions, 0 deletions
diff --git a/macros/latex/contrib/exercisepoints/exercisepoints.sty b/macros/latex/contrib/exercisepoints/exercisepoints.sty
new file mode 100644
index 0000000000..42a3754672
--- /dev/null
+++ b/macros/latex/contrib/exercisepoints/exercisepoints.sty
@@ -0,0 +1,330 @@
+% !TEX encoding = UTF-8 Unicode
+%
+%% exercisepoints.sty
+%% A LaTeX package to count exercises and points.
+%%
+%% Copyright (c) 2017-2019 Henning Kerstan.
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Henning Kerstan.
+%
+% This work consists of the files `exercisepoints.sty' and `exercisepoints.tex'.
+%
+
+
+% package identification
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{exercisepoints}[%
+ 2019/01/03 v1.2.3 %
+ count exercises and points%
+]
+
+
+% switches for custom exercise layout
+\newif\if@exercisepoints@usecustomlayout%
+\newif\if@exercisepoints@exercise@layoutdefined%
+\newif\if@exercisepoints@subexercise@layoutdefined%
+
+\DeclareOption{customlayout}{%
+ \@exercisepoints@usecustomlayouttrue%
+}
+
+% this package does not have any other options
+\DeclareOption*{
+ \PackageWarning{exercisepoints}{Unknown option '\CurrentOption'}
+}
+\ProcessOptions\relax%
+
+
+% avoid nesting (i.e. putting exercises in exercises)
+\newif\if@exercisepoints@inexercise%
+\global\@exercisepoints@inexercisefalse%
+\newif\if@exercisepoints@insubexercise%
+\global\@exercisepoints@insubexercisefalse%
+
+
+% counters to store number of exercises
+\newcounter{exercisepoints@exercisecount}
+\newcounter{exercisepoints@subexercisecount}[exercisepoints@exercisecount]
+
+
+% lengths to store points
+\newlength{\exercisepoints@currentexercisepoints}
+\newlength{\exercisepoints@currentsubexercisepoints}
+\newlength{\exercisepoints@totalpoints}
+\newlength{\exercisepoints@bonuspoints}
+
+
+% macros to get total points and total number of exercises (whole document)
+\providecommand{\totalpoints}{0}
+\providecommand{\numberofexercises}{0}
+
+
+% macros to get info about current exercise(-part)
+% (to be used in AtBeginExercise or AtEndExercise hooks)
+\providecommand{\currentexercisetitle}{}
+\providecommand{\currentsubexercisetitle}{}
+
+\providecommand{\currentexercisepoints}{%
+ \if@exercisepoints@inexercise\else%
+ \PackageError{exercisepoints}{'\string\currentexercisepoints' can only be used in exercise or subexercise environment}%
+ \fi%
+ %
+ \ifcsname exercisepoints@points@\currentexercisenumber\endcsname%
+ \@nameuse{exercisepoints@points@\currentexercisenumber}%
+ \else%
+ \textbf{??}% TODO:issue package warning in such a way that it can be used also in section commands
+ \fi%
+}
+
+\providecommand{\currentsubexercisepoints}{%
+ \if@exercisepoints@insubexercise\else%
+ \PackageError{exercisepoints}{'\string\currentsubexercisepoints' can only be used in subexercise environment}%
+ \fi%
+ %
+ \ifcsname exercisepoints@points@\currentexercisenumber.\currentsubexercisenumber\endcsname%
+ \@nameuse{exercisepoints@points@\currentexercisenumber.\currentsubexercisenumber}%
+ \else%
+ \textbf{??}% TODO:issue package warning in such a way that it can be used also in section commands
+ \fi%
+}
+
+\providecommand{\currentexercisenumber}{%
+ \theexercisepoints@exercisecount%
+}
+
+\providecommand{\currentsubexercisenumber}{%
+ \theexercisepoints@subexercisecount%
+}
+
+
+% hooks to modify the exercise typesetting
+\providecommand{\AtBeginExercise}[1]{
+ \renewcommand{\exercisepoints@begin}{#1}%
+ \@exercisepoints@exercise@layoutdefinedtrue%
+}
+
+\providecommand{\AtEndExercise}[1]{
+ \renewcommand{\exercisepoints@end}{#1}
+}
+
+% the same for subexercises
+\providecommand{\AtBeginSubexercise}[1]{
+ \renewcommand{\exercisepoints@sub@begin}{#1}
+ \@exercisepoints@subexercise@layoutdefinedtrue%
+}
+
+\providecommand{\AtEndSubexercise}[1]{
+ \renewcommand{\exercisepoints@sub@end}{#1}
+}
+
+
+% storage for the hooks
+\newcommand{\exercisepoints@begin}{}
+\newcommand{\exercisepoints@end}{}
+\newcommand{\exercisepoints@sub@begin}{}
+\newcommand{\exercisepoints@sub@end}{}
+
+
+% a very simple default exercise style
+\if@exercisepoints@usecustomlayout\else%
+ \RequirePackage{ifthen}%
+ \AtBeginExercise{%
+ ~\smallskip\\\sffamily%
+ \ifthenelse{\equal{\currentexercisetitle}{}}%
+ {\textbf{Exercise~\currentexercisenumber}} % empty title
+ {%
+ \textbf{Exercise~\currentexercisenumber:} %
+ \currentexercisetitle%
+ }% non-empty title
+ \,~\hfill\textbf{(\currentexercisepoints~Points)}%
+ \smallskip\\\noindent\normalfont%
+ }
+ \AtEndExercise{~\smallskip\\}
+ %
+ \AtBeginSubexercise{%
+ ~\smallskip\\\sffamily%
+ \ifthenelse{\equal{\currentsubexercisetitle}{}}%
+ {\emph{Exercise~\currentexercisenumber.\currentsubexercisenumber}} % empty title
+ {%
+ \emph{Exercise~\currentexercisenumber.\currentsubexercisenumber:} %
+ \emph{\currentsubexercisetitle}%
+ }% non-empty title
+ \,~\hfill\emph{(\currentsubexercisepoints~Points)}%
+ \smallskip\\\noindent\normalfont%
+ }
+ \AtEndSubexercise{~\\}
+\fi
+
+
+% points commands sets points (additive within an exercise environment)
+\newcommand{\points}[1]{%
+ \if@exercisepoints@inexercise%
+ \addtolength{\exercisepoints@currentexercisepoints}{#1 pt}%
+ \global\exercisepoints@currentexercisepoints=\exercisepoints@currentexercisepoints%
+ \addtolength{\exercisepoints@totalpoints}{#1 pt}%
+ \global\exercisepoints@totalpoints=\exercisepoints@totalpoints%
+ \if@exercisepoints@insubexercise%
+ \addtolength{\exercisepoints@currentsubexercisepoints}{#1 pt}%
+ \global\exercisepoints@currentsubexercisepoints=\exercisepoints@currentsubexercisepoints%
+ \fi%
+ \else%
+ \PackageError{exercisepoints}{\string\points{...} can only be used within exercise or subexercise environment.}%
+ \fi%
+}
+
+% itempoints units
+\newcommand{\exercisepoints@itempointsunit@singular}{}
+\newcommand{\exercisepoints@itempointsunit@plural}{}
+\newcommand{\setitempointsunit}[2]{% singular, plural
+ \renewcommand{\exercisepoints@itempointsunit@singular}{#1}%
+ \renewcommand{\exercisepoints@itempointsunit@plural}{#2}%
+}
+
+% itempoints calls points and displays points flush right for use in
+% enumerate environments
+\RequirePackage{ifthen}
+\newcommand{\itempoints}[1]{%
+ \points{#1}%
+ % check if exactly 1 points
+ \ifthenelse{\equal{#1}{1}}{% not robust, so issuing 1.0 will not result in correct (singular) form!
+ \ifthenelse{\equal{\exercisepoints@itempointsunit@singular}{}}{%
+ \,~\hfill(#1)%
+ }{%
+ \,~\hfill(#1~\exercisepoints@itempointsunit@singular)%
+ }%
+ }{%
+ \ifthenelse{\equal{\exercisepoints@itempointsunit@plural}{}}{%
+ \,~\hfill(#1)%
+ }{%
+ \,~\hfill(#1~\exercisepoints@itempointsunit@plural)%
+ }%
+ }%
+}
+
+
+
+
+% getpoints retrieves points for a specific exercise number (starting at 0)
+\newcommand{\getpoints}[1]{%
+ \ifthenelse{#1 < \numberofexercises}%
+ {\exercisepoints@readfromaux{points@#1}}%
+ {\textbf{??}}%
+}
+
+
+% aux storage function (key-value store using #1 as key and #2 as value)
+\newcommand{\exercisepoints@storetoaux}[2]{%
+ \immediate\write\@auxout{%
+ \string\global\string\long\string\@namedef{exercisepoints@#1}{#2}%
+ }%
+}
+
+
+% aux retrieval
+\newcommand{\exercisepoints@readfromaux}[1]{%
+ \ifcsname exercisepoints@#1\endcsname%
+ \@nameuse{exercisepoints@#1}%
+ \else%
+ \textbf{??}%
+ \PackageWarning{exercisepoints}{%
+ Key 'exercisepoints@#1' not found in aux file. Maybe you need to recompile?%
+ }%
+ \fi%
+}
+
+
+% exercise environment; optional parameter is title of the respective exercise
+\newenvironment{exercise}[1][]{%
+ \if@exercisepoints@inexercise%
+ \PackageError{exercisepoints}{You cannot nest exercise environments}%
+ \fi
+ %
+ \if@exercisepoints@exercise@layoutdefined\else%
+ \PackageError{exercisepoints}{Option `customlayout' requires you to define an exercise layout using at least `\string\AtBeginExercise{...}'}
+ \fi
+ %
+ \global\@exercisepoints@inexercisetrue%
+ \setlength{\exercisepoints@currentexercisepoints}{0pt}%
+ \global\exercisepoints@currentexercisepoints=\exercisepoints@currentexercisepoints%
+ \renewcommand{\currentexercisetitle}{#1}%
+ \exercisepoints@begin%
+}{%
+ \exercisepoints@end%
+ \exercisepoints@storetoaux{points@\theexercisepoints@exercisecount}{\strip@pt\exercisepoints@currentexercisepoints}%
+ \stepcounter{exercisepoints@exercisecount}%
+ \global\@exercisepoints@inexercisefalse%
+}
+
+
+% exercise environment; optional parameter is title of the respective exercise
+\newenvironment{subexercise}[1][]{%
+ \if@exercisepoints@insubexercise%
+ \PackageError{exercisepoints}{You cannot nest subexercise environments}%
+ \fi%
+ %
+ \if@exercisepoints@subexercise@layoutdefined\else%
+ \PackageError{exercisepoints}{Option `customlayout' requires you to define a subexercise layout using at least `\string\AtBeginSubexercise{...}'}
+ \fi%
+ \global\@exercisepoints@insubexercisetrue%
+ \setlength{\exercisepoints@currentsubexercisepoints}{0pt}%
+ \global\exercisepoints@currentsubexercisepoints=\exercisepoints@currentsubexercisepoints%
+ \renewcommand{\currentsubexercisetitle}{#1}%
+ \exercisepoints@sub@begin%
+}{%
+ \exercisepoints@sub@end%
+ \exercisepoints@storetoaux{points@\theexercisepoints@exercisecount.\theexercisepoints@subexercisecount}{\strip@pt\exercisepoints@currentsubexercisepoints}%
+ \stepcounter{exercisepoints@subexercisecount}%
+ \global\@exercisepoints@insubexercisefalse%
+}
+
+
+\newcommand{\bonuspoints}[1]{%
+ \setlength{\exercisepoints@bonuspoints}{#1 pt}%
+ \global\exercisepoints@bonuspoints=\exercisepoints@bonuspoints%
+}
+
+\newcommand{\getbonuspoints}{%
+ \exercisepoints@readfromaux{points@bonus}%
+}
+
+\newcommand{\totalpointswithbonus}{%
+ \readfromaux{totalpointswithbonus}%
+}
+
+
+% read values from aux file at begin
+\AtBeginDocument{
+ \setlength{\exercisepoints@totalpoints}{0pt}% reset total points length
+ %
+ % set numberofexercises to 0 if not found in aux
+ \ifcsname exercisepoints@numberofexercises\endcsname%
+ \renewcommand{\numberofexercises}{%
+ \exercisepoints@readfromaux{numberofexercises}%
+ }%
+ \fi%
+ %
+ \renewcommand{\totalpoints}{\exercisepoints@readfromaux{points@total}}%
+ \renewcommand{\totalpointswithbonus}{\exercisepoints@readfromaux{points@totalwithbonus}}%
+}
+
+
+% store values in aux file at end
+\AtEndDocument{
+ \exercisepoints@storetoaux{numberofexercises}{\theexercisepoints@exercisecount}%
+ \exercisepoints@storetoaux{points@total}{\strip@pt\exercisepoints@totalpoints}%
+ \exercisepoints@storetoaux{points@bonus}{\strip@pt\exercisepoints@bonuspoints}%
+ \newlength{\exercisepoints@totalpointswithbonus}%
+ \setlength{\exercisepoints@totalpointswithbonus}{\exercisepoints@totalpoints}%
+ \addtolength{\exercisepoints@totalpointswithbonus}{\exercisepoints@bonuspoints}%
+ \exercisepoints@storetoaux{points@totalwithbonus}{\strip@pt\exercisepoints@totalpointswithbonus}%
+}