%%%============================================================================== %% Copyright 2022-present by Alceu Frigeri %% %% This work may be distributed and/or modified under the conditions of %% %% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt), %% version 1.3c (or later), and/or %% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html), %% version 3 (or later) %% %% This work has the LPPL maintenance status *maintained*. %% %% The Current Maintainer of this work is Alceu Frigeri %% %% This is version {2.12} {2025/09/18} %% %% The list of files that compose this work can be found in the README.md file at %% https://ctan.org/pkg/ufrgscca %% %%%============================================================================== %% UFRGS stands for "Federal University of Rio Grande do Sul" in south Brazil %% EE stands for "Engineering School" %% CCA stands for "Control and Automation Engineering Course" (Portuguese acronym) %%%============================================================================== \NeedsTeXFormat{LaTeX2e}[2023/11/01] \ProvidesExplPackage {ufrgscca-curr} {2025/09/18} {2.12} {UFRGS/CCA curricula commands} %%%%%%% %%% %%% Just an attempt of having my packages info in a regular way %%% Idea being: { / pkg info } for each and all. %%% %%%%%%% \keys_define:nn { ufrgscca-curr / pkg info} { name .code:n = {ufrgscca-curr} , prefix .code:n = {ufrgscca} , date .code:n = {2025/09/18}, version .code:n = {2.12} , description .code:n = {UFRGS/CCA~ curricula~ commands} } \cs_if_exist:NF \PkgInfo { \NewDocumentCommand \PkgInfo {mm} { \keys_set:nn {#1 / pkg info}{#2} } \NewDocumentCommand \PkgDescription {m} { \noindent Package~ \textbf{\PkgInfo{#1}{name}}~Version:~\PkgInfo{#1}{version}~ -~ \PkgInfo{#1}{date}\par \emph{\PkgInfo{#1}{description}}~\par } } %%%%%%% %%% End of cut-n-paste %%%%%%% %%%%%%% %%% %%% V-less nightmare TO BE DONE! %%% => convert all V referenced sequences into 'starray sub structures' %%% less efficient, but 'portable' and V-safe. %%% %%% => Alternative approach: convert a _seq into a clist then store it into starray (argh! double damm) %%% => or just use ..._clist instead of _seq (replacing all _seq that are stored in starrays by a _clist) %%% %%%%%%% \starray_new:n {topics} \starray_def_from_keyval:nn {topics} { topichash = , name = , color = , class . struct = { classcode = , } } \starray_new:n {classes} \starray_def_from_keyval:nn {classes} { cred = , classcode = , name = , summary = , topichash = , remark = , bib = , bib basic = , bib compl = , ref . struct = { currhash = , semhash = , kind = , } , } \starray_new:n {curricula} \starray_def_from_keyval:nn {curricula} { currhash = , name = , text = , sem.struct = { pos = , semhash = , name = , class . struct = { classcode = , kind = , obs = , pos = , color = , prereqset . struct = { prereq . struct = { starred = , classcode = , angIN = , angOUT = , } } , } , } , } \NewDocumentCommand\topicdef{O{}mm} { \starray_new_term:nn {topics}{#2} \starray_set_from_keyval:nn {topics} { topichash = {#2} , name = {#3} , color = {#1} , } } \tl_new:N \l__ufrgscca_default_topic_tl \NewDocumentCommand\defaulttopic{m} { \tl_set:Ne \l__ufrgscca_default_topic_tl{#1} } \NewDocumentCommand{\classdef}{O{\l__ufrgscca_default_topic_tl}mmm} { \starray_new_term:nn {classes}{#2} \starray_set_from_keyval:nn {classes} { classcode = {#2} , cred = {#3} , name = {#4} , topichash = {#1} , } \starray_set_prop:nnV {classes}{bib} \c_empty_clist \starray_set_prop:nnV {classes}{bib basic} \c_empty_clist \starray_set_prop:nnV {classes}{bib compl} \c_empty_clist \starray_set_iter_from_hash:nn {topics}{#1} \starray_new_term:nn {topics.class}{} \starray_set_prop:nnn {topics.class}{classcode}{#2} } \NewDocumentCommand{\csummary}{m} { \starray_set_prop:nnn {classes}{summary}{#1} } \NewDocumentCommand{\classremark}{m} { \starray_set_prop:nnn {classes}{remark}{#1} } \NewDocumentCommand{\bibdef}{O{main}m} { \str_case:nnF {#1} { {main} { \starray_get_prop:nnN {classes}{bib} \l_tmpa_clist \clist_put_right:Nn \l_tmpa_clist {#2} \starray_set_prop:nnV {classes}{bib} \l_tmpa_clist } {basic} { \starray_get_prop:nnN {classes}{bib basic} \l_tmpa_clist \clist_put_right:Nn \l_tmpa_clist {#2} \starray_set_prop:nnV {classes}{bib basic} \l_tmpa_clist } {compl} { \starray_get_prop:nnN {classes}{bib compl} \l_tmpa_clist \clist_put_right:Nn \l_tmpa_clist {#2} \starray_set_prop:nnV {classes}{bib compl} \l_tmpa_clist } } { \starray_get_prop:nnN {classes}{bib} \l_tmpa_clist \clist_put_right:Nn \l_tmpa_clist {#2} \starray_set_prop:nnV {classes}{bib} \l_tmpa_clist } } \NewDocumentCommand{\classset}{m} { \starray_set_iter_from_hash:nn {classes}{#1} } \let\setclass\classset \cs_generate_variant:Nn \starray_set_iter_from_hash:nn {ne} \cs_generate_variant:Nn \starray_set_iter_from_hash:nn {nV} \prg_generate_conditional_variant:Nnn \starray_set_iter_from_hash:nn {ne} {T , F , TF} \NewDocumentCommand{\currdef}{mmm} { \starray_new_term:nn {curricula}{#1} \starray_set_from_keyval:nn {curricula} { currhash = {#1} , name = {#2} , text = {#3} , } } \NewDocumentCommand{\semdef}{mmm} { \starray_new_term:nn {curricula.sem}{#1} \starray_set_from_keyval:nn {curricula.sem} { semhash = {#1} , name = {#2} , pos = {#3} , } } \NewDocumentCommand{\addclass}{O{}mmmO{}} { \starray_new_term:nn {curricula.sem.class}{#3} \starray_set_from_keyval:nn {curricula.sem.class} { color = {#1} , pos = {#2} , classcode = {#3} , kind = {#4} , obs = {#5} , } \starray_new_term:nn {curricula.sem.class.prereqset}{} \starray_set_iter_from_hash:nn {classes}{#3} \starray_new_term:nn {classes.ref}{} \starray_get_prop:nnN {curricula}{currhash} \l_tmpa_tl \starray_set_prop:nnV {classes.ref}{currhash} \l_tmpa_tl \starray_get_prop:nnN {curricula.sem}{semhash} \l_tmpa_tl \starray_set_prop:nnV {classes.ref}{semhash} \l_tmpa_tl \starray_set_prop:nnn {classes.ref}{kind}{#4} } \cs_new_protected:Npn \__ufrgscca_cut:nNN #1#2#3 { \tl_if_blank:nTF {#1} { \tl_set:Nn #2 {} \tl_set:Nn #3 {} } { \seq_set_split:NVn \l_tmpa_seq \c_colon_str {#1} \seq_pop_left:NNTF \l_tmpa_seq \l_tmpa_tl { \tl_set_eq:NN #2 \l_tmpa_tl \seq_pop_left:NNTF \l_tmpa_seq \l_tmpb_tl { \tl_set_eq:NN #3 \l_tmpb_tl } { \tl_set:Nn #3 {} } } { \tl_set:Nn #2 {} \tl_set:Nn #3 {} } } } \NewDocumentCommand{\depdef}{sO{}m} { \__ufrgscca_cut:nNN{#2}{\l__ufrgscca_partA_tl}{\l__ufrgscca_partB_tl} \tl_if_empty:NTF \l__ufrgscca_partB_tl { \str_case:NnF \l__ufrgscca_partA_tl { {A} { \tl_set:Nn \l__ufrgscca_angOUT_tl {30} \tl_set:Nn \l__ufrgscca_angIN_tl {180-30} } {B} { \tl_set:Nn \l__ufrgscca_angOUT_tl {60} \tl_set:Nn \l__ufrgscca_angIN_tl {180-60} } {C} { \tl_set:Nn \l__ufrgscca_angOUT_tl {80} \tl_set:Nn \l__ufrgscca_angIN_tl {180-80} } {-A} { \tl_set:Nn \l__ufrgscca_angOUT_tl {-30} \tl_set:Nn \l__ufrgscca_angIN_tl {180+30} } {-B} { \tl_set:Nn \l__ufrgscca_angOUT_tl {-60} \tl_set:Nn \l__ufrgscca_angIN_tl {180+60} } {-C} { \tl_set:Nn \l__ufrgscca_angOUT_tl {-80} \tl_set:Nn \l__ufrgscca_angIN_tl {180+80} } {A*} { \tl_set:Nn \l__ufrgscca_angOUT_tl {30} \tl_set:Nn \l__ufrgscca_angIN_tl {180+30} } {B*} { \tl_set:Nn \l__ufrgscca_angOUT_tl {60} \tl_set:Nn \l__ufrgscca_angIN_tl {180+60} } {C*} { \tl_set:Nn \l__ufrgscca_angOUT_tl {80} \tl_set:Nn \l__ufrgscca_angIN_tl {180+80} } {-A*} { \tl_set:Nn \l__ufrgscca_angOUT_tl {-30} \tl_set:Nn \l__ufrgscca_angIN_tl {180-30} } {-B*} { \tl_set:Nn \l__ufrgscca_angOUT_tl {60} \tl_set:Nn \l__ufrgscca_angIN_tl {180-60} } {-C*} { \tl_set:Nn \l__ufrgscca_angOUT_tl {80} \tl_set:Nn \l__ufrgscca_angIN_tl {180-80} } } { \tl_if_blank:VTF {\l__ufrgscca_partA_tl} { \tl_set:Nn \l__ufrgscca_angOUT_tl {0} \tl_set:Nn \l__ufrgscca_angIN_tl {180} } { \tl_set:Ne \l__ufrgscca_angOUT_tl {\fp_eval:n {\l__ufrgscca_partA_tl}} \tl_set:Ne \l__ufrgscca_angIN_tl {\fp_eval:n {180 - \l__ufrgscca_angOUT_tl}} } }%didn't match } { \tl_set:Ne \l__ufrgscca_angOUT_tl {\l__ufrgscca_partA_tl} \tl_set:Ne \l__ufrgscca_angIN_tl {180-\l__ufrgscca_partB_tl} } \starray_new_term:nn {curricula.sem.class.prereqset.prereq}{#3} \starray_set_from_keyval:nn {curricula.sem.class.prereqset.prereq} { starred = {#1} , classcode = {#3} } \starray_set_prop:nnV {curricula.sem.class.prereqset.prereq} {angIN} \l__ufrgscca_angIN_tl \starray_set_prop:nnV {curricula.sem.class.prereqset.prereq} {angOUT} \l__ufrgscca_angOUT_tl } \NewDocumentCommand{\altdep}{} { \starray_new_term:nn {curricula.sem.class.prereqset}{} } \cs_generate_variant:Nn \starray_set_iter_from_hash:nn {ne} %%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%% %%% %%% %%% %%% %%% %%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%% \tl_new:N \l__ufrgscca_tmp_class_tl \tl_new:N \l__ufrgscca_tmp_name_tl \tl_new:N \l__ufrgscca_tmp_obs_tl \tl_new:N \l__ufrgscca_tmp_kind_tl \tl_new:N \l__ufrgscca_tmp_cred_tl \tl_new:N \l__ufrgscca_tmp_topic_tl \tl_new:N \l__ufrgscca_tmp_color_tl \tl_new:N \l__ufrgscca_tmp_summary_tl \tl_new:N \l__ufrgscca_tmp_OR_tl \seq_new:N \l__ufrgscca_tmp_bib_seq \seq_new:N \l__ufrgscca_tmp_bibB_seq \seq_new:N \l__ufrgscca_tmp_prereq_seq \bool_new:N \l__ufrgscca_tmp_second_bool \clist_new:N \l__ufrgscca_tmpa_clist \NewDocumentCommand\TabEtp{sO{\notoc\section}mO{\footnotesize}}{% \starray_set_iter_from_hash:nn {curricula.sem}{#3} \bool_if:nTF {#1} { #4 \begin{tabular}{l@{\,}l@{\ }c@{\ }c@{\ }J{5mm}@{}J{10.2cm}}% \starray_get_prop:nnN {curricula.sem}{name} \l__ufrgscca_tmp_name_tl \use:e { & \exp_not:N \multicolumn{5}{J{11cm}}{\exp_not:N \textbf{\l__ufrgscca_tmp_name_tl}}}\\* } { \starray_term_syntax:n {curricula.sem} #2{\starray_parsed_get_prop:n {name}} #4 \begin{longtable}{l@{\,}l@{\ }c@{\ }c@{\ }J{5mm}@{}J{10.2cm}}% } \starray_iterate_over:nn {curricula.sem.class} { \starray_get_prop:nnN {curricula.sem.class}{classcode} \l__ufrgscca_tmp_class_tl \starray_get_prop:nnN {curricula.sem.class}{kind} \l__ufrgscca_tmp_kind_tl \starray_get_prop:nnN {curricula.sem.class}{color} \l__ufrgscca_tmp_color_tl \starray_set_iter_from_hash:neTF {classes}{\l__ufrgscca_tmp_class_tl} {} {\color{red}MISSING} \starray_get_prop:nnN {classes}{name} \l__ufrgscca_tmp_name_tl \starray_get_prop:nnN {classes}{cred} \l__ufrgscca_tmp_cred_tl % \tl_show:N \l__ufrgscca_tmp_name_tl \tl_if_empty:NT \l__ufrgscca_tmp_color_tl { \tl_set:Nn \l__ufrgscca_tmp_color_tl {black} } % \tl_show:N \l__ufrgscca_tmp_name_tl %% class identification \bool_if:NTF \l__ufrgscca_showind_bool { \use:e { & \l__ufrgscca_tmp_class_tl & \l__ufrgscca_tmp_cred_tl & \l__ufrgscca_tmp_kind_tl & \exp_not:N \multicolumn{2}{J{10.5cm}}{\exp_not:N \textcolor{\l__ufrgscca_tmp_color_tl}{\l__ufrgscca_tmp_name_tl}}\\* } } { \use:e { & \l__ufrgscca_tmp_class_tl & \l__ufrgscca_tmp_cred_tl & \l__ufrgscca_tmp_kind_tl & \exp_not:N \multicolumn{2}{J{10.5cm}}{\l__ufrgscca_tmp_name_tl}\\* } } %% Pre-reqs \bool_gset_false:N \l__ufrgscca_tmp_second_bool \starray_iterate_over:nnTF {curricula.sem.class.prereqset} { \seq_gclear:N \l__ufrgscca_tmp_prereq_seq \starray_iterate_over:nnTF {curricula.sem.class.prereqset.prereq} { \starray_get_prop:nnN {curricula.sem.class.prereqset.prereq}{classcode} \l_tmpa_tl \seq_gput_right:Ne \l__ufrgscca_tmp_prereq_seq {\l_tmpa_tl} } {} {} \seq_if_empty:NF \l__ufrgscca_tmp_prereq_seq { \bool_if:NTF \l__ufrgscca_tmp_second_bool { & & & & \multicolumn{2}{J{11cm}}{\smaller\makebox[10mm][l]{~\ ~OR}\seq_use:Nn \l__ufrgscca_tmp_prereq_seq {~AND~} }\\* } { & & & & \multicolumn{2}{J{11cm}}{\smaller\makebox[10mm][l]{}\seq_use:Nn \l__ufrgscca_tmp_prereq_seq {~AND~} }\\* \bool_gset_true:N \l__ufrgscca_tmp_second_bool } } } {} {} \starray_get_prop:nnN {curricula.sem.class}{obs} \l__ufrgscca_tmp_obs_tl \tl_if_empty:NF \l__ufrgscca_tmp_obs_tl { \use:e { & & & & & {\exp_not:N \scriptsize{\exp_not:N \emph{\l__ufrgscca_tmp_obs_tl}}}\\* } } \bool_if:nF {#1} { %% Topic \starray_get_prop:nnN {classes}{topichash} \l__ufrgscca_tmp_topic_tl \starray_set_iter_from_hash:ne {topics}{\l__ufrgscca_tmp_topic_tl} \starray_get_prop:nnN {topics}{name} \l__ufrgscca_tmp_topic_tl \starray_get_prop:nnN {topics}{color} \l__ufrgscca_tmp_color_tl \tl_if_empty:NT \l__ufrgscca_tmp_color_tl { \tl_set:Nn \l__ufrgscca_tmp_color_tl {black} } \use:e { & & & & \exp_not:N \multicolumn{2}{J{11cm}}{\exp_not:N \smaller \exp_not:N \scshape\exp_not:N \textcolor{\l__ufrgscca_tmp_color_tl}{\l__ufrgscca_tmp_topic_tl}}\\* } %% class summary & & & & \multicolumn{2}{J{11cm}}{\smaller\scshape Súmula}\\* \starray_get_prop:nnN {classes}{summary} \l__ufrgscca_tmp_summary_tl \use:e { & & & & & \exp_not:N \smaller \l__ufrgscca_tmp_summary_tl\\*} %% bibliography I \starray_get_prop:nnN {classes}{bib} \l_tmpa_clist \clist_gset_eq:NN \l__ufrgscca_tmpa_clist \l_tmpa_clist \clist_if_empty:NF \l__ufrgscca_tmpa_clist { & & & & \multicolumn{2}{J{11cm}}{\smaller\scshape Bibliografia~ Básica~ Essencial}\\* \clist_map_inline:Nn \l__ufrgscca_tmpa_clist { & & & & & \smaller \fullcite{##1}\\ % & & & & & \smaller\textopenbullet ~\ ~ ##1\\ } } %% bibliography II \starray_get_prop:nnN {classes}{bib basic} \l_tmpa_clist \clist_gset_eq:NN \l__ufrgscca_tmpa_clist \l_tmpa_clist \clist_if_empty:NF \l__ufrgscca_tmpa_clist { & & & & \multicolumn{2}{J{11cm}}{\smaller\scshape Bibliografia~ Básica}\\* \clist_map_inline:Nn \l__ufrgscca_tmpa_clist { & & & & & \smaller \fullcite{##1}\\ % & & & & & \smaller\textopenbullet ~\ ~ ##1\\ } } %% bibliography III \starray_get_prop:nnN {classes}{bib compl} \l_tmpa_clist \clist_gset_eq:NN \l__ufrgscca_tmpa_clist \l_tmpa_clist \clist_if_empty:NF \l__ufrgscca_tmpa_clist { & & & & \multicolumn{2}{J{11cm}}{\smaller\scshape Bibliografia~ Complementar}\\* \clist_map_inline:Nn \l__ufrgscca_tmpa_clist { & & & & & \smaller \fullcite{##1}\\ % & & & & & \smaller\textopenbullet ~\ ~ ##1\\ } } \\[-1.5mm] } } \bool_if:nTF {#1} { \end{tabular} } { \end{longtable} } } \seq_new:N \l__ufrgscca_tmp_classlst_seq \tl_new:N \l__ufrgscca_tmpa_tl \NewDocumentCommand{\TabTopic}{m} { \starray_set_iter_from_hash:nnTF {topics}{#1} { \begin{tabular}{l@{\,}l@{\ -\ }J{11.5cm}} \starray_get_prop:nnN {topics}{name} \l__ufrgscca_tmp_name_tl \starray_get_prop:nnN {topics}{color} \l__ufrgscca_tmp_color_tl \tl_if_empty:NF \l__ufrgscca_tmp_color_tl { \tl_set:Nn \l__ufrgscca_tmp_color_tl {black} } \use:e { & \exp_not:N \multicolumn{2}{J{11cm}}{\exp_not:N \textcolor{\l__ufrgscca_tmp_color_tl}{\exp_not:N \textbf{\l__ufrgscca_tmp_name_tl} }}}\\\hline \starray_iterate_over:nnTF {topics.class} { \starray_get_prop:nnN {topics.class}{classcode}\l__ufrgscca_tmpa_tl \starray_set_iter_from_hash:nV {classes} \l__ufrgscca_tmpa_tl \starray_get_prop:nnN {classes}{name} \l__ufrgscca_tmp_name_tl \use:e { & \l__ufrgscca_tmpa_tl & \l__ufrgscca_tmp_name_tl\\} }{}{} \end{tabular} } { \textbf{--Topic #1 non existant--} } } %%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%% %%% %%% %%% %%% %%% %%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%% \bool_new:N \l__ufrgscca_colors_topic_bool \bool_new:N \l__ufrgscca_colors_class_bool \keys_define:nn { ufrgscca / curr graph} { deltaX .usage:n = general, deltaX .fp_set:N = \l__ufrgscca_graph_deltaX_fp, deltaX .value_required:n = true, deltaX .initial:n = {4.2}, deltaY .usage:n = general, deltaY .fp_set:N = \l__ufrgscca_graph_deltaY_fp, deltaY .value_required:n = true, deltaY .initial:n = {2.1}, clipminX .usage:n = general, clipminX .fp_set:N = \l__ufrgscca_graph_clip_minX_fp, clipminX .value_required:n = true, clipminX .initial:n = {0}, maxX .usage:n = general, maxX .fp_set:N = \l__ufrgscca_graph_maxX_fp, maxX .value_required:n = true, maxX .initial:n = {11.5}, clipminY .usage:n = general, clipminY .fp_set:N = \l__ufrgscca_graph_clip_minY_fp, clipminY .value_required:n = true, clipminY .initial:n = {0}, maxY .usage:n = general, maxY .fp_set:N = \l__ufrgscca_graph_maxY_fp, maxY .value_required:n = true, maxY .initial:n = {-18.5}, graph~ title .usage:n = general, graph~ title .tl_set:N = \l__ufrgscca_graph_title_tl, graph~ title .value_required:n = true, graph~ title .initial:n = {Graph Title}, default~ color .usage:n = general, default~ color .tl_set:N = \l__ufrgscca_graph_default_color_tl, default~ color .value_required:n = true, default~ color .initial:n = {black}, colors .usage:n = general, colors .choice: , colors / none .code:n = { \bool_set_false:N \l__ufrgscca_colors_topic_bool \bool_set_false:N \l__ufrgscca_colors_class_bool } , colors / topic .code:n = { \bool_set_true:N \l__ufrgscca_colors_topic_bool \bool_set_false:N \l__ufrgscca_colors_class_bool } , colors / class .code:n = { \bool_set_false:N \l__ufrgscca_colors_topic_bool \bool_set_true:N \l__ufrgscca_colors_class_bool } , colors / both .code:n = { \bool_set_true:N \l__ufrgscca_colors_topic_bool \bool_set_true:N \l__ufrgscca_colors_class_bool } , colors / unknown .code:n = { \bool_set_false:N \l__ufrgscca_colors_topic_bool \bool_set_false:N \l__ufrgscca_colors_class_bool } , } \keys_define:nn { ufrgscca / graph angles} { } \NewDocumentEnvironment{tikzGraphSem}{O{}}{% \bool_set_false:N \l__ufrgscca_colors_topic_bool \bool_set_false:N \l__ufrgscca_colors_class_bool \keys_set:nn {ufrgscca / curr graph}{#1} \fp_set:Nn \l__ufrgscca_graph_clip_maxX_fp {\l__ufrgscca_graph_maxX_fp * \l__ufrgscca_graph_deltaX_fp } \fp_set:Nn \l__ufrgscca_graph_clip_maxY_fp {\l__ufrgscca_graph_maxY_fp * \l__ufrgscca_graph_deltaY_fp } \begin{tikzpicture}[% disc/.style={% ellipse~ split, double, draw, line~ width=2pt,% every~ text~ node part/.style={font=\small\bfseries},% every~ lower~ node part/.style={font=\large\bfseries,color=blue}},% dep/.style={->,dotted,line~ width=3pt}]% \begin{scope} \clip ( \fp_use:N \l__ufrgscca_graph_clip_minX_fp , \fp_use:N \l__ufrgscca_graph_clip_minY_fp ) -- ( \fp_use:N \l__ufrgscca_graph_clip_minX_fp , \fp_use:N \l__ufrgscca_graph_clip_maxY_fp ) -- ( \fp_use:N \l__ufrgscca_graph_clip_maxX_fp , \fp_use:N \l__ufrgscca_graph_clip_maxY_fp ) -- ( \fp_use:N \l__ufrgscca_graph_clip_maxX_fp , \fp_use:N \l__ufrgscca_graph_clip_minY_fp ); \filldraw[color=red] ( \fp_eval:n {0.5*\l__ufrgscca_graph_clip_maxX_fp} , \fp_eval:n {-0.25*\l__ufrgscca_graph_deltaY_fp} ) node{\Huge\textbf{\l__ufrgscca_graph_title_tl}};% }{% \end{scope}% \end{tikzpicture}% } \fp_new:N \l__ufrgscca_tmp_posX_fp \bool_new:N \l__ufrgscca_tmp_starred_bool \tl_new:N \l__ufrgscca_tmp_prereq_name_tl \tl_new:N \l__ufrgscca_graph_color_tl \NewDocumentCommand{\GraphEtp}{m} { \starray_set_iter_from_hash:nn {curricula.sem}{#1} \starray_get_prop:nnN {curricula.sem}{pos} \l__ufrgscca_tmp_pos_tl \starray_get_prop:nnN {curricula.sem}{name} \l__ufrgscca_tmp_name_tl \fp_set:Nn \l__ufrgscca_tmp_posX_fp {\l__ufrgscca_tmp_pos_tl * \l__ufrgscca_graph_deltaX_fp - 0.5*\l__ufrgscca_graph_deltaX_fp} \draw ( \fp_use:N \l__ufrgscca_tmp_posX_fp , \fp_eval:n {-\l__ufrgscca_graph_deltaY_fp} ) node[disc](#1) {\l__ufrgscca_tmp_name_tl }; \starray_iterate_over:nn {curricula.sem.class} { \starray_get_prop:nnN {curricula.sem.class}{pos} \l__ufrgscca_tmp_pos_tl \starray_get_prop:nnN {curricula.sem.class}{classcode} \l__ufrgscca_tmp_name_tl \starray_set_iter_from_hash:ne {classes}{\l__ufrgscca_tmp_name_tl} \starray_get_prop:nnN {classes}{cred} \l__ufrgscca_tmp_cred_tl \starray_get_prop:nnN {classes}{topichash} \l__ufrgscca_tmp_topic_tl \tl_set:Ne \l__ufrgscca_graph_color_tl {\l__ufrgscca_graph_default_color_tl} \bool_if:NT \l__ufrgscca_colors_topic_bool { \starray_set_iter_from_hash:ne {topics}{\l__ufrgscca_tmp_topic_tl} \starray_get_prop:nnN {topics}{color} \l__ufrgscca_tmp_color_tl \tl_if_empty:NF \l__ufrgscca_tmp_color_tl { \tl_set:Ne \l__ufrgscca_graph_color_tl {\l__ufrgscca_tmp_color_tl} } } \bool_if:NT \l__ufrgscca_colors_class_bool { \starray_get_prop:nnN {curricula.sem.class}{color} \l__ufrgscca_tmp_color_tl \tl_if_empty:NF \l__ufrgscca_tmp_color_tl { \tl_set:Ne \l__ufrgscca_graph_color_tl {\l__ufrgscca_tmp_color_tl} } } \draw ( \fp_use:N \l__ufrgscca_tmp_posX_fp , \fp_eval:n {\l__ufrgscca_tmp_pos_tl * \l__ufrgscca_graph_deltaY_fp - 1.25 * \l__ufrgscca_graph_deltaY_fp} ) node[disc,\l__ufrgscca_graph_color_tl](\l__ufrgscca_tmp_name_tl) { \l__ufrgscca_tmp_name_tl \nodepart{lower} \l__ufrgscca_tmp_cred_tl ~\ ~créd. } ; \starray_iterate_over:nnTF {curricula.sem.class.prereqset} { \starray_iterate_over:nnTF {curricula.sem.class.prereqset.prereq} { \starray_get_prop:nnN {curricula.sem.class.prereqset.prereq}{starred} \l__ufrgscca_tmp_starred_bool \bool_if:NF \l__ufrgscca_tmp_starred_bool { \starray_get_prop:nnN {curricula.sem.class.prereqset.prereq}{classcode} \l__ufrgscca_tmp_prereq_name_tl \starray_get_prop:nnN {curricula.sem.class.prereqset.prereq}{angIN} \l__ufrgscca_angIN_tl \starray_get_prop:nnN {curricula.sem.class.prereqset.prereq}{angOUT} \l__ufrgscca_angOUT_tl \path[dep,\l__ufrgscca_graph_color_tl] ( \l__ufrgscca_tmp_prereq_name_tl ) edge [ out=\l__ufrgscca_angOUT_tl , in=\l__ufrgscca_angIN_tl] (\l__ufrgscca_tmp_name_tl) ; } }{}{} %iterate over:TF prereq }{}{} %iterate over:TF prereqset } }