% ---------------------------------------------------------------------------- % the XSIM package - grades module % % eXercise Sheets IMproved % % ---------------------------------------------------------------------------- % Clemens Niederberger % Web: https://github.com/cgnieder/xsim % E-Mail: contact@mychemistry.eu % ---------------------------------------------------------------------------- % Copyright 2017--2020 Clemens Niederberger % % 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 Clemens Niederberger. % ---------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % ---------------------------------------------------------------------------- \XSIMmodule{grades}{distribute goal sums to grades} \xsim_load_modules:n {goals} \msg_new:nnn {xsim} {grade-unknown} { The~ grade~ `#1'~ has~ never~ been~ declared~ \msg_line_context: } \bool_new:N \l__xsim_grades_half_bool \fp_new:N \l__xsim_grade_round_fp \fp_zero:N \l__xsim_grade_round_fp \prop_new:N \l__xsim_relative_grades_prop \tl_new:N \l__xsim_grade_split_tl \cs_new:Npn \__xsim_fp_round_to_half:n #1 { round( 2*(#1),0)/2 } \cs_new:Npn \__xsim_grades_round:n #1 { round ( #1 , \l__xsim_grade_round_fp ) } % #1: factor % #2: goal sum \cs_new:Npn \__xsim_grade_rounded:nn #1#2 { \bool_if:NTF \l__xsim_grades_half_bool { \__xsim_fp_round_to_half:n } { \__xsim_grades_round:n } { (#1) * (#2) } } \cs_new_protected:Npn \xsim_declare_relative_grades:n #1 { \seq_set_split:NVn \l__xsim_tmpa_seq \l__xsim_grade_split_tl {#1} \seq_map_inline:Nn \l__xsim_tmpa_seq { \__xsim_declare_relative_grade:w ##1 \q_stop } \xsim_verbose:n {Declaring~ relative~ grade~ distribution} } \cs_new_protected:Npn \__xsim_declare_relative_grade:w #1 = #2 \q_stop { \tl_set:Nx \l__xsim_tmpa_tl { \tl_trim_spaces:n {#1} } \tl_set:Nx \l__xsim_tmpb_tl { \tl_trim_spaces:n {#2} } \prop_put:NVV \l__xsim_relative_grades_prop \l__xsim_tmpa_tl \l__xsim_tmpb_tl } % #1: grade % #2: sum of points % #3: code after grade requirement if == 1 % #4: code after grade requirement if != 1 \cs_new_protected:Npn \xsim_get_grade:nnnn #1#2#3#4 { \prop_get:NnNTF \l__xsim_relative_grades_prop {#1} \l__xsim_tmpa_tl { \xsim_print_goal:nnn { min( \__xsim_grade_rounded:nn { \l__xsim_tmpa_tl } {#2} , #2 ) } {#3} {#4} } { \msg_error:nnn {xsim} {grade-unknown} {#1} } } % #1: grade % #2: goal % #3: code after grade requirement if == 1 % #4: code after grade requirement if != 1 \cs_new_protected:Npn \xsim_get_grade_goal:nnnn #1#2#3#4 { \xsim_if_goal_exist:nTF {#2} { \xsim_get_grade:nnnn {#1} { \use:c {g__xsim_total_goal_#2_fp} } {#3} {#4} } { \msg_error:nnn {xsim} {goal-unknown} {#2} } } % #1: grade % #2: goal list (separated with +) % #3: code after grade requirement if == 1 % #4: code after grade requirement if != 1 \cs_new_protected:Npn \xsim_get_grade_requirement:nnnn #1#2#3#4 { \seq_set_split:Nnn \l__xsim_tmpa_seq {+} {#2} \fp_zero:N \l__xsim_tmpa_fp \seq_map_inline:Nn \l__xsim_tmpa_seq { \fp_add:Nn \l__xsim_tmpa_fp { \use:c {g__xsim_total_goal_\tl_trim_spaces:n {##1} _fp} } } \xsim_get_grade:nnnn {#1} { \l__xsim_tmpa_fp } {#3} {#4} } % #1: grade % #2: code after grade requirement if == 1 % #3: code after grade requirement if != 1 \cs_new_protected:Npn \xsim_get_absolute_grade_requirement:nnn #1#2#3 { \fp_zero:N \l__xsim_tmpa_fp \xsim_foreach_goal:n { \fp_add:Nn \l__xsim_tmpa_fp { \use:c {g__xsim_total_goal_##1_fp} } } \xsim_get_grade:nnnn {#1} { \l__xsim_tmpa_fp } {#2} {#3} } \keys_define:nn {xsim/grades} { round .fp_set:N = \l__xsim_grade_round_fp , half .bool_set:N = \l__xsim_grades_half_bool , split .tl_set:N = \l__xsim_grade_split_tl , split .initial:n = {,} } % ---------------------------------------------------------------------------- \file_input_stop: