%%%============================================================================== %% 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.13a} {2026/07/04} %% %% 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}[2026/06/01] %%%%%%% %%% %%% Just an attempt at having my package's info in a regular way %%% \pkginfograb_set:nn { } { props } sets package info %%% %%% \pkginfograbProvidesExplPackage { } { props } sets package info %%% and calls \ProvidesExplPackage %%% %%%%%%% \RequirePackage{pkginfograb} \pkginfograbProvidesExplPackage {ufrgscca-curr} { name = {ufrgscca-curr} , prefix = {ufrgscca} , date = {2026/07/04}, version = {2.13a} , description = {UFRGS/CCA curricula commands} } %%%%%%% %%% 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__ufrgscca_tt_tmpa_clist \clist_put_right:Nn \l__ufrgscca_tt_tmpa_clist { #2 } \starray_set_prop:nnV { classes }{ bib } \l__ufrgscca_tt_tmpa_clist } { basic } { \starray_get_prop:nnN { classes }{ bib basic } \l__ufrgscca_tt_tmpa_clist \clist_put_right:Nn \l__ufrgscca_tt_tmpa_clist { #2 } \starray_set_prop:nnV { classes }{ bib basic } \l__ufrgscca_tt_tmpa_clist } { compl } { \starray_get_prop:nnN { classes }{ bib compl } \l__ufrgscca_tt_tmpa_clist \clist_put_right:Nn \l__ufrgscca_tt_tmpa_clist { #2 } \starray_set_prop:nnV { classes }{ bib compl } \l__ufrgscca_tt_tmpa_clist } } { \starray_get_prop:nnN { classes }{ bib } \l__ufrgscca_tt_tmpa_clist \clist_put_right:Nn \l__ufrgscca_tt_tmpa_clist { #2 } \starray_set_prop:nnV { classes }{ bib } \l__ufrgscca_tt_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__ufrgscca_tt_tmpa_tl \starray_set_prop:nnV { classes.ref }{ currhash } \l__ufrgscca_tt_tmpa_tl \starray_get_prop:nnN { curricula.sem }{ semhash } \l__ufrgscca_tt_tmpa_tl \starray_set_prop:nnV { classes.ref }{ semhash } \l__ufrgscca_tt_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__ufrgscca_tt_tmpa_seq \c_colon_str { #1 } \seq_pop_left:NNTF \l__ufrgscca_tt_tmpa_seq \l__ufrgscca_tt_tmpa_tl { \tl_set_eq:NN #2 \l__ufrgscca_tt_tmpa_tl \seq_pop_left:NNTF \l__ufrgscca_tt_tmpa_seq \l__ufrgscca_tt_tmpb_tl { \tl_set_eq:NN #3 \l__ufrgscca_tt_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_parser: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__ufrgscca_tt_tmpa_tl \seq_gput_right:Ne \l__ufrgscca_tmp_prereq_seq { \l__ufrgscca_tt_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]{ ~\ ~OU }\seq_use:Nn \l__ufrgscca_tmp_prereq_seq { ~E~} }\\* } { & & & & \multicolumn{ 2 }{ J{ 11cm }}{ \smaller\makebox[10mm][l]{ }\seq_use:Nn \l__ufrgscca_tmp_prereq_seq { ~E~} }\\* \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__ufrgscca_tt_tmpa_clist \clist_gset_eq:NN \l__ufrgscca_tmpa_clist \l__ufrgscca_tt_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__ufrgscca_tt_tmpa_clist \clist_gset_eq:NN \l__ufrgscca_tmpa_clist \l__ufrgscca_tt_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__ufrgscca_tt_tmpa_clist \clist_gset_eq:NN \l__ufrgscca_tmpa_clist \l__ufrgscca_tt_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 } }