*! exam2tex.ado Version 1.0.1 - 20 February 2026
*! Authors: Wu Lianghai, Hu Fangfang, Chen Liwen, Yang Lu, Wu Hanyan
*! Fixed question numbering alignment issue for English papers
capture program drop exam2tex
program define exam2tex, rclass
    version 14.0

    syntax [anything(name=filename)] [,       ///
            SUBject(string)                   /// Exam subject
            GRADE(string)                      /// Grade/Class information
            DATE(string)                        /// Exam date
            DURation(string)                     /// Exam duration
            TOTALPoints(string)                   /// Total points
            TEACHER(string)                        /// Teacher name
            LANGuage(string)                        /// Language (en/cn)
            HEADer(string)                           /// Custom header
            QUESTIONStart(numlist integer >=1 max=1)  /// Starting question number
            SECTions(numlist >0)                       /// Number of questions per section
            REPLACE                                     /// Replace existing file
            TEXEngine(string)                            /// LaTeX engine (pdflatex/xelatex/lualatex)
            COMPile                                     /// Automatically compile to PDF
            ]

    // Set defaults with LaTeX-safe values
    if "`filename'" == "" local filename "exam"
    if "`subject'" == "" local subject "Examination"
    if "`grade'" == "" local grade "Grade/Class: {\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_}"
    if "`date'" == "" local date "\today"
    if "`duration'" == "" local duration "120 minutes"
    if "`totalpoints'" == "" local totalpoints "100"
    if "`teacher'" == "" local teacher "Instructor: {\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_}"
    if "`language'" == "" local language "en"
    if "`questionstart'" == "" local questionstart 1
    if "`texengine'" == "" local texengine "pdflatex"

    // Validate language option
    if !inlist("`language'", "en", "cn") {
        display as error "Language must be either 'en' or 'cn'"
        exit 198
    }

    // Validate TeX engine
    if !inlist("`texengine'", "pdflatex", "xelatex", "lualatex") {
        display as error "TeX engine must be pdflatex, xelatex, or lualatex"
        exit 198
    }

    // Add .tex extension if not present
    if strpos("`filename'", ".") == 0 {
        local filename "`filename'.tex"
    }

    // Check if file exists
    capture confirm file "`filename'"
    if _rc == 0 & "`replace'" == "" {
        display as error "File `filename' already exists. Use replace option to overwrite."
        exit 602
    }

    // Open file for writing
    file open texfile using "`filename'", write text `replace'

    // Write LaTeX header
    file write texfile "% LaTeX Exam Template generated by exam2tex.ado" _n
    file write texfile "% Authors: Wu Lianghai, Hu Fangfang, Chen Liwen, Yang Lu, Wu Hanyan" _n
    file write texfile "% Date: 15Feb2026" _n
    file write texfile "% Subject: `subject'" _n
    file write texfile "% Grade: `grade'" _n
    file write texfile "%" _n _n

    // Document class and packages based on language
    if "`language'" == "en" {
        file write texfile "\documentclass[12pt,a4paper]{article}" _n
        file write texfile "\usepackage[english]{babel}" _n
    }
    else {
        file write texfile "\documentclass[12pt,a4paper]{ctexart}" _n
        file write texfile "\usepackage[fontset=windows]{ctex}" _n
    }

    // Common packages
    file write texfile "\usepackage{amsmath,amssymb,amsfonts}" _n
    file write texfile "\usepackage{geometry}" _n
    file write texfile "\usepackage{fancyhdr}" _n
    file write texfile "\usepackage{lastpage}" _n
    file write texfile "\usepackage{enumitem}" _n
    file write texfile "\usepackage{titlesec}" _n
    file write texfile "\usepackage{xcolor}" _n
    file write texfile "\usepackage{hyperref}" _n
    file write texfile "\usepackage{graphicx}" _n
    file write texfile "\usepackage{array}" _n
    file write texfile "\usepackage{booktabs}" _n
    file write texfile "\usepackage{tabularx}" _n _n

    // Page geometry
    file write texfile "\geometry{" _n
    file write texfile "    a4paper," _n
    file write texfile "    left=2.5cm," _n
    file write texfile "    right=2.5cm," _n
    file write texfile "    top=2.5cm," _n
    file write texfile "    bottom=2.5cm" _n
    file write texfile "}" _n _n

    // Hyperref setup
    file write texfile "\hypersetup{" _n
    file write texfile "    colorlinks=true," _n
    file write texfile "    linkcolor=blue," _n
    file write texfile "    urlcolor=blue," _n
    if "`language'" == "en" {
        file write texfile "    pdfauthor={Exam Generator}," _n
    }
    else {
        file write texfile "    pdfauthor={试卷生成器}," _n
    }
    file write texfile "    pdftitle={`subject'}" _n
    file write texfile "}" _n _n

    // Custom commands for exam - ensure LaTeX safety
    // Escape any underscores in user-provided strings
    local date_escaped = subinstr("`date'", "_", "\_", .)
    local subject_escaped = subinstr("`subject'", "_", "\_", .)
    local grade_escaped = subinstr("`grade'", "_", "\_", .)
    local duration_escaped = subinstr("`duration'", "_", "\_", .)
    local totalpoints_escaped = subinstr("`totalpoints'", "_", "\_", .)
    local teacher_escaped = subinstr("`teacher'", "_", "\_", .)

    file write texfile "\newcommand{\examdate}{`date_escaped'}" _n
    file write texfile "\newcommand{\examsubject}{`subject_escaped'}" _n
    file write texfile "\newcommand{\examgrade}{`grade_escaped'}" _n
    file write texfile "\newcommand{\examduration}{`duration_escaped'}" _n
    file write texfile "\newcommand{\exampoints}{`totalpoints_escaped'}" _n
    file write texfile "\newcommand{\examteacher}{`teacher_escaped'}" _n _n

    // Header and footer - with proper headheight to avoid warnings
    file write texfile "\setlength{\headheight}{14.5pt}" _n
    file write texfile "\pagestyle{fancy}" _n
    file write texfile "\fancyhf{}" _n
    file write texfile "\fancyhead[L]{\examsubject}" _n
    file write texfile "\fancyhead[C]{\examgrade}" _n
    file write texfile "\fancyhead[R]{\examdate}" _n
    file write texfile "\fancyfoot[C]{\thepage\ of \pageref{LastPage}}" _n
    file write texfile "\renewcommand{\headrulewidth}{0.4pt}" _n
    file write texfile "\renewcommand{\footrulewidth}{0.4pt}" _n _n

    // Custom header if provided - also escape underscores
    if "`header'" != "" {
        local header_escaped = subinstr("`header'", "_", "\_", .)
        file write texfile "`header_escaped'" _n _n
    }

    // Begin document
    file write texfile "\begin{document}" _n _n

    // Title section
    file write texfile "\begin{center}" _n
    file write texfile "    {\LARGE \textbf{\examsubject}}\\[0.5cm]" _n
    file write texfile "    {\large \examgrade}\\[0.3cm]" _n
    file write texfile "    \examdate\\[0.3cm]" _n
    file write texfile "    \textbf{Duration:} \examduration \hfill \textbf{Total Points:} \exampoints\\[0.3cm]" _n
    file write texfile "    \examteacher" _n
    file write texfile "\end{center}" _n
    file write texfile "\vspace{0.5cm}" _n _n

    // Instructions based on language
    file write texfile "\noindent" _n
    if "`language'" == "en" {
        file write texfile "\textbf{Instructions:}" _n
        file write texfile "\begin{itemize}[leftmargin=*]" _n
        file write texfile "    \item Please write your name and student ID clearly on the answer sheet." _n
        file write texfile "    \item Read each question carefully before answering." _n
        file write texfile "    \item Show all your work for partial credit." _n
        file write texfile "    \item Electronic devices are not permitted unless specified." _n
        file write texfile "\end{itemize}" _n
    }
    else {
        file write texfile "\textbf{考试说明：}" _n
        file write texfile "\begin{itemize}[leftmargin=*]" _n
        file write texfile "    \item 请在答题纸上清晰填写姓名和学号。" _n
        file write texfile "    \item 答题前请仔细阅读题目。" _n
        file write texfile "    \item 展示解题过程可获得部分分数。" _n
        file write texfile "    \item 除非特别说明，否则不得使用电子设备。" _n
        file write texfile "\end{itemize}" _n
    }
    file write texfile "\vspace{0.5cm}" _n _n

    // Generate sections
    local qnum = `questionstart'

    if "`sections'" != "" {
        tokenize `sections'
        local i = 1
        while "``i''" != "" {
            local num_questions = ``i''

            // Section header
            file write texfile "\section*{"
            if "`language'" == "en" {
                file write texfile "Section "
                if `i' == 1 file write texfile "A"
                else if `i' == 2 file write texfile "B"
                else if `i' == 3 file write texfile "C"
                else if `i' == 4 file write texfile "D"
                else if `i' == 5 file write texfile "E"
                else if `i' == 6 file write texfile "F"
                else if `i' == 7 file write texfile "G"
                else if `i' == 8 file write texfile "H"
                else if `i' == 9 file write texfile "I"
                else file write texfile "J"
                file write texfile " (``i'' questions)"
            }
            else {
                file write texfile "第"
                if `i' == 1 file write texfile "一"
                else if `i' == 2 file write texfile "二"
                else if `i' == 3 file write texfile "三"
                else if `i' == 4 file write texfile "四"
                else if `i' == 5 file write texfile "五"
                else if `i' == 6 file write texfile "六"
                else if `i' == 7 file write texfile "七"
                else if `i' == 8 file write texfile "八"
                else if `i' == 9 file write texfile "九"
                else file write texfile "十"
                file write texfile "部分 （``i''题）"
            }
            file write texfile "}" _n _n

            // Generate questions - Fixed: Added \noindent to ensure all question numbers are left-aligned
            forvalues j = 1/`num_questions' {
                file write texfile "\noindent\textbf{`qnum'. }" _n
                file write texfile "\vspace{0.3cm}" _n
                file write texfile "\hrule" _n
                file write texfile "\vspace{0.5cm}" _n
                local ++qnum
            }

            local ++i
        }
    }
    else {
        // Default single section with 5 questions
        file write texfile "\section*{"
        if "`language'" == "en" file write texfile "Questions"
        else file write texfile "试题"
        file write texfile "}" _n _n

        // Generate questions - Fixed: Added \noindent to ensure all question numbers are left-aligned
        forvalues j = 1/5 {
            file write texfile "\noindent\textbf{`qnum'. }" _n
            file write texfile "\vspace{0.3cm}" _n
            file write texfile "\hrule" _n
            file write texfile "\vspace{0.5cm}" _n
            local ++qnum
        }
    }

    // Optional blank space for additional questions
    file write texfile "\vspace{1cm}" _n
    file write texfile "\noindent\rule{\textwidth}{0.5pt}" _n
    file write texfile "\begin{center}" _n
    if "`language'" == "en" {
        file write texfile "\textbf{--- END OF EXAM ---}" _n
    }
    else {
        file write texfile "\textbf{--- 试卷完 ---}" _n
    }
    file write texfile "\end{center}" _n

    // End document
    file write texfile "\end{document}" _n

    // Close file
    file close texfile

    // Display success message
    display as result "Exam template successfully generated: `filename'"
    display as text "To compile to PDF, run: "
    display as input "    `texengine' `filename'"
    display as text "    `texengine' `filename' (run twice for correct references)"
    display as text ""
    display as text "Note: All underscores have been automatically escaped for LaTeX compatibility."

    // Optional automatic compilation
    if "`compile'" != "" {
        display as text "Compiling to PDF..."
        !`texengine' `filename'
        !`texengine' `filename'
        local pdfname = subinstr("`filename'", ".tex", ".pdf", 1)
        display as result "PDF generated: `pdfname'"
    }

    // Return information
    return local filename "`filename'"
    return local subject "`subject'"
    return local grade "`grade'"
    return local date "`date'"
    return local texengine "`texengine'"

end