%
% Copyright (c) 2024 Kangwei Xia
% Released under the LaTeX Project Public License v1.3c License.
% Repository: https://gitee.com/xkwxdyy/exam-zh
%

\NeedsTeXFormat{LaTeX2e}

\RequirePackage{expl3}

\ProvidesExplPackage {exam-zh-math} {2024-02-15} {v0.2.1}
  {exam-zh math module}

\RequirePackage { tabularray }
\RequirePackage { varwidth }
\RequirePackage { graphicx }
\RequirePackage { filehook }
\file_if_exist:nT { wrapstuff.sty }
  {
    \RequirePackage { wrapstuff }
    \AtEndOfPackageFile* { exam-zh-choices }
      {
        \AddToHook { env / choices / before }
          { \wrapstuffclear }
      }
  }


\keys_define:nn { exam-zh }
  { calculations .meta:nn = { exam-zh / calculations } {#1} }

%% calculations ������ %%


% ��������������� label ���������
\str_new:N \l__examzh_calculations_figure_position_str
% coffin type ���������������
\str_new:N \l__examzh_calculations_coffin_align_str


\keys_define:nn { exam-zh / calculations }
  {
    % calculations ��������� label ������������������������������ index +  seq ��������� ##1 ��������������� index���
    index .int_set:N = \l__examzh_calculations_label_index_shift_int,
    % ������������������������������������������
    columns .int_set:N = \l__examzh_calculations_column_int,
    % ������������������������������������������������
    fig-pos .choices:nn =
      { top, above, bottom, below, left, right, left-top }
      { \str_set:Nx \l__examzh_calculations_figure_position_str { \l_keys_choice_tl } },
    % ���������������������������
    top-sep .skip_set:N = \l__examzh_calculations_top_sep_skip,
    % ���������������������������
    bottom-sep .skip_set:N = \l__examzh_calculations_bottom_sep_skip,
    % ���������������������������
    hsep .skip_set:N = \l__examzh_calculations_hsep_skip,
    % ���������������������������
    vsep .skip_set:N = \l__examzh_calculations_vsep_skip,
    % ������������������
    xshift .dim_set:N = \l__examzh_calculations_xshift_dim,
    hshift .dim_set:N = \l__examzh_calculations_xshift_dim,
    yshift .dim_set:N = \l__examzh_calculations_yshift_dim,
    vshift .dim_set:N = \l__examzh_calculations_yshift_dim,
    % label ������������
    label-xshift .dim_set:N = \l__examzh_calculations_label_xshift_dim,
    label-hshift .dim_set:N = \l__examzh_calculations_label_xshift_dim,
    label-yshift .dim_set:N = \l__examzh_calculations_label_yshift_dim,
    label-vshift .dim_set:N = \l__examzh_calculations_label_yshift_dim,
    % ������������
    align .choices:nn = 
      { t, m, b }
      { \str_set:Nx \l__examzh_calculations_coffin_align_str { \l_keys_choice_tl } }
  }
\keys_set:nn { exam-zh / calculations }
  {
    index        = 0,
    columns      = 2,
    fig-pos      = left-top,
    xshift       = 2em,
    hsep         = 2em,
    vsep         = 0pt,
    label-xshift = 0pt,
    align        = t,
    top-sep      = 1ex plus .5ex minus .5ex,
    bottom-sep   = 0pt,
  }

% item ��� index ��������������������� item���
\int_new:N \l__examzh_calculations_item_index_int
% ��������������� coffin ������ seq ���
\seq_new:N \l__examzh_calculations_store_seq
% ��������� seq ��� item ���
\int_new:N \l__examzh_calculations_store_seq_item_int
% ������������ tblr ������������
\tl_new:N \l__examzh_calculations_tblr_content_tl



% #1: ������ calculations
% #2: ��������������� tblr
\NewDocumentEnvironment { calculations } { O{ } +O{ } }
  {
    \group_begin:
      \RenewDocumentCommand \item { O{ } }
        { \__examzh_calculations_item:n {##1} }
      \int_set:Nn \l__examzh_calculations_item_index_int {0}
      \seq_clear:N \l__examzh_calculations_store_seq
      \tl_clear:N \l__examzh_calculations_tblr_content_tl
      \keys_set:nn { exam-zh / calculations } {#1}
  }
  {
      % ������������
        \unskip
      \end{varwidth}
      % \end{minipage}
      \hcoffin_set_end:
      % ������ label ��� figure
      \__examzh_calculations_coffin_join:
      % ������
      \__examzh_calculations_coffin_typeset:n {#2}
      % \par \int_use:N \l__examzh_calculations_item_index_int
    \group_end:
  }
% ������ label ��� figure
\cs_new:Npn \__examzh_calculations_coffin_join:
  {
    \int_step_inline:nn { \l__examzh_calculations_item_index_int }
      {
        \__examzh_calculations_coffin_join_position_set:n {##1}
        \seq_gput_right:Nn \l__examzh_calculations_store_seq
          {
            \__examzh_calculations_coffin_align_set:n {##1}
            \kern\l__examzh_calculations_hsep_skip
          }
      }
  }
\cs_new:Npn \__examzh_calculations_coffin_align_set:n #1
  {
    \str_case:Vn \l__examzh_calculations_coffin_align_str
      {
        {t} { \__examzh_calculations_coffin_align_set_t:n {#1} }
        {m} { \__examzh_calculations_coffin_align_set_m:n {#1} }
        {b} { \__examzh_calculations_coffin_align_set_b:n {#1} }
      }
  }
\cs_new:Npn \__examzh_calculations_coffin_align_set_t:n #1
  {
    \coffin_typeset:cnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n { #1 } _coffin }
      { l } { t }  % align = t
      { \l__examzh_calculations_xshift_dim } { \l__examzh_calculations_yshift_dim + 1em }
  }
\cs_new:Npn \__examzh_calculations_coffin_align_set_m:n #1
  {
    \coffin_typeset:cnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n { #1 } _coffin }
      { l } { vc }  % align = m
      { \l__examzh_calculations_xshift_dim } { \l__examzh_calculations_yshift_dim }
  }
\cs_new:Npn \__examzh_calculations_coffin_align_set_b:n #1
  {
    \coffin_typeset:cnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n { #1 } _coffin }
      { l } { b }   % align = b
      { \l__examzh_calculations_xshift_dim } { \l__examzh_calculations_yshift_dim }
  }
\cs_new:Npn \__examzh_calculations_coffin_join_position_set:n #1
  {
    \use:c { __examzh_calculations_coffin_join_position_set_ \l__examzh_calculations_figure_position_str :n } {#1}
  }
\cs_new:cpn { __examzh_calculations_coffin_join_position_set_left-top :n } #1
  {
    \coffin_join:cnncnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n {#1} _ coffin }
      { l } { t }
      { l__examzh_calculations_label_ \int_to_roman:n {#1} _ coffin }
      { r } { b }
      { \l__examzh_calculations_label_xshift_dim }
      { \l__examzh_calculations_label_yshift_dim -10.6pt}
  }
\cs_new:Npn \__examzh_calculations_coffin_join_position_set_top:n #1
  {
    \coffin_join:cnncnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n {#1} _ coffin }
      { hc } { b }
      { l__examzh_calculations_label_ \int_to_roman:n {#1} _ coffin }
      { hc } { t }
      { \l__examzh_calculations_label_xshift_dim }
      { \l__examzh_calculations_label_yshift_dim - 6pt }
  }
\cs_set_eq:NN 
  \__examzh_calculations_coffin_join_position_set_above:n 
  \__examzh_calculations_coffin_join_position_set_top:n
\cs_new:Npn \__examzh_calculations_coffin_join_position_set_bottom:n #1
  {
    \coffin_join:cnncnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n {#1} _ coffin }
      { hc } { t }
      { l__examzh_calculations_label_ \int_to_roman:n {#1} _ coffin }
      { hc } { b }
      { \l__examzh_calculations_label_xshift_dim }
      { \l__examzh_calculations_label_yshift_dim + 6pt }
  }
\cs_set_eq:NN 
  \__examzh_calculations_coffin_join_position_set_below:n 
  \__examzh_calculations_coffin_join_position_set_bottom:n
\cs_new:Npn \__examzh_calculations_coffin_join_position_set_left:n #1
  {
    \coffin_join:cnncnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n {#1} _ coffin }
      { l } { vc }
      { l__examzh_calculations_label_ \int_to_roman:n {#1} _ coffin }
      { r } { vc }
      { \l__examzh_calculations_label_xshift_dim - 6pt }
      { \l__examzh_calculations_label_yshift_dim }
  }
\cs_new:Npn \__examzh_calculations_coffin_join_position_set_right:n #1
  {
    \coffin_join:cnncnnnn
      { l__examzh_calculations_figure_ \int_to_roman:n {#1} _ coffin }
      { r } { vc }
      { l__examzh_calculations_label_ \int_to_roman:n {#1} _ coffin }
      { l } { vc }
      { \l__examzh_calculations_label_xshift_dim + 2pt }
      { \l__examzh_calculations_label_yshift_dim }
  }
\cs_new:Npn \__examzh_calculations_coffin_typeset:n #1
  {
    \__examzh_calculations_coffin_typeset_count:
    \seq_map_indexed_inline:Nn \l__examzh_calculations_store_seq
      % ##1: index
      % ##2: content
      {
        \int_compare:nNnTF { \int_mod:nn {##1} { \l__examzh_calculations_column_int } } = {0}
          {
            \tl_gput_right:Nn \l__examzh_calculations_tblr_content_tl 
              { ##2 \\[\l__examzh_calculations_vsep_skip] }
          }
          {
            \tl_gput_right:Nn \l__examzh_calculations_tblr_content_tl 
              { ##2 & }
          }
      }
    % ������ seq ��� item ��� column ��������������� column ��������������� &
    \int_compare:nNnT { \l__examzh_calculations_store_seq_item_int } > { \l__examzh_calculations_column_int }
      {
        \int_compare:nNnF { \l__examzh_calculations_item_num_mod_column_left_int } = { 0 }
          {
            \tl_gput_right:Nx \l__examzh_calculations_tblr_content_tl
              {
                \prg_replicate:nn { \l__examzh_calculations_item_num_mod_column_left_int -1 } {&}
              }
            % \int_use:N \l__examzh_calculations_item_num_mod_column_left_int
          }
      }
    \par 
    \vspace*{ \l__examzh_calculations_top_sep_skip }
    \noindent 
    % \centering
    % \SetTblrInner
    %   {
    %     rowsep = 4pt,
    %     % colsep = 0pt
    %   }
    \begin{tblr}
      [ expand = \l__examzh_calculations_tblr_content_tl ]
      {
        width = \linewidth,
        columns = 
          {
            l,
            leftsep = 0em,
            rightsep = 0pt,
          },
        rows = 
          {
            m,
            ht=\baselineskip,
            abovesep = 0pt,
            belowsep = 0pt,
          },
        stretch=0,
        #1
      }
      \l__examzh_calculations_tblr_content_tl
    \end{tblr}
    \vspace*{ \l__examzh_calculations_bottom_sep_skip }
    \par
  }
\int_new:N \l__examzh_calculations_item_num_mod_column_left_int
\cs_new:Npn \__examzh_calculations_coffin_typeset_count:
  {
    % ������ seq ������������
    \int_set:Nn \l__examzh_calculations_store_seq_item_int
      { \seq_count:N \l__examzh_calculations_store_seq }
    % seq ������������ column ���������column ��������� seq ������
    \int_compare:nNnTF { \l__examzh_calculations_store_seq_item_int } < { \l__examzh_calculations_column_int }
      { \int_set_eq:NN \l__examzh_calculations_column_int \l__examzh_calculations_store_seq_item_int }
      {
        % ������ \l__examzh_calculations_store_seq_item_int mod \l__examzh_calculations_column_int ��������������������� &
        \int_set:Nn \l__examzh_calculations_item_num_mod_column_left_int { \int_mod:nn { \l__examzh_calculations_store_seq_item_int } { \l__examzh_calculations_column_int } }
      }
  }

\cs_new:Npn \__examzh_calculations_item:n #1
  {
    % ���������������g ������������
    \int_gincr:N \l__examzh_calculations_item_index_int
    % ������ coffin
    \__examzh_calculations_item_new_coffin:
    % ������ label��������������������������������������������� gset���
    \hcoffin_gset:cn 
      { l__examzh_calculations_label_ \int_to_roman:n { \l__examzh_calculations_item_index_int } _coffin } 
      {
        % ������ index ��������������������������������������� index
        % ���\int_eval:n { \l__examzh_calculations_item_index_int + \l__examzh_calculations_label_index_shift_int - 1} ���
        % ������ \item ���[] ��������������������������� label ������
        % \tl_if_blank:nTF {#1} 
        %   {
        %     \box_move_up:nn  { 2.7pt } { \hbox{\__examzh_calculations_the_label:} }
        %     \space
        %     #1
        %   } 
        %   {
        %     \__examzh_calculations_the_label: #1
        %   }
        % \IfBooleanTF{#1}{#1 yes}{#1 no}
        % \IfNoValueTF{#1}
        %   {
        %     \dim_set:Nn \l__examzh_calculations_label_yshift_dim { 4pt }
        %   }{#1 yes}
      }
    % ������ figure
    \int_compare:nNnF { \l__examzh_calculations_item_index_int } = {1}
      {
          \unskip
          \end{varwidth}
          % \end{minipage}
        % ��������������� item ���������
        \hcoffin_set_end:
      }
    % ������
    \hcoffin_set:cw { l__examzh_calculations_figure_ \int_to_roman:n { \l__examzh_calculations_item_index_int } _coffin }
      % \begin{varwidth}{\hsize}
    % ������ columns ������������������
    \__examzh_calculations_item_varwidth_width_set:
      \begin{varwidth}{\l__examzh_calculations_item_varwidth_width_dim}
      % \begin{minipage}{8cm}
        \ignorespaces
        \makebox[0em]{\rule{0pt}{\baselineskip}}
        \__examzh_calculations_the_label:
  }
\dim_new:N \l__examzh_calculations_item_varwidth_width_dim
\cs_new:Npn \__examzh_calculations_item_varwidth_width_set:
  {
    \int_case:nnF { \l__examzh_calculations_column_int }
      {
        {1} { \dim_set:Nn \l__examzh_calculations_item_varwidth_width_dim {0.8 \textwidth} }
        {2} { \dim_set:Nn \l__examzh_calculations_item_varwidth_width_dim {0.3 \textwidth} }
        {3} { \dim_set:Nn \l__examzh_calculations_item_varwidth_width_dim {0.3 \textwidth} }
        {4} { \dim_set:Nn \l__examzh_calculations_item_varwidth_width_dim {0.2 \textwidth} }
      }
      { \dim_set:Nn \l__examzh_calculations_item_varwidth_width_dim { \hsize } }
  }

% ������ coffin
\cs_new:Npn \__examzh_calculations_item_new_coffin:
  {
    % ������������ coffin
    \coffin_if_exist:cF { l__examzh_calculations_figure_ \int_to_roman:n { \l__examzh_calculations_item_index_int } _coffin }
      { \coffin_new:c { l__examzh_calculations_figure_ \int_to_roman:n { \l__examzh_calculations_item_index_int } _coffin } }
    % ��� label ��� coffin
    \coffin_if_exist:cF { l__examzh_calculations_label_ \int_to_roman:n { \l__examzh_calculations_item_index_int } _coffin }
      { \coffin_new:c { l__examzh_calculations_label_ \int_to_roman:n { \l__examzh_calculations_item_index_int } _coffin } }
  }

\tl_new:N \l__examzh_calculations_counters_commands_set_tl

\keys_define:nn { exam-zh / calculations }
  {
    label .tl_set:N = \l__examzh_calculations_label_tl
  }
\keys_set:nn { exam-zh / calculations }
  {
    label = \arabic*
  }
  
\cs_new:Npn \__examzh_calculations_the_label:
  {
    \group_begin:
      % ������������������������������������
      \l__examzh_calculations_counters_commands_set_tl
      % ������������������ label
      \l__examzh_calculations_label_tl
    \group_end:
  }

\NewDocumentCommand \AddCalculationsCounter { m m }
  {
    % ���������������������
    \tl_put_right:Nn \l__examzh_calculations_counters_commands_set_tl
      { \__examzh_process_counter:NNn #1 #2 { calculations } }
    % ������������������������
    \cs_set_eq:cN { __examzh_calculations_save_ \cs_to_str:N #1 : } #2
    \cs_set_eq:cN { __examzh_calculations_save_ \cs_to_str:N #2 : } #2
  }

\AddCalculationsCounter \arabic \@arabic
\AddCalculationsCounter \alph   \@alph
\AddCalculationsCounter \Alph   \@Alph
\AddCalculationsCounter \roman  \@roman
\AddCalculationsCounter \Roman  \@Roman

\cs_new:Npn \__examzh_calculations_process_counter_aux:Nn #1#2
  {
    \tl_if_eq:nnTF {#2} { * }
      {
        % \Alph*
        \use:c { __examzh_calculations_save_ \cs_to_str:N #1 : }
          { \int_eval:n { \l__examzh_calculations_item_index_int + \l__examzh_calculations_label_index_shift_int } }
      }
      {
        % \Alph{...}
        \use:c { __examzh_calculations_save_ \cs_to_str:N #1 : }
          {#2}
      }
  }