%%%==============================================================================
%% 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.10} {2024/04/20}
%%
%% 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}
    {2024/04/20}
    {2.10}
    {UFRGS/CCA curricula commands}

%%%%%%%
%%%
%%% Just an attempt of having my packages info in a regular way
%%% Idea being: { <pck-name> / 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 = {2024/04/20},
     version     .code:n = {2.10} ,
     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_new:n {classes}
\starray_new:n {curricula}

\starray_def_from_keyval:nn {topics}
  {
    self  = ,
    name = ,
    color = ,
    uniqueID = , % to replace class list (V-less)
  }

\starray_def_from_keyval:nn {classes}
  {
   cred = ,
   self = ,
   name = ,
   summary = ,
   topic = ,
   remark = ,
   uniqueID = , % to replace the many V sequences (bib)
   ref . struct = {
     curr = ,
     sem = ,
     kind = ,
   } ,
  }

\starray_def_from_keyval:nn {curricula}
  {
    self = ,
    name = ,
    text = ,
    sem.struct = {
      pos = ,
      self = ,
      name = ,
      class . struct = {
        name = ,
        kind = ,
        obs = ,
        pos = ,
        color = ,
        prereqset . struct = {
          prereq . struct = {
            starred = ,
            name = ,
            ang = ,
          }
        } ,
      } ,
    } ,
  }

\NewDocumentCommand{\currdef}{mmm}
  {
    \starray_new_term:nn {curricula}{#1}
    \starray_set_from_keyval:nn {curricula}
      {
        self = {#1} ,
        name = {#2} ,
        text = {#3} ,
      }
  }

\NewDocumentCommand{\semdef}{mmm}
  {
    \starray_new_term:nn {curricula.sem}{#1}
    \starray_set_from_keyval:nn {curricula.sem}
      {
        self       = {#1} ,
        name       = {#2} ,
        pos        = {#3} ,
      }
  }

\NewDocumentCommand{\addclass}{O{}D<>{}mmO{}}
  {
    \starray_new_term:nn {curricula.sem.class}{#3}
    \starray_set_from_keyval:nn {curricula.sem.class}
      {
        color = {#1} ,
        pos   = {#2} ,
        name  = {#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}{self} \l_tmpa_tl
    \starray_set_prop:nnV {classes.ref}{curr} \l_tmpa_tl
    \starray_get_prop:nnN {curricula.sem}{self} \l_tmpa_tl
    \starray_set_prop:nnV {classes.ref}{sem} \l_tmpa_tl
    \starray_set_prop:nnn {classes.ref}{kind}{#4}
  }

\NewDocumentCommand{\depdef}{sD<>{}m}
  {
    \starray_new_term:nn {curricula.sem.class.prereqset.prereq}{#3}
    \starray_set_from_keyval:nn {curricula.sem.class.prereqset.prereq}
      {
        starred = {#1} ,
        name = {#3} ,
        ang  = {#2}
      }
  }

\NewDocumentCommand{\altdep}{}
  {
    \starray_new_term:nn {curricula.sem.class.prereqset}{}
  }




\NewDocumentCommand\topicdef{O{}mm}
  {
    \starray_new_term:nn {topics}{#2}
    \starray_set_from_keyval:nn {topics}
      {
        self = {#2} ,
        name = {#3} ,
        color = {#1} ,
      }
    %% V-less : replacing / new seq
    \starray_get_unique_id:nNTF {topics}\l__ufrgscca_uniqueID_tmpa_tl
      {}
      {\tl_set:Nn \l__ufrgscca_uniqueID_tmpa_tl {}}
    \starray_set_prop:nnV {topics}{uniqueID} \l__ufrgscca_uniqueID_tmpa_tl
    \seq_new:c {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpa_tl _seq}
    
  }

\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}
      {
        self = {#2} ,
        cred = {#3} ,
        name = {#4} ,
        topic = {#1} ,
      }
  %% V-less : new
    \starray_get_unique_id:nNTF {classes}\l__ufrgscca_uniqueID_tmpb_tl
      {}
      {\tl_set:Nn \l__ufrgscca_uniqueID_tmpb_tl {}}
    \starray_set_prop:nnV {classes}{uniqueID} \l__ufrgscca_uniqueID_tmpb_tl
    \seq_new:c {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib _seq}
    \seq_new:c {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib basic _seq}
    \seq_new:c {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib compl _seq}
    

    \starray_set_iter_from_hash:nn {topics}{#1}
    %% V-less : new seq
    \starray_get_prop:nnN {topics}{uniqueID} \l__ufrgscca_uniqueID_tmpa_tl
    \seq_put_right:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpa_tl _seq} {#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}
  {
    %% V-less
    \starray_get_prop:nnN {classes}{uniqueID} \l__ufrgscca_uniqueID_tmpb_tl
    
    \str_case:nnF {#1}
      {
        {main}
          {
            %% V-less
            \seq_gput_right:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib _seq} {#2}
          }
        {basic}%{ \starray_get_prop:nnN {classes}{bib basic seq} \l_tmpa_seq }
          {
            %% V-less
            \seq_gput_right:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib basic _seq} {#2}
          }
        {compl}%{ \starray_get_prop:nnN {classes}{bib compl seq} \l_tmpa_seq }
          {
            %% V-less
            \seq_gput_right:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib compl _seq} {#2}
          }
      }
      {
            %% V-less
            \seq_put_right:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib _seq} {#2}
      }
  }

\NewDocumentCommand{\classset}{m}
  {
    \starray_set_iter_from_hash:nn {classes}{#1}
  }
\let\setclass\classset

%\NewDocumentCommand\xTabEtp{O{\notoc\section}m}{%

\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

\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}{name} \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:ne {classes}{\l__ufrgscca_tmp_class_tl}
        \starray_get_prop:nnN {classes}{name} \l__ufrgscca_tmp_name_tl
        \starray_get_prop:nnN {classes}{cred} \l__ufrgscca_tmp_cred_tl
        \tl_if_empty:NT \l__ufrgscca_tmp_color_tl
          {
            \tl_set:Nn \l__ufrgscca_tmp_color_tl {black}
          }

          %% 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}{name} \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]{~\ ~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}{topic} \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\\*}
               
        %% V-less
        \starray_get_prop:nnN {classes}{uniqueID} \l_tmpa_tl
        \tl_gset:Ne \l__ufrgscca_uniqueID_tmpb_tl {\l_tmpa_tl}

         %% bibliography I
        \seq_if_empty:cF {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib _seq}
          {                                     
            &  &  &   & \multicolumn{2}{J{11cm}}{\smaller\scshape Bibliografia~ Básica~ Essencial}\\*
            \seq_map_inline:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib _seq}
              {
                &  &  &   &  &  \smaller\textopenbullet  ~\ ~  ##1\\
              }
          }

         %% bibliography II
        \seq_if_empty:cF {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib basic _seq}
          {
            &  &  &   & \multicolumn{2}{J{11cm}}{\smaller\scshape Bibliografia~ Básica}\\*
            \seq_map_inline:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib basic _seq}
              {
                &  &  &   &  &  \smaller\textopenbullet  ~\ ~  ##1\\
              }
          }

         %% bibliography III
        \seq_if_empty:cF {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib compl _seq}
          {
           &  &  &   & \multicolumn{2}{J{11cm}}{\smaller\scshape Bibliografia~ Complementar}\\*
            \seq_map_inline:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpb_tl _bib compl _seq}
              {
                 &  &  &   &  &  \smaller\textopenbullet  ~\ ~  ##1\\
              }
          }
          \\[-1.5mm]
          }
      }
    \bool_if:nTF {#1}
      {
        \end{tabular}
      }
      {
        \end{longtable}
      }
}


\seq_new:N \l__ufrgscca_tmp_classlst_seq

\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

        %% V-less : to be replaced
            \starray_get_prop:nnN {topics}{uniqueID} \l__ufrgscca_uniqueID_tmpa_tl
             \seq_map_inline:cn {l__ufrgscca_curr_ \l__ufrgscca_uniqueID_tmpa_tl _seq} 
              {
                \starray_set_iter_from_hash:nn {classes}{##1}
                \starray_get_prop:nnN {classes}{name} \l__ufrgscca_tmp_name_tl
                \use:e { & ##1 & \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}{name} \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}{topic} \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}{name} \l__ufrgscca_tmp_prereq_name_tl
                    \starray_get_prop:nnN {curricula.sem.class.prereqset.prereq}{ang} \l__ufrgscca_tmp_ang_tl
                    \StrCut{\l__ufrgscca_tmp_ang_tl}{:}{\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_set:Nn \l__ufrgscca_angOUT_tl {0}
                            \tl_set:Nn \l__ufrgscca_angIN_tl {180}
                          }%didn't match
                      }
                      {
                        \tl_set:Nn \l__ufrgscca_angOUT_tl {\l__ufrgscca_partA_tl}
                        \tl_set:Nn \l__ufrgscca_angIN_tl {180-\l__ufrgscca_partB_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

      }

  }

