% \subsection{bitreport.cls 模板类}
%
% \subsubsection{全局变量与临时变量}
%
% \begin{variable}{\g_@@_thesis_type_int}
% 论文类型，取值从 1 开始，分别对应:
%  \begin{enumerate}
%      \item 课程实验报告
%      \item （计算机学院）本科生毕业（设计）开题报告（已废弃）
%  \end{enumerate}
%    \begin{macrocode}
\int_new:N \g_@@_report_type_int
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\c_@@_report_type_clist}
% 定义报告类型的列表。
%    \begin{macrocode}
\clist_const:Nn \c_@@_report_type_clist
    { common, undergraduate_proposal}
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_right_seq,\l_@@_left_seq}
% 临时变量。
%    \begin{macrocode}
\seq_new:N \l_@@_right_seq
\seq_new:N \l_@@_left_seq
%    \end{macrocode}
% \end{variable}
%
% 手动开启伪粗体、伪斜体。
%    \begin{macrocode}
\PassOptionsToPackage{AutoFakeBold,AutoFakeSlant}{xeCJK}
%    \end{macrocode}
%
% \subsubsection{l3keys 接口键值对定义}
%
% 定义 |bitreport| 模板类的键值对。
%    \begin{macrocode}
\keys_define:nn { bitreport }
  {
    option .meta:nn = {bitreport / option } {#1},
    cover .meta:nn = { bitreport / cover  } {#1},
    info .meta:nn = { bitreport / info } {#1},
    misc .meta:nn = { bitreport / misc } {#1}
  }
%    \end{macrocode}
%
% 定义 |bitreport/option| 模板类的键值对。
%    \begin{macrocode}
\keys_define:nn { bitreport / option }
  {
    type .choice:,
    type .value_required:n = true,
    type .choices:Vn =
      \c_@@_report_type_clist
      {
        \int_set_eq:NN \g_@@_report_type_int \l_keys_choice_int
      },
    type .initial:n = common,
    ctex .tl_set:N = \l_@@_options_to_ctex_tl,
  }
%    \end{macrocode}
%
% 定义 |bitreport/cover| 模板类的键值对。
%    \begin{macrocode}
\keys_define:nn { bitreport / cover }
  {
    imagePath .tl_set:N = \l_bit_coverimagepath_tl,
    date .tl_set:N = \l_@@_cover_date_tl,
    %% cover entry
    delimiter .tl_set:N = \l_@@_cover_delimiter_tl,
    labelAlign .tl_set:N = \l_@@_cover_label_align_tl,
    labelAlign .initial:n = {r},
    valueAlign .tl_set:N = \l_@@_cover_value_align_tl,
    valueAlign .initial:n = {c},
    labelMaxWidth .dim_set:N = \l_@@_cover_label_max_width_dim,
    valueMaxWidth .dim_set:N = \l_@@_cover_value_max_width_dim,
    autoWidthPadding .dim_set:N = \l_@@_cover_auto_width_padding_dim,
    autoWidthPadding .initial:n = {0.25em},
    autoWidth .bool_set:N = \l_@@_cover_auto_width_bool,
    autoWidth .initial:n = {true},
    underlineThickness .dim_set:N = \l_@@_cover_underline_thickness_dim,
    underlineThickness .initial:n = {1pt},
    underlineOffset .dim_set:N = \l_@@_cover_underline_offset_dim,
    underlineOffset .initial:n = { -10pt },
  }
%    \end{macrocode}
%
% 定义 |bitreport/info| 模板类的键值对。
%    \begin{macrocode}
\keys_define:nn { bitreport / info }
  {
    title .tl_set:N = \l_@@_value_title_tl,
    school .tl_set:N = \l_@@_value_school_tl,
    major .tl_set:N = \l_@@_value_major_tl,
    class .tl_set:N = \l_@@_value_class_tl,
    author .tl_set:N = \l_@@_value_author_tl,
    supervisor .tl_set:N = \l_@@_value_supervisor_tl,
    externalSupervisor .tl_set:N = \l_@@_value_external_supervisor_tl,
    studentId .tl_set:N = \l_@@_value_student_id_tl,
  }
%    \end{macrocode}
%
% 定义 |bitreport/misc| 模板类的键值对。
%    \begin{macrocode}
\keys_define:nn { bitreport / misc }
  {
    reviewTable .tl_set:N = \l_bit_reviewtable_tl,
  }
%    \end{macrocode}
%
% 将 |bithesis/option/ctex| 中的值传递给 ctexbook 模板类。
%    \begin{macrocode}
\DeclareOption*{
  \PassOptionsToClass{\l_@@_options_to_ctex_tl}{ctexart}
}
%    \end{macrocode}
%
% 加载 ctexbook 模板类。
%    \begin{macrocode}
\ProcessOptions\relax
\LoadClass[zihao=-4]{ctexart}
%    \end{macrocode}
%
% \subsubsection{定义模板类样式}
% 加载所需的宏包。
%    \begin{macrocode}
\RequirePackage[a4paper,left=3cm,right=2.4cm,top=2.6cm,bottom=2.38cm,includeheadfoot]{geometry}
\RequirePackage{fancyhdr}
\RequirePackage{setspace}
\RequirePackage{caption}
\RequirePackage{booktabs}
\RequirePackage{pdfpages}
%    \end{macrocode}
%
% 在宏加载时，处理 |bitreport/option| 中的值。使得 |bitreport|
% 宏包的模板选项可以在宏加载时生效。
%    \begin{macrocode}
\ProcessKeysOptions { bitreport / option }
%    \end{macrocode}
%
% \subsubsection{辅助函数与常量}
%
% \begin{macro}{\tl_if_empty:xTF,\seq_set_split:Nnx}
% 生成变体。
%    \begin{macrocode}
\cs_generate_variant:Nn \tl_if_empty:nTF {x}
\cs_generate_variant:Nn \seq_set_split:Nnn {Nnx}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_dunderline:nnn}
% 用于渲染下划线。
%
% 参数如下：
% \begin{itemize}
%   \item \#1 |dim| 线的竖直偏移量，例如 |-10pt|。
%   \item \#2 |dim| 线宽（粗细），例如 |1pt|。
%   \item \#3 |tl| 文字内容。
% \end{itemize}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_dunderline:nnn #1#2#3 {
  {\setbox0=\hbox{#3}\ooalign{\copy0\cr\rule[\dimexpr#1-#2\relax]{\wd0}{#2}}}
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{|@@_render_cover_entry:nn}
% 用于渲染封面的辅助函数。
%
% 参数如下：
% \begin{itemize}
%   \item \#1 |{token_list}| 为封面信息条目的名称，含分隔符。
%   \item \#2 |{token_list}| 为封面信息条目的内容。
% \end{itemize}
%
% 需要在 |\l_@@_cover_label_max_width_dim| 和 |\l_@@_cover_value_max_width_dim|
% 存储已经计算出来的最大宽度。
%    \begin{macrocode}
\cs_new_protected:Npn \@@_render_cover_entry:nn #1#2 {
  \makebox[\l_@@_cover_label_max_width_dim][\l_@@_cover_label_align_tl]{
    \tl_if_blank:VTF #1 {} {#1}
  }
  \hspace{1ex}
  \@@_dunderline:nnn{\l_@@_cover_underline_offset_dim}{\l_@@_cover_underline_thickness_dim}{
    \makebox[\l_@@_cover_value_max_width_dim][\l_@@_cover_value_align_tl]{#2}
  }\par
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{|@@_get_text_width:Nn,\@@_get_text_width:NV}
% 计算 \#2 所占用的宽度，将结果存储在 \#1 中。
%
% 参数如下：
% \begin{itemize}
%   \item \#1 |dim| 存储宽度的变量。
%   \item \#2 |tl| 要计算宽度的文本。
% \end{itemize}
%    \begin{macrocode}
% Get text with from #2, then set to #1.
\cs_new_protected:Npn \@@_get_text_width:Nn #1#2
  {
    \hbox_set:Nn \l_tmpa_box {#2}
    \dim_set:Nn #1 { \box_wd:N \l_tmpa_box }
  }
\cs_generate_variant:Nn \@@_get_text_width:Nn { NV }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_get_max_text_width:NN}
% 从 \#2 中获取最大的文本宽度，然后设置到 \#1 中。
%
% 参数如下：
% \begin{itemize}
%   \item \#1: |dim| 用于输出最大宽度。
%   \item \#2: |seq| 用于输入存储文本。
% \end{itemize}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_get_max_text_width:NN #1#2
  {
% 这里用 |group| 确保局部变量不会被污染。
    \group_begin:
      \seq_set_eq:NN \l_@@_tmpa_seq #2
      \dim_zero_new:N \l_@@_tmpa_dim
      \bool_until_do:nn { \seq_if_empty_p:N \l_@@_tmpa_seq }
        {
          \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_tmpa_tl
          \@@_get_text_width:NV \l_@@_tmpa_dim \l_@@_tmpa_tl
          \dim_gset:Nn #1 { \dim_max:nn {#1} { \l_@@_tmpa_dim } }
        }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_parse_entry:nn}
% 解析封面信息条目，丢弃空项，并添加分隔符。
%
% 参数如下：
% \begin{itemize}
%   \item \#1: |tl| 为封面信息条目的名称。
%   \item \#2: |tl| 为封面信息条目的内容。
% \end{itemize}
% |\\| 会被视为换行符，从而实现信息条目换行的效果。
%
% 结果会存储到 |\l_@@_tmp_left_seq| 和 |\l_@@_tmp_right_seq|。
%
%    \begin{macrocode}
\cs_new_protected:Npn \@@_parse_entry:nn #1 #2 {
  \seq_clear:N \l_@@_tmp_left_seq
  \seq_clear:N \l_@@_tmp_right_seq

  % 只处理 value 非空的项
  \tl_set:Nn \l_tmpa_tl {#2}
  \tl_if_empty:xTF {\l_tmpa_tl} {} {
    \seq_set_split:Nnx \l_@@_tmp_right_seq {\\} {#2}
    \seq_map_inline:Nn \l_@@_tmp_right_seq {
      \seq_put_right:Nn \l_@@_tmp_left_seq {}
    }
    \seq_put_left:Nn \l_@@_tmp_left_seq {#1\l_@@_cover_delimiter_tl}
    \seq_pop_right:NN \l_@@_tmp_left_seq \g_@@_trashcan_tl
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_render_cover_entry}
% 渲染封面信息项。此函数为主函数。
%    \begin{macrocode}
\cs_new_protected:Npn \@@_render_cover_entry:n #1 {
  % 左边是标签，右边是值。
  % 形如：
  % { {label_1} {value_1}, {label_2} {value 2} }
  % 首先转换成 seq 类型。
  \seq_set_from_clist:NN \l_@@_input_seq #1
  \seq_map_inline:Nn \l_@@_input_seq {
    % 然后对于每一对 label 和 value，首先查找
    % value 中是否含有 \\ 字符，如果有，则将其分割成多个
    % label - value 对。
    % 比如 {label_1} {value \\ 1} 会被转换成
    % { {label_1} {value}, {} {1} }
    \@@_parse_entry:nn ##1
    % 然后将这些 label - value 对添加到 \l_@@_right_seq
    % 或者 \l_@@_left_sql 中。
    % left 就是 label，right 就是 value。
    \seq_concat:NNN \l_@@_right_seq \l_@@_right_seq \l_@@_tmp_right_seq
    \seq_concat:NNN \l_@@_left_seq \l_@@_left_seq \l_@@_tmp_left_seq
  }

  % 如果用户选择自动计算最大宽度，则计算最大宽度。
  \bool_if:NT \l_@@_cover_auto_width_bool {
    \@@_get_max_text_width:NN \l_@@_cover_label_max_width_dim \l_@@_left_seq
    \@@_get_max_text_width:NN \l_@@_cover_value_max_width_dim \l_@@_right_seq
    % 在 value 两边加上空白，避免文本太靠边。
    \dim_add:Nn \l_@@_cover_value_max_width_dim { \l_@@_cover_auto_width_padding_dim * 2 }
  }


  % 最后，根据宽度渲染 label 和 value 对。
  \group_begin:
    \bool_until_do:nn { \seq_if_empty_p:N \l_@@_left_seq }
      {
        \seq_pop_left:NN \l_@@_left_seq \l_@@_tmpa_tl
        \seq_pop_left:NN \l_@@_right_seq \l_@@_tmpb_tl
        \@@_render_cover_entry:nn {\l_@@_tmpa_tl} {\l_@@_tmpb_tl}
      }
  \group_end:
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{定义用户接口}
%
% \begin{macro}{\BITSetup}
% 提供用户配置的接口。
%    \begin{macrocode}
\DeclareDocumentCommand \BITSetup { m }
  { \keys_set:nn { bitreport } { #1 }}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\MakeCover}
% 渲染封面。
%    \begin{macrocode}
\DeclareDocumentCommand \MakeCover {}
  {
    \group_begin:
    \int_case:nn {\g_@@_report_type_int} {
      {1} {
        \begin{titlepage}
          \centering

          \vspace{23mm}

          \tl_if_empty:NF \l_bit_coverimagepath_tl {
            \includegraphics[width=.5\textwidth]{\l_bit_coverimagepath_tl}\\
          }

          \vspace{10mm}

          \heiti\fontsize{24pt}{24pt}\selectfont{\l_@@_value_title_tl}\\

          \vspace{67mm}

          \begin{spacing}{2.2}
            \songti\zihao{3}

            \clist_set:Nn \l_@@_input_clist {
                {\textbf{学\qquad 院：}} {\l_@@_value_school_tl},
                {\textbf{专\qquad 业：}} {\l_@@_value_major_tl},
                {\textbf{班\qquad 级：}} {\l_@@_value_class_tl},
                {\textbf{学\qquad 号：}} {\l_@@_value_student_id_tl},
                {\textbf{姓\qquad 名：}} {\l_@@_value_author_tl},
                {\textbf{任课教师：}} {\l_@@_value_supervisor_tl},
            }

            \@@_render_cover_entry:n \l_@@_input_clist

          \end{spacing}

          \vspace*{\fill}

          \centering

          \songti\fontsize{12pt}{12pt}\selectfont{
            \tl_if_empty:NTF \l_@@_cover_date_tl {
              \today
            } {
              \l_@@_cover_date_tl
            }
          }
        \end{titlepage}
      }
      {2} {
        % Main code for \MakeCover
        \begin{titlepage}
          \topskip=0pt
          \vspace*{-16mm}
          \centering
          \hspace{-6mm}
          \songti\fontsize{22pt}{22pt}
          \selectfont{北京理工大学}\par

          \vspace{13mm}

          \hspace{-6mm}
          \heiti\fontsize{24pt}{24pt}
          \selectfont{本科生毕业设计（论文）开题报告}\par

          \vspace{53mm}

          \begin{spacing}{2.2}
            \songti\zihao{3}
            \clist_set:Nn \l_@@_input_clist {
                {\textbf{学\qquad 院：}} {\l_@@_value_school_tl},
                {\textbf{专\qquad 业：}} {\l_@@_value_major_tl},
                {\textbf{班\qquad 级：}} {\l_@@_value_class_tl},
                {\textbf{姓\qquad 名：}} {\l_@@_value_author_tl},
                {\textbf{指导教师：}} {\l_@@_value_supervisor_tl},
                {\textbf{校外指导教师：}} {\l_@@_value_external_supervisor_tl},
            }

          \@@_render_cover_entry:n \l_@@_input_clist

          \end{spacing}

          \vspace*{\fill}

          \centering
          \hspace{-6mm}\songti\fontsize{12pt}{12pt}\selectfont{\today}

        \end{titlepage}
      }
    }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\MakeReviewTable}
% 渲染评阅表。
%    \begin{macrocode}
\DeclareDocumentCommand \MakeReviewTable {}
  {
    \group_begin:
      \begin{titlepage}
        \includepdf[pages=-]{\l_bit_reviewtable_tl}
      \end{titlepage}
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
% 定义 caption 字体为楷体
%    \begin{macrocode}
\DeclareCaptionFont{kaiticaption}{\kaishu \normalsize}
%    \end{macrocode}
%
% 设置图片的 caption 格式
%    \begin{macrocode}
\renewcommand{\thefigure}{\thesection-\arabic{figure}}
\captionsetup[figure]{font=small,labelsep=space,skip=10bp,labelfont=bf,font=kaiticaption}
%    \end{macrocode}
%
% 设置表格的 caption 格式
%    \begin{macrocode}
\renewcommand{\thetable}{\thesection-\arabic{table}}
\captionsetup[table]{font=small,labelsep=space,skip=10bp,labelfont=bf,font=kaiticaption}
%    \end{macrocode}
%
% 输出大写数字日期
%    \begin{macrocode}
\ctexset{today=big}
%    \end{macrocode}
%
% 将西文字体设置为 Times New Roman
%    \begin{macrocode}
\setromanfont{Times~New~Roman}
%    \end{macrocode}
%
% 设置文档标题深度
%    \begin{macrocode}
\setcounter{tocdepth}{3}
\setcounter{secnumdepth}{3}
%    \end{macrocode}
%
% 设置一级标题、二级标题格式。
%    \begin{macrocode}
% 一级标题：小三，宋体，加粗，段前段后各半行。
\ctexset{section={
  format={
    \raggedright \bfseries \songti \zihao{-3}
  },
  beforeskip = 24bp plus 1ex minus .2ex,
  afterskip = 24bp plus .2ex,
  fixskip = true,
  name = {,.\quad}
  }
}
% 二级标题：小四，宋体，加粗，段前段后各半行。
\ctexset{subsection={
  format = {
    \bfseries \songti \raggedright \zihao{4}
  },
  beforeskip = 24bp plus 1ex minus .2ex,
  afterskip = 24bp plus .2ex,
  fixskip = true,
  }
}
%    \end{macrocode}
%
% 页眉和页脚（页码）的格式设定。
%    \begin{macrocode}
\fancyhf{}
\int_case:nn {\g_@@_report_type_int} {
  {1} {
    \fancyhead[R]{
      \fontsize{10.5pt}{10.5pt}
      \selectfont{\l_@@_value_title_tl}
    }
  }
  {2} {
    \fancyhead[R]{
      \fontsize{10.5pt}{10.5pt}
      \selectfont{北京理工大学本科生毕业设计（论文）开题报告}
    }
  }
}
\fancyfoot[R]{\fontsize{9pt}{9pt}\selectfont{\thepage}}
\renewcommand{\headrulewidth}{1pt}
\renewcommand{\footrulewidth}{0pt}
%    \end{macrocode}
%
% 正文开始
%    \begin{macrocode}
\pagestyle{fancy}
\setcounter{page}{1}
%    \end{macrocode}
%
%    \begin{macrocode}
% 正文行距 22 磅
\cs_set:Npn \baselinestretch {1.53}
% 正文首行悬挂 1.02cm
% \setlength{\parindent}{1.02cm}
%    \end{macrocode}
