summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-03-16 22:06:48 +0000
committerKarl Berry <karl@freefriends.org>2021-03-16 22:06:48 +0000
commitc830caf8a92fadfa0ff7b0e1b88ac58c2ad07ae5 (patch)
tree947589149c3da5ce24fcb19519757fe4c8385f16 /Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls
parentf2effa23ac78e40a3add9f09b6a9bce843941ce3 (diff)
tuda-ci (16mar21)
git-svn-id: svn://tug.org/texlive/trunk@58433 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls')
-rw-r--r--Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls246
1 files changed, 216 insertions, 30 deletions
diff --git a/Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls b/Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls
index 659ccdb3514..2f7af0470fe 100644
--- a/Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls
+++ b/Master/texmf-dist/tex/latex/tuda-ci/tudaexercise.cls
@@ -1,4 +1,4 @@
-%% This is file `tudaexercise.cls' version 3.12 (2021/03/06),
+%% This is file `tudaexercise.cls' version 3.13 (2021/03/16),
%% it is part of
%% TUDa-CI -- Corporate Design for TU Darmstadt
%% ----------------------------------------------------------------------------
@@ -26,8 +26,8 @@
%%
%% ============================================================================
%%
-\def\fileversion{3.12}
-\def\filedate{2021/03/06}
+\def\fileversion{3.13}
+\def\filedate{2021/03/16}
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{expl3}
\ProvidesExplClass{tudaexercise}
@@ -41,7 +41,12 @@
\prop_gput:Nnn \g_ptxcd_clsopts_prop {captions} {nooneline}
\prop_gput:Nnn \g_ptxcd_clsopts_prop {parskip} {half-}
-\int_new:N \g_ptxcd_ruledheaders_int
+\prop_new:N \g__ptxcd_points_collector_prop
+\bool_new:N \l__ptxcd_points_auto_bool
+\bool_new:N \g__ptxcd_points_bool
+\prop_new:N \g__ptxcd_loaded_points_prop
+\fp_new:N \g__ptxcd_points_total_fp
+
\int_new:N \g_ptxcd_paper_int
\bool_new:N \g_ptxcd_geometry_bool
@@ -51,6 +56,17 @@
\bool_new:N \g_ptxcd_smalltitle_bool
\str_new:N \g_ptxcd_department_str
+\tl_new:N \g_ptxcd_tmp_tl
+\int_new:N \g_ptxcd_tmp_int
+\tl_new:N \l_ptxcd_tmp_tl
+
+\clist_map_inline:nn {section,subsection,subsubsection,task,subtask,@solution} {
+ \bool_new:c {g__ptxcd_ruled_#1_bool}
+ \bool_gset_true:c {g__ptxcd_ruled_#1_bool}
+}
+
+\bool_new:N \g__ptxcd_runin_subtask_bool
+
\RequirePackage{environ}
\newenvironment{solution}{}{}
@@ -171,6 +187,21 @@
},
solution .default:n = true,
unknown .code:n = {\prop_gput:NVn \g_ptxcd_unknown_clsopts_prop \l_keys_key_tl {#1}},
+ points .choice:,
+ points / true .code:n = \bool_set_false:N \l__ptxcd_points_auto_bool\bool_gset_true:N \g__ptxcd_points_bool,
+ points /false .code:n = \bool_set_false:N \l__ptxcd_points_auto_bool\bool_gset_false:N \g__ptxcd_points_bool,
+ points / auto .code:n = \bool_set_true:N \l__ptxcd_points_auto_bool\bool_gset_true:N \g__ptxcd_points_bool,
+ points .initial:n = false,
+ subtask .choice:,
+ subtask / ruled .code:n =
+ \bool_gset_true:N \g__ptxcd_ruled_subtask_bool
+ \bool_gset_false:N \g__ptxcd_runin_subtask_bool,
+ subtask / runin .code:n =
+ \bool_gset_false:N \g__ptxcd_ruled_subtask_bool
+ \bool_gset_true:N \g__ptxcd_runin_subtask_bool,
+ subtask / plain .code:n =
+ \bool_gset_false:N \g__ptxcd_ruled_subtask_bool
+ \bool_gset_false:N \g__ptxcd_runin_subtask_bool,
}
\ProcessKeysOptions{ptxcd/exercise}
@@ -186,23 +217,33 @@
\RequirePackage{environ}
\bool_new:N \l_ptxcd_ex_subtask_fallback_bool
+\fp_new:N \l_ptxcd_ex_task_points_fp
+\fp_new:N \g__ptxcd_ex_collected_points_fp
+\tl_new:N \l_ptxcd_ex_task_credit_tl
\keys_define:nn {ptxcd/task}{
- points .int_set:N = \l_ptxcd_ex_task_points_int,
+ points .choice:,
+ points / auto .code:n =
+ \bool_set_true:N \l__ptxcd_points_auto_bool,
+ points / unknown .code:n = \fp_set:Nn \l_ptxcd_ex_task_points_fp {#1}
+ \bool_set_false:N \l__ptxcd_points_auto_bool,
points .initial:n = 0,
- credit .tl_set:N = \l_ptxcd_ex_task_credit_tl,
+ credit .code:n = \tl_set:Nn \l_ptxcd_ex_task_credit_tl {#1}
+ \bool_set_false:N \l__ptxcd_points_auto_bool,
credit .initial:n =,
solution .meta:nn ={ptxcd/exercise}{solution=#1},
}
+\fp_new:N \l_ptxcd_ex_subtask_points_fp
\keys_define:nn {ptxcd/subtask} {
credit .tl_set:N = \l_ptxcd_ex_subtask_credit_tl,
credit .initial:n =,
- points .int_set:N = \l_ptxcd_ex_subtask_points_int,
+ points .code:n = \fp_set:Nn \l_ptxcd_ex_subtask_points_fp {#1}
+ \bool_set_false:N \l__ptxcd_points_auto_bool,
points .initial:n = 0,
title .tl_set:N = \l_ptxcd_ex_title_tl,
title .initial:n =,
- unknown .code:n = \bool_set_true:N \l_ptxcd_ex_subtask_fallback_bool \tl_clear:N \l_ptxcd_ex_subtask_credit_tl \int_zero:N \l_ptxcd_ex_subtask_points_int,
+ unknown .code:n = \bool_set_true:N \l_ptxcd_ex_subtask_fallback_bool \tl_clear:N \l_ptxcd_ex_subtask_credit_tl \fp_zero:N \l_ptxcd_ex_subtask_points_fp,
}
\keys_define:nn {ptxcd/exercise/headline} {
@@ -257,22 +298,30 @@
\renewcommand*\sectionlinesformat[4]{%
\parbox{\linewidth}{
+ \bool_if:cT {g__ptxcd_ruled_#1_bool} {
\rule[5\g_ptxcd_titlerule_dim]{\linewidth}{\g_ptxcd_titlerule_dim}\par\nointerlineskip
+ }
\@hangfrom{%
\hskip #2#3}{
\tl_if_eq:nnT {#1} {task} {
\exp_args:No \tl_if_empty:nF {#4}
- {:~}
+ {:~}
+ \bool_if:NT \l__ptxcd_points_auto_bool {
+ \exp_args:NNx \prop_get:NnN \g__ptxcd_loaded_points_prop {\thetask} \l_ptxcd_tmp_tl
+ \quark_if_no_value:NF \l_ptxcd_tmp_tl {
+ \fp_set:Nn \l_ptxcd_ex_task_points_fp {\l_ptxcd_tmp_tl}
+ }
+ }
}
#4
\tl_if_in:nnT {#1} {task} {
\tl_if_empty:cTF{l_ptxcd_ex_#1_credit_tl}
- {\pointformat{\tl_use:c {l_ptxcd_ex_#1_points_int}}}
+ {\pointformat{\fp_to_decimal:c {l_ptxcd_ex_#1_points_fp}}}
{\creditformat{\tl_use:c {l_ptxcd_ex_#1_credit_tl}}}
}
\rule[-\dp\strutbox]{0pt}{\dp\strutbox}\par}\nointerlineskip
\skip_vertical:n {\ptxcd_titlerule_sep: -\dp\strutbox}
- \smash{\rule{\linewidth}{\g_ptxcd_titlerule_dim}}
+ \bool_if:cT {g__ptxcd_ruled_#1_bool} {\smash{\rule{\linewidth}{\g_ptxcd_titlerule_dim}}}
}}
@@ -676,21 +725,26 @@
\newcommand*{\StudentIDsep}{:~}
\providecommand{\creditformat}[1]{\space(#1)}
+\providecommand{\creditformatsum}[1]{\creditformat{#1}}
\newcommand*{\pointformat}[1]{
- \int_case:nnF {#1}
+ \fp_compare:nF {#1 = 0} {
+ \bool_if:NTF \l__ptxcd_points_auto_bool
+ \creditformatsum
+ \creditformat
{
- {0} {}
- {1} {\creditformat{\int_to_arabic:n {#1}\space\PointName}}
+ \fp_to_decimal:n {#1}\space
+ \fp_compare:nTF {#1=1}
+ \PointName
+ \PointsName
}
- {\creditformat{\int_to_arabic:n {#1}\space\PointsName}}
}
+}
\providecaptionname{ngerman, german}{\PointName}{Punkt}
\providecaptionname{english, american, british}{\PointName}{Point}
\providecommand{\PointsName}{Punkte}
\providecaptionname{ngerman, german}{\PointsName}{Punkte}
\providecaptionname{english, american, british}{\PointsName}{Points}
-
%Has to be initialized after captionnames have been defined
\AtBeginDocument{
\ptxcd_update_headline_boxes:
@@ -698,12 +752,10 @@
\global\let\ConfigureHeadline\ptxcd_ConfigureHeadline:n
}
-
-
%task environment
\DeclareSectionCommand[%
style=section,%
- level=1,%
+ level=2,%
indent=\z@,%
beforeskip=\cs_if_exist_use:NF \scr@subsection@beforeskip {-3.25ex\@plus -1ex \@minus -.2ex},%
afterskip=\cs_if_exist_use:NF \scr@subsection@afterskip {1.5ex \@plus .2ex},%
@@ -712,7 +764,10 @@
tocnumwidth=\cs_if_exist_use:NF \scr@tso@subsection@numwidth {2.3em},%
]{task}
-\renewcommand*{\thetask}{\g_ptxcd_ex_sheetnum_tl\tl_if_empty:NF \g_ptxcd_ex_sheetnum_tl{.}\arabic{task}}
+\renewcommand*{\thetask}{
+ \g_ptxcd_ex_sheetnum_tl\tl_if_empty:NF \g_ptxcd_ex_sheetnum_tl{.}
+ \arabic{task}
+}
\renewcommand*{\taskformat}{\taskname\tasksep\thetask{}}
\let\@task\task
@@ -721,7 +776,17 @@
\NewDocumentEnvironment{task}{om}{
\IfNoValueF{#1}{\keys_set:nn {ptxcd/task}{#1}}
\@task{#2}
-}{}
+ \bool_if:NF \l__ptxcd_points_auto_bool {
+ \prop_gput:Nxx \g__ptxcd_points_collector_prop
+ {\thetask} {\fp_to_decimal:N \l_ptxcd_ex_task_points_fp}
+ }
+}{
+ \bool_if:NT \l__ptxcd_points_auto_bool {
+ \prop_gput:Nxx \g__ptxcd_points_collector_prop
+ {\thetask} {\fp_to_decimal:N \g__ptxcd_ex_collected_points_fp}
+ \fp_gzero:N \g__ptxcd_ex_collected_points_fp
+ }
+}
\cs_set_eq:cN {task*} \task
\cs_set_eq:cN {endtask*} \endtask
@@ -729,7 +794,7 @@
% subtasks
\DeclareSectionCommand[%
style=section,%
- level=2,%
+ level=3,%
indent=\z@,%
beforeskip=\cs_if_exist_use:NF \scr@subsubsection@beforeskip {-3.25ex\@plus -1ex \@minus -.2ex},%
afterskip=\cs_if_exist_use:NF \scr@subsubsection@afterskip {1.5ex \@plus .2ex},%
@@ -739,6 +804,10 @@
counterwithin=task,%
]{subtask}
+\bool_if:NT \g__ptxcd_runin_subtask_bool {
+ \RedeclareSectionCommand[runin=true]{subtask}
+}
+
\renewcommand*{\thesubtask}{\alph{subtask})}
\renewcommand*{\subtaskformat}{\thetask{}\thesubtask\enskip}
\setkomafont{subtask}{\mdseries\normalsize}
@@ -767,14 +836,14 @@
%Solution mechanism
\DeclareSectionCommand[%
-style=section,%
-level=2,%
-indent=\z@,%
-beforeskip=\cs_if_exist_use:NF \scr@subsubsection@beforeskip {-3.25ex\@plus -1ex \@minus -.2ex},%
-afterskip=\cs_if_exist_use:NF \scr@subsubsection@afterskip {1.5ex \@plus .2ex},%
-tocstyle=subsection,%
-tocindent=\cs_if_exist_use:NF \scr@tso@subsubsection@indent {1.5em},%
-tocnumwidth=\cs_if_exist_use:NF \scr@tso@subsubsection@numwidth {2.3em},%
+ style=section,%
+ level=3,%
+ indent=\z@,%
+ beforeskip=\cs_if_exist_use:NF \scr@subsubsection@beforeskip {-3.25ex\@plus -1ex \@minus -.2ex},%
+ afterskip=\cs_if_exist_use:NF \scr@subsubsection@afterskip {1.5ex \@plus .2ex},%
+ tocstyle=subsection,%
+ tocindent=\cs_if_exist_use:NF \scr@tso@subsubsection@indent {1.5em},%
+ tocnumwidth=\cs_if_exist_use:NF \scr@tso@subsubsection@numwidth {2.3em},%
]{@solution}
@@ -819,5 +888,122 @@ tocnumwidth=\cs_if_exist_use:NF \scr@tso@subsubsection@numwidth {2.3em},%
\ptxcd_makeheadrule[color=identbarcolor, width=\textwidth]{ptxcd_headrule}
+% Point referencing
+\AddtoDoHook{heading/preinit/subtask}{
+ \bool_if:NT \g__ptxcd_points_bool {
+ \fp_gadd:Nn \g__ptxcd_ex_collected_points_fp {\l_ptxcd_ex_subtask_points_fp}
+ }
+}
+
+\AddtoDoHook{heading/preinit/task}{
+ \fp_gzero:N \g__ptxcd_ex_collected_points_fp
+}
+
+
+\msg_new:nnn {tudaexercise} {points-differ} {
+ Value~of~points~changed~for~at~least~one~task.\\
+ Please~rerun~LaTeX~to~get~correct~references~and~calculations.
+}
+
+\msg_new:nnn {tudaexercise} {empty-point-mapping} {
+ I~could~not~find~references~for~points~in~the~aux~file.\\
+ Please~rerun~LaTeX~to~get~correct~references~and~calculations.
+}
+
+\msg_new:nnn {tudaexercise} {point-referencing-disabled} {
+ You~try~to~use~#1.\\
+ This~function~is~only~available~with~points=true~or~points=auto.\\
+ Please~activate~referencing~to~use~it.
+}
+
+\bool_if:NTF \g__ptxcd_points_bool {
+ \BeforeClosingMainAux{
+ \tl_clear:N \l_tmpa_tl
+ \tl_clear:N \l_tmpb_tl
+ \prop_map_inline:Nn \g__ptxcd_points_collector_prop {
+ \tl_put_right:Nn \l_tmpa_tl {#1=#2,}
+ }
+ \prop_map_inline:Nn \g__ptxcd_loaded_points_prop {
+ \tl_put_right:Nn \l_tmpb_tl {#1=#2,}
+ }
+ \tl_if_eq:NNF \l_tmpa_tl \l_tmpb_tl {
+ \msg_warning:nn {tudaexercise} {points-differ}
+ }
+ \iow_now:Nx \@auxout{
+ \exp_not:N \ptxcd@LoadPoints[\thetask]{\l_tmpa_tl}
+ }
+ }
+
+ \newcommand{\getPoints}[1]{
+ \exp_args:NNf \prop_get:NnNTF \g__ptxcd_loaded_points_prop {#1} \l_tmpa_tl
+ {\l_tmpa_tl}
+ {\nfss@text{\reset@font\bfseries??}}
+ }
+
+ \newcommand{\refPoints}[1]{
+ \edef\x{#1}
+ \cs_if_exist:cTF {r@\x} {
+ \getPoints{\tl_head:v {r@\x}}
+ }{
+ \nfss@text{\reset@font\bfseries??}
+ }
+ }
+
+ \newcommand{\getPointsTotal}{
+ \fp_use:N \g__ptxcd_points_total_fp
+ }
+} {
+ \newcommand{\getPoints}[1]{
+ \msg_error:nnn {tudaexercise} {point-referencing-disabled} {\getPoints}
+ }
+ \newcommand{\refPoints}[1]{
+ \msg_error:nnn {tudaexercise} {point-referencing-disabled} {\refPoints}
+ }
+ \newcommand{\getPointsTotal}[1]{
+ \msg_error:nnn {tudaexercise} {point-referencing-disabled} {\getPointsTotal}
+ }
+}
+
+\cs_new:Nn \__ptxcd_map_points_helper:nn {#1-#2}
+\NewDocumentCommand{\mapPoints}{sO{1}m}{
+ \cs_gset_nopar:Nn \__ptxcd_map_points_helper:nn {#3}
+ \prop_if_empty:NTF \g__ptxcd_loaded_points_prop {
+ \msg_warning:nn {tudaexercise} {empty-point-mapping}
+ \__ptxcd_map_points_helper:nn {?task?} {?points?}
+ }{
+ \int_gset:Nn \g_ptxcd_tmp_int {\value{task}}
+ \setcounter{task}{#2}
+ \tl_gclear:N \g_ptxcd_tmp_tl
+ \bool_gset_true:N \g_tmpa_bool
+ \bool_while_do:Nn \g_tmpa_bool
+ {
+ \exp_args:NNx \prop_get:NnNTF \g__ptxcd_loaded_points_prop {\thetask} \l_tmpa_tl
+ {
+ \fp_compare:nF {\l_tmpa_tl = 0}
+ {
+ \tl_gput_right:Nn \g_ptxcd_tmp_tl {\__ptxcd_map_points_helper:nn}
+ \tl_gput_right:Nx \g_ptxcd_tmp_tl {{\thetask} {\l_tmpa_tl}}
+ }
+ }
+ {\bool_gset_false:N \g_tmpa_bool}
+ \stepcounter{task}
+ }
+ \setcounter{task}{\int_use:N \g_ptxcd_tmp_int}
+ \g_ptxcd_tmp_tl
+ }
+}
+
+
+\newcommand*{\ptxcd@LoadPoints}[2][]{
+ \prop_gset_from_keyval:Nn \g__ptxcd_loaded_points_prop {
+ #2
+ }
+ \fp_gzero:N \g__ptxcd_points_total_fp
+ \prop_map_inline:Nn \g__ptxcd_loaded_points_prop {
+ \fp_gadd:Nn \g__ptxcd_points_total_fp {##2}
+ }
+}
+
+
\endinput
%End of class tudaexercise.cls