% \iffalse meta-comment % ================================================== % exam-rtl.dtx – LaTeX Exam Package (RTL/Arabic) % Version: 1.0 % Date: 2026/08/20 % % Copyright (C) 2026 by Nadeer Aljaroudi % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3c of this license or (at your option) any later % version. % ================================================== % \fi % \iffalse %<*driver> \documentclass{ltxdoc} \usepackage{xcolor} \usepackage{tcolorbox} \tcbuselibrary{skins, breakable} \usepackage{enumitem} \usepackage[hyperindex=false]{hyperref} \hypersetup{colorlinks=true,linkcolor=blue} \EnableCrossrefs \RecordChanges \OnlyDescription % لا نعرض الكود في PDF \begin{document} \DocInput{exam-rtl.dtx} \end{document} % % \fi % \changes{v1.0}{2026/08/20}{Initial Arabic/RTL release} % \GetFileInfo{exam-rtl.dtx} % \title{^^A % \textsf{exam-rtl} --- An Arabic/RTL Exam Package\thanks{^^A % This file has version v1.0, dated 2026-08-20.}^^A % } % % \author{Nadeer Aljaroudi} % \date{2026-08-20} % % \maketitle % % \begin{abstract} % The \textsf{exam-rtl} package is the Arabic/RTL version of % \textsf{exam-ltr}. It provides a comprehensive framework for % creating professional exams in Arabic and Right-to-Left (RTL) % languages. It supports a wide variety of question types, % including Multiple Choice, True/False, Fill in the Blank, % Ordering, Matching, Essay, Short Answer, and Reading Passages. % % Key features include automatic answer key generation, controlled % randomization of options and matching items, and full support for % RTL text alignment and Eastern Arabic numerals. % \end{abstract} % % \tableofcontents % % \section{Introduction} % % The \textsf{exam-rtl} package is the Arabic/RTL version of \textsf{exam-ltr}. % It provides a clean and robust environment for building professional exams % without manual formatting. Built with educators in mind, it allows you to % focus on creating high-quality question content while the package handles % question layout and RTL alignment automatically. % % \medskip % \textbf{Key features:} % \begin{itemize} % \item \textbf{8 Dedicated Question Types}: MC, TF, FillBlank, Ordering, % Matching, Essay, ShortAnswer, and ReadingPassage. % \item \textbf{Automated Answer Keys}: Answers are collected and displayed % directly after each question in teacher mode. % \item \textbf{Smart Randomization}: Shuffles options, matching columns, % and ordering items in a reproducible manner. % \item \textbf{Metadata Display}: Show or hide marks, difficulty levels, % and question type tags. % \item \textbf{Dual-Mode Output}: Switch between student version (answers % hidden) and teacher version (answers shown). % \item \textbf{Arabic Support}: RTL text alignment and Eastern Arabic numerals. % \end{itemize} % % \section{Requirements} % % \begin{itemize} % \item \textbf{LaTeX engine}: XeLaTeX (PDFLaTeX and LuaLaTeX are \textbf{not} supported) % \item \textbf{Fonts}: IBM Plex Sans Arabic (default) – ensure it is installed on your system % \item \textbf{Required packages} (loaded automatically): % \texttt{xcolor}, \texttt{tcolorbox}, \texttt{fontspec}, % \texttt{polyglossia}, \texttt{bidi}, \texttt{expl3}, \texttt{xparse} % \end{itemize} % % \section{Installation} % % The \texttt{exam-rtl} package is distributed through CTAN and is included % in all major LaTeX distributions (TeX Live, MiKTeX, MacTeX). In most cases, % no manual installation is needed; the system's package manager will handle % it automatically. % % If manual installation is required, use one of the following methods. % % \subsection*{Quick Installation (Single Project)} % % \begin{enumerate} % \item Place \texttt{exam-rtl.sty} in the same folder as your \texttt{.tex} file. % \item Add \texttt{\textbackslash usepackage\{exam-rtl\}} to your preamble. % \end{enumerate} % % \subsection*{Permanent Installation (All Projects)} % % \subsubsection*{Linux / macOS} % \begin{enumerate} % \item Create the target directory:\\ % \texttt{mkdir -p \~{}/texmf/tex/latex/exam-rtl} % % \item Copy the package file into this directory:\\ % \texttt{cp exam-rtl.sty \~{}/texmf/tex/latex/exam-rtl/} % % \item Update the LaTeX file database:\\ % \texttt{texhash \~{}/texmf} % \end{enumerate} % % \subsubsection*{Windows} % % \paragraph*{MiKTeX:} % \begin{enumerate} % \item Create the folder: % \texttt{C:\textbackslash texmf\textbackslash tex\textbackslash latex\textbackslash exam-rtl} % \item Copy \texttt{exam-rtl.sty} into it. % \item Refresh the database via the MiKTeX Console ``Refresh FNDB''. % \end{enumerate} % % \paragraph*{TeX Live:} % \begin{enumerate} % \item Create the folder: % \texttt{C:\textbackslash texlive\textbackslash texmf-local\textbackslash tex\textbackslash latex\textbackslash exam-rtl} % \item Copy \texttt{exam-rtl.sty} into it. % \item Refresh the database by running \texttt{texhash}. % \end{enumerate} % % \section{Quick Start} % % This section outlines the standard workflow for creating an exam with % the \texttt{exam-rtl} package. % % \subsection*{Step 1: Load the Package and Configure Mode} % % Include the package in your document preamble and set the desired output % mode: % % \begin{flushleft}\ttfamily % \cs{documentclass}\{article\}\\ % \cs{usepackage}\{exam-rtl\}\\[1em] % % \cs{TeacherMode} \quad \% Show answer keys\\[1em] % % \cs{ShowMarks} \quad \% Display marks\\ % \cs{ShowCorrection} \quad \% Show answer boxes\\ % \cs{ExamID}\{123\} \quad \% Fix randomization seed % \end{flushleft} % % \subsection*{Step 2: Structure Your Questions} % % Wrap every question in the \texttt{Question} environment. You must % specify four arguments: \meta{Type}, \meta{Difficulty}, \meta{Marks}, % and \meta{Question text}: % % \begin{flushleft}\ttfamily % \cs{begin}\{Question\}\marg{Type}\marg{Difficulty}\marg{Marks}\marg{Question text}\\ % \hspace*{2em}\textit{question content}\\ % \cs{end}\{Question\} % \end{flushleft} % % \subsection*{Step 3: Choose the Environment for Your Question} % % Inside the \texttt{Question} environment, select the environment that % matches your question type: \texttt{MC} (Multiple Choice), \texttt{TF} % (True/False), \texttt{FillBlank}, \texttt{Ordering}, \texttt{Matching}, % \texttt{Essay}, \texttt{ShortAnswer}, or \texttt{ReadingPassage}. % % \subsection*{Step 4: Compile and View Output} % % Compile your document with \texttt{xelatex}. The output depends on the % mode set in Step 1: % % \begin{itemize} % \item \textbf{Student Mode (default):} Answer keys are hidden. % \item \textbf{Teacher Mode:} Answer keys appear only when % \cs{ShowCorrection} is also enabled. % \end{itemize} % % For complete examples in Arabic, please refer to the % \texttt{exam-rtl-doc.tex} file included with the package. % % \section{Mode Commands} % % The package provides several switches that control the appearance of % the final exam sheet. These switches allow you to toggle between student % and teacher views, display metadata, and show answer boxes. % % \subsection*{Student and Teacher Modes} % % \DescribeMacro{\StudentMode} % \DescribeMacro{\TeacherMode} % These commands toggle between student and teacher views. % % \begin{flushleft}\ttfamily % \cs{StudentMode} \quad \% Hide answer keys (default)\\ % \cs{TeacherMode} \quad \% Show answer keys % \end{flushleft} % % The default mode is \cs{StudentMode}. When \cs{TeacherMode} is active, % answer keys become visible. % % \subsection*{Metadata Visibility} % % \DescribeMacro{\ShowMarks} % \DescribeMacro{\ShowDifficulty} % \DescribeMacro{\ShowType} % These commands control the visibility of question metadata. % % \begin{flushleft}\ttfamily % \cs{ShowMarks} \quad \% Display marks\\ % \cs{ShowDifficulty} \quad \% Display difficulty levels\\ % \cs{ShowType} \quad \% Display question type % \end{flushleft} % % Each switch is independent; any combination may be enabled. % % \subsection*{Correction Boxes} % % \DescribeMacro{\ShowCorrection} % Enables the display of correction boxes for teacher use. % % \begin{flushleft}\ttfamily % \cs{ShowCorrection} % \end{flushleft} % % Only takes effect when \cs{TeacherMode} is explicitly enabled. % % \subsection*{Randomization Seed} % % \DescribeMacro{\ExamID} % Sets a fixed seed for all randomization operations (shuffling MC options, % ordering items, and matching pairs). % % \begin{flushleft}\ttfamily % \cs{ExamID}\marg{number} % \end{flushleft} % % Using the same seed guarantees identical output across compilations. % % \section{Question Environment} % % \DescribeEnv{Question} % The Question environment is the primary container for all question % types. It handles automatic numbering, manages metadata display % (type, difficulty, marks), and integrates answer key collection % in teacher mode. % % \subsection*{Syntax} % % \begin{flushleft}\ttfamily % \cs{begin}\{Question\}\marg{Type}\marg{Difficulty}\marg{Marks}\marg{Question Text}\\ % \hspace*{2em}\textit{question content}\\ % \cs{end}\{Question\} % \end{flushleft} % % \subsection*{Arguments} % % \begin{itemize} % \item \meta{Type}: Question category (MC, TF, FillBlank, Ordering, % Matching, Essay, ShortAnswer, ReadingPassage). % \item \meta{Difficulty}: Descriptive label (e.g., Easy, Medium, Hard). % \item \meta{Marks}: Numeric score assigned to the question. % \item \meta{Question Text}: Main prompt or instruction. % \end{itemize} % % \subsection*{How It Works} % % \begin{itemize} % \item \textbf{Automatic Numbering:} Questions are numbered sequentially. % % \item \textbf{Metadata Display:} When enabled via \cs{ShowType}, % \cs{ShowDifficulty}, and \cs{ShowMarks}, the corresponding % labels are displayed alongside the question. % % \item \textbf{Answer Key Collection:} When \cs{TeacherMode} and % \cs{ShowCorrection} are enabled, all answers are collected % and displayed in a dedicated answer key box. % % \item \textbf{Consistent Formatting:} All question types placed % inside this environment share consistent spacing and layout. % \end{itemize} % % \section{Question Types} % % \subsection{Multiple Choice (MC)} % \DescribeEnv{MC} % \DescribeMacro{\MCQuestion} % \DescribeMacro{\MCOption} % The MC environment creates multiple-choice questions with automatically % shuffled options. Multiple questions can be placed inside a single % MC environment, each with its own set of options. The correct answer % is stored internally and appears in the answer key in teacher mode. % Options are displayed in a grid layout with a customizable number % of columns. % % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{MC\}\oarg{columns}\\ % \hspace*{2em}\cs{MCQuestion}\marg{question text}\marg{correct\_index}\\ % \hspace*{4em}\cs{MCOption}\marg{option 1}\\ % \hspace*{4em}\cs{MCOption}\marg{option 2}\\ % \hspace*{4em}\cs{MCOption}\marg{option 3}\\ % \hspace*{4em}...\\ % \cs{end}\{MC\} % \end{quote} % % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Column Layout (default: 4):} The optional \oarg{columns} argument % sets the number of columns for displaying options. % Any number can be used as long as it fits the page width. % \item \textbf{Correct Answer Index:} The \marg{correct\_index} % refers to the position of the correct option as written % (e.g., 1, 2, 3). This index is used internally to track % the correct answer after shuffling. % \item \textbf{Randomization:} All options inside \cs{MCQuestion} % are shuffled based on the global exam seed set by % \cs{ExamID}. This ensures reproducibility when a fixed % seed is provided. % \item \textbf{Answer Key Integration:} The correct answer is % collected automatically and displayed in the answer key % when \cs{TeacherMode} and \cs{ShowCorrection} are enabled. % \end{itemize} % % \subsection{True/False (TF)} % \DescribeEnv{TF} % \DescribeMacro{\TFQuestion} % The TF environment creates True/False questions. Multiple statements % can be placed inside a single TF environment, each with its own % correct answer. Two display styles are available: bracket style % (default) and options style, allowing flexibility for different % assessment needs. % % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{TF\}\oarg{style}\\ % \hspace*{2em}\cs{TFQuestion}\marg{statement}\marg{answer}\\ % \hspace*{2em}\cs{TFQuestion}\marg{statement}\marg{answer}\\ % \hspace*{2em}...\\ % \cs{end}\{TF\} % \end{quote} % % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Visual Style:} The optional \oarg{style} argument % selects the display format: % \begin{itemize} % \item \texttt{bracket} (default): Places an empty answer slot % \texttt{( )} after each statement. % \item \texttt{options}: Places ``True'' and ``False'' labels % to the right of each statement. % \end{itemize} % \item \textbf{Statement Input:} The \marg{statement} argument % receives the text that students must evaluate. % \item \textbf{Answer Specification:} The \marg{answer} argument % must contain either ``True'' or ``False''. % \item \textbf{Answer Key:} When \cs{TeacherMode} and % \cs{ShowCorrection} are enabled, the correct answers are % collected and displayed in the answer key. % \item \textbf{Multiple Questions:} Multiple \cs{TFQuestion} % commands can be placed sequentially within one TF environment. % \end{itemize} % % \subsection{Fill in the Blank (FillBlank)} % \DescribeEnv{FillBlank} % \DescribeMacro{\WordBank} % \DescribeMacro{\FillQuestion} % \DescribeMacro{\Blank} % The FillBlank environment creates fill-in-the-blank questions where % students complete sentences with appropriate words. It supports % single or multiple blanks per question and an optional word % bank to assist students during assessment. % % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{FillBlank\}\oarg{wordbank}\\ % \hspace*{2em}\cs{WordBank}\oarg{separator}\marg{word1, word2, ...}\\ % \hspace*{2em}\cs{FillQuestion}\marg{text with \cs{Blank}}\marg{answer}\\ % \hspace*{2em}...\\ % \cs{end}\{FillBlank\} % \end{quote} % % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Blank Creation:} The \cs{Blank} command creates an % underline field where students write their answers. % Its optional argument \oarg{width} sets the line length % (default: 15mm). % \item \textbf{Word Bank Activation:} The optional \oarg{wordbank} % argument controls whether a word bank is displayed. % Set to \texttt{true} to show a framed list of words % above the questions (default is \texttt{false}). % \item \textbf{Word Bank Configuration:} The \cs{WordBank} command % defines the vocabulary list. Words must be separated by commas. % The optional \oarg{separator} controls spacing between words % (default: \cs{quad}). % \item \textbf{Multiple Questions:} Multiple \cs{FillQuestion} % commands can be placed sequentially within one FillBlank environment. % \item \textbf{Answer Key:} When \cs{TeacherMode} and % \cs{ShowCorrection} are enabled, correct answers are % collected and displayed in a dedicated answer key box. % \end{itemize} % % \subsection{Ordering} % \DescribeEnv{Ordering} % \DescribeMacro{\OrderQuestion} % \DescribeMacro{\OrderOption} % \DescribeMacro{\OrderAnswer} % The Ordering environment creates sequencing questions where students % must arrange items in their correct logical order. Items must be % written in their proper sequence inside the environment, but are % presented to students in a shuffled layout. The original order % is preserved for the teacher's answer key. Options are displayed % in a grid layout with a customizable number of columns. % % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{Ordering\}\oarg{columns}\\ % \hspace*{2em}\cs{OrderQuestion}\marg{instruction}\\ % \hspace*{4em}\cs{OrderOption}\marg{item 1}\\ % \hspace*{4em}\cs{OrderOption}\marg{item 2}\\ % \hspace*{4em}\cs{OrderOption}\marg{item 3}\\ % \hspace*{4em}...\\ % \hspace*{2em}\cs{OrderAnswer}\oarg{width}\\ % \cs{end}\{Ordering\} % \end{quote} % % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Correct Sequence:} Items must be written inside % \cs{OrderOption} in their correct logical order. This order % is preserved for the answer key. % % \item \textbf{Randomization:} Items are shuffled for the student % based on the global exam seed (\cs{ExamID}), ensuring % consistent randomization across compilations. % % \item \textbf{Column Layout (default: 4):} The optional \oarg{columns} argument % sets the number of columns for displaying shuffled items. % Any number can be used as long as it fits the page width. % % \item \textbf{Answer Space:} The \cs{OrderAnswer} command adds % an optional answer space with customizable width (default: 5mm) where % students write their final ordered sequence. % % \item \textbf{Answer Key:} When \cs{TeacherMode} and % \cs{ShowCorrection} are enabled, the correct sequence is % collected and displayed in the answer key. % \end{itemize} % % \subsection{Matching} % \DescribeEnv{Matching} % \DescribeMacro{\MatchPair} % The Matching environment creates two-column association questions. % Items must be written in their correct pairs inside the environment. % The right column remains fixed and numbered, while the left column % is automatically shuffled for students. The original pairings % are preserved for the teacher's answer key. % % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{Matching\}\oarg{right\_ratio}\\ % \hspace*{2em}\cs{MatchPair}\marg{left item}\marg{right item}\\ % \hspace*{2em}\cs{MatchPair}\marg{left item}\marg{right item}\\ % \hspace*{2em}...\\ % \cs{end}\{Matching\} % \end{quote} % % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Pair Definition:} Each pair is defined using \cs{MatchPair}. % The order of definition determines the correct answer key. % The right column is fixed and numbered, while the left column % is automatically shuffled. % \item \textbf{Column Width Control:} The optional \oarg{right\_ratio} % adjusts the width of the right column as a decimal fraction % between 0 and 1. Default is 0.5 (equal split). This is useful % when the right column contains short terms and the left column % has lengthy descriptions (e.g., 0.3 for 30\% width). % \item \textbf{Randomization:} The left column is shuffled based on % the global exam seed (\cs{ExamID}), ensuring consistency % across compilations. % \item \textbf{Answer Key:} When \cs{TeacherMode} and % \cs{ShowCorrection} are enabled, the correct mappings are % displayed as numbered-to-lettered pairs. % \item \textbf{Capacity:} Supports a maximum of 28 pairs per question % (limited by Arabic alphabet). % \end{itemize} % % \subsection{Essay} % \DescribeEnv{Essay} % \DescribeMacro{\EssayQuestion} % The Essay environment creates open-ended, long-form written response % questions. It provides a writing area with either ruled lines or % blank space, depending on the selected style. The instructor's % answer summary is stored and displayed in the answer key in teacher % mode. % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{Essay\}\oarg{lines}\\ % \hspace*{2em}\cs{EssayQuestion}\oarg{line\_count}\marg{question}\marg{answer summary}\\ % \hspace*{2em}...\\ % \cs{end}\{Essay\} % \end{quote} % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Writing Space Style:} The optional environment argument % \oarg{lines} controls the appearance of the writing area: % \begin{itemize} % \item \texttt{true}: Generates ruled notebook lines (default). % \item \texttt{false}: Provides blank white space for free-form % text or diagrams. % \end{itemize} % \item \textbf{Writing Space Size (default: 4):} The optional \oarg{line\_count} % argument specifies the number of lines allocated for the % student's answer. % \item \textbf{Question Components:} \cs{EssayQuestion} command % takes two mandatory arguments: the question prompt and a % concise answer summary for the instructor's reference. % \item \textbf{Multiple Questions:} Multiple \cs{EssayQuestion} % commands can be placed sequentially within one Essay environment. % \item \textbf{Answer Key:} When \cs{TeacherMode} and % \cs{ShowCorrection} are enabled, all answer summaries are % collected and displayed in a dedicated answer key box. % \end{itemize} % % \subsection{Short Answer} % \DescribeEnv{ShortAnswer} % \DescribeMacro{\ShortQuestion} % The ShortAnswer environment creates questions that require brief, % direct responses — such as single words, short phrases, or concise % statements. The answer space can be customized (0, 1, or 2 lines) % to keep the exam layout clear and space-efficient. The instructor's % answer is stored and displayed in the answer key in teacher mode. % % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{ShortAnswer\}\oarg{lines}\\ % \hspace*{2em}\cs{ShortQuestion}\oarg{size}\marg{question}\marg{answer}\\ % \hspace*{2em}...\\ % \cs{end}\{ShortAnswer\} % \end{quote} % % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Writing Space Style:} The optional environment argument % \oarg{lines} controls the appearance of the answer space: % \begin{itemize} % \item \texttt{true}: Generates ruled notebook lines (default). % \item \texttt{false}: Provides blank white space without lines. % \end{itemize} % \item \textbf{Answer Space Size:} The optional \oarg{size} argument % specifies the number of lines for the student's answer: % \begin{itemize} % \item \texttt{0}: Prints a short underline directly after the % question text — ideal for single-word answers. % (Prints a line regardless of the environment style.) % \item \texttt{1}: Generates a one-line writing space below the % question. % \item \texttt{2}: Generates a two-line writing space below the % question. % \end{itemize} % % \item \textbf{Question Components:} \cs{ShortQuestion} command % takes two mandatory arguments: the question prompt and the % model answer or keyword solution. % % \item \textbf{Multiple Questions:} Multiple \cs{ShortQuestion} % commands can be placed sequentially within one ShortAnswer % environment. % % \item \textbf{Answer Key:} When \cs{TeacherMode} and % \cs{ShowCorrection} are enabled, all answers are collected % and displayed in a dedicated answer key box. % \end{itemize} % % \subsection{Reading Passage} % \DescribeEnv{ReadingPassage} % The ReadingPassage environment provides a container for reading % comprehension texts. The passage is printed exactly as written — % preserving all formatting, paragraph breaks, and inline styling — % without any modification or randomization. The passage is displayed % in a standalone box, and authors can place any question type after % it to assess comprehension. % % \subsubsection*{Syntax:} % \begin{quote}\ttfamily % \cs{begin}\{ReadingPassage\}\marg{title}\\ % \hspace*{2em}\textit{passage text}\\ % \cs{end}\{ReadingPassage\} % \end{quote} % % \subsubsection*{How It Works:} % \begin{itemize} % \item \textbf{Passage Rendering:} The text is displayed in a framed % box, exactly as entered, preserving all formatting. % \item \textbf{Title:} The mandatory \marg{title} argument sets the % centered heading above the passage. If left empty \{\}, % the default title ``Reading Passage'' is used. % \item \textbf{Content Flexibility:} The passage can include multiple % paragraphs, inline text styles (bold, italic, etc.), and % custom lists. % \item \textbf{Question Integration:} Any question type can follow % a ReadingPassage within the same \texttt{Question} block % to assess comprehension. % \end{itemize} % % \section{Complete Example} % % A fully functional sample exam file, \texttt{example.tex}, is included with % the package to demonstrate its capabilities in a realistic academic context. % The example file covers all question types supported by the package: % \texttt{MC}, \texttt{TF}, \texttt{Ordering}, \texttt{FillBlank}, % \texttt{Matching}, \texttt{ShortAnswer}, \texttt{Essay}, and % \texttt{ReadingPassage}. % % \medskip % \textbf{Usage Instructions:} % % \begin{enumerate} % \item Ensure you have the file \texttt{example.tex} in your working % directory (usually found in the package documentation folder). % % \item Open it in your \LaTeX{} editor and compile with \texttt{xelatex}. % % \item To switch between student and teacher views, uncomment or comment % the \cs{TeacherMode} and \cs{ShowCorrection} commands in the % preamble. This toggles the display of answer keys and correction % boxes. % \end{enumerate} % % \textbf{Note:} Arabic examples are provided in the \texttt{exam-rtl-doc.tex} % file included with the package. % % \section{Common Mistakes} % % The following list addresses frequent errors encountered during exam % creation. Adhering to these guidelines ensures correct compilation % and output. % % \begin{itemize} % \item \textbf{Enabling \cs{ShowCorrection} without \cs{TeacherMode}:} % \cs{ShowCorrection} alone does not display answers. Both % \cs{TeacherMode} and \cs{ShowCorrection} must be active for % solutions to appear. % % \item \textbf{Omitting the \texttt{Question} Environment:} % All question types must be wrapped inside the \texttt{Question} % environment. Failing to do so prevents metadata and answer keys % from appearing. % % \item \textbf{Using Invalid Type Identifiers:} % The first argument of \texttt{Question} must be a valid % identifier: \texttt{MC}, \texttt{TF}, \texttt{FillBlank}, % \texttt{Ordering}, \texttt{Matching}, \texttt{Essay}, % \texttt{ShortAnswer}, or \texttt{ReadingPassage}. Using % non-standard identifiers (e.g., \texttt{MCQ}) will result in % missing or incorrect metadata labels. % % \item \textbf{Using the Wrong Engine:} % This package requires XeLaTeX. PDFLaTeX and LuaLaTeX are not % supported due to the \texttt{bidi} package dependency. % % \item \textbf{Incorrect Column Placement in \texttt{Matching}:} % The \texttt{Matching} environment always shuffles the left % column. Items intended for randomization must be placed in % the first argument. % % \item \textbf{Incorrect Input Sequence in \texttt{Ordering}:} % The order in which you write the \cs{OrderOption} commands % in your document defines the correct answer. Entering them % in the wrong order will result in incorrect grading. % % \item \textbf{Omitting the Title in \texttt{ReadingPassage}:} % The \texttt{ReadingPassage} environment requires a title % argument. If no custom title is needed, use empty braces % \texttt{\{\}}. Omitting the argument causes LaTeX to misinterpret % the first character of the passage text as the title. % % \item \textbf{Font not installed:} The default font is IBM Plex Sans Arabic. % Ensure it is installed on your system. % \end{itemize} % % \section{Known Limitations} % % The \texttt{exam-rtl} package has the following limitations in its % current version. % % \begin{itemize} % \item \textbf{Directionality:} % The package is optimized for Right-to-Left (RTL) languages % (e.g., Arabic). For LTR support, use the companion package % \texttt{exam-ltr}. % % \item \textbf{Mandatory Randomization:} % Option shuffling cannot be fully disabled. Even without the % \cs{ExamID} macro, a default randomization is applied. % % \item \textbf{Scope of Randomization:} % Randomization is limited to internal elements: choices in % \texttt{MC}, items in \texttt{Ordering}, and the left-hand % column in \texttt{Matching}. Shuffling the entire sequence % of question blocks is not supported in this version. % % \item \textbf{Item Capacity:} % In \texttt{Ordering}, each question is limited to a maximum % of 28 options (items to order). In \texttt{Matching}, each % question is limited to a maximum of 28 pairs. Both limits % are due to the 28 Arabic letters used for labeling. % % \item \textbf{Short Answer Lines:} % Configuring more than 2 lines in the \texttt{ShortAnswer} % environment caps the display at 2. % % \item \textbf{Answer Key Placement:} % Answer keys are displayed individually beneath each question. % A centralized answer sheet at the end of the document is not % supported in this version. % \end{itemize} % % \section{License} % % This package is distributed under the LaTeX Project Public License (LPPL), % version 1.3c or later. % % The latest version of this license is available at: % \url{http://www.latex-project.org/lppl.txt} % % \section{Source Code} % % The complete source code of the \textsf{exam-rtl} package is included in this % \texttt{.dtx} file. To view the code: % % \begin{itemize} % \item Open \texttt{exam-rtl.dtx} in any text editor. % \item The code is located after the line: \verb|% \begin{macrocode}|. % \item To extract the package only: \texttt{latex exam-rtl.ins}. % \item The extracted \texttt{exam-rtl.sty} will preserve all Arabic text correctly. % \item This documentation does not include the source code to avoid % compilation issues with Arabic text. % \end{itemize} % % \StopEventually{^^A % \PrintChanges % % \PrintIndex % } % % \section{Implementation} % \iffalse %<*package> % \fi % \begin{macrocode} % ================================================== % exam-rtl.sty – Arabic/RTL Exam Package % Version: 1.0 % Date: 2026/08/20 % ================================================== \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{exam-rtl}[2026/08/20 v1.0 Arabic/RTL Exam Package] % -------------------------------------------------- % 1. Required Packages % -------------------------------------------------- \RequirePackage{xcolor} \RequirePackage{tcolorbox} \tcbuselibrary{all} \RequirePackage{fontspec} \RequirePackage{polyglossia} \RequirePackage{bidi} \RequirePackage{expl3} \RequirePackage{xparse} % -------------------------------------------------- % 2. Arabic Font Setup % -------------------------------------------------- \setmainlanguage{arabic} \setotherlanguages{english} \newfontfamily\arabicfont[Script=Arabic, BoldFont={* Medium}]{IBM Plex Sans Arabic} \newfontfamily\arabicfontsf[Script=Arabic, BoldFont={* Medium}]{IBM Plex Sans Arabic} \newfontfamily\arabicfonttt[Script=Arabic]{Cascadia Code-SemiLight} % -------------------------------------------------- % 3. Basic Macros % -------------------------------------------------- \newcommand{\ArNum}[1]{\textarabic{\arabicdigits{\number#1}}} \newcommand{\arbstrut}{\vrule height 1.15em depth 0.51em width 0pt} % -------------------------------------------------- % 4. Expl3 Setup % -------------------------------------------------- \ExplSyntaxOn \cs_generate_variant:Nn \tl_if_eq:nnT { VVT } \cs_generate_variant:Nn \prop_item:Nn { Nx } \cs_generate_variant:Nn \msg_warning:nnn { nnx } % -------------------------------------------------- % 5. Core Booleans % -------------------------------------------------- \bool_new:N \g__mode_teacher_bool \bool_new:N \g__mode_marks_bool \bool_new:N \g__mode_difficulty_bool \bool_new:N \g__mode_type_bool \bool_new:N \g__mode_correction_bool % -------------------------------------------------- % 6. Core Integers % -------------------------------------------------- \int_new:N \g__exam_id_int \int_new:N \g__question_number_int \int_new:N \g__question_seed_int % -------------------------------------------------- % 7. Core Token Lists % -------------------------------------------------- \tl_new:N \g__question_answer_tl \tl_new:N \g__question_type_tl \tl_new:N \g__question_level_tl \tl_new:N \g__question_marks_tl % -------------------------------------------------- % 8. Type Properties % -------------------------------------------------- \prop_new:N \g__question_type_prop \prop_put:Nnn \g__question_type_prop {MC} {اختيار~من~متعدد} \prop_put:Nnn \g__question_type_prop {TF} {صح~خطأ} \prop_put:Nnn \g__question_type_prop {FillBlank} {ملء~فراغ} \prop_put:Nnn \g__question_type_prop {Ordering} {ترتيب} \prop_put:Nnn \g__question_type_prop {Matching} {توصيل} \prop_put:Nnn \g__question_type_prop {Essay} {مقالي} \prop_put:Nnn \g__question_type_prop {ShortAnswer} {جواب~قصير} \prop_put:Nnn \g__question_type_prop {ReadingPassage} {قطعة~قراءة} % -------------------------------------------------- % 9. Letters Sequence (Arabic) % -------------------------------------------------- \seq_new:N \g_exam_letters_seq \seq_set_from_clist:Nn \g_exam_letters_seq { أ , ب , ج , د , هـ , و , ز , ح , ط , ي , ك , ل , م , ن , س , ع , ف , ص , ق , ر , ش , ت , ث , خ , ذ , ض , ظ , غ } % -------------------------------------------------- % 10. Mode Control Commands % -------------------------------------------------- \NewDocumentCommand{\StudentMode}{} { \bool_gset_false:N \g__mode_teacher_bool } \NewDocumentCommand{\TeacherMode}{} { \bool_gset_true:N \g__mode_teacher_bool } \NewDocumentCommand{\ShowMarks}{} { \bool_gset_true:N \g__mode_marks_bool } \NewDocumentCommand{\ShowDifficulty}{} { \bool_gset_true:N \g__mode_difficulty_bool } \NewDocumentCommand{\ShowType}{} { \bool_gset_true:N \g__mode_type_bool } \NewDocumentCommand{\ShowCorrection}{} { \bool_gset_true:N \g__mode_correction_bool } \NewDocumentCommand{\ExamID}{ m } { \tl_if_blank:nTF {#1} { \int_gset:Nn \g__exam_id_int {0} \sys_gset_rand_seed:n {0} } { \int_gset:Nn \g__exam_id_int {#1} \sys_gset_rand_seed:n {#1} } } % -------------------------------------------------- % 11. Seed Builder % -------------------------------------------------- \cs_new_protected:Npn \__question_build_seed: { \int_gset:Nn \g__question_seed_int { \int_eval:n { \g__exam_id_int * 1000 + \g__question_number_int } } \sys_gset_rand_seed:n { \g__question_seed_int } } \cs_new_protected:Npn \__subquestion_build_seed:n #1 { \sys_gset_rand_seed:n { \g__exam_id_int * 10000 + \g__question_number_int * 100 + #1 } } % -------------------------------------------------- % 12. Answer Box % -------------------------------------------------- \cs_new_protected:Npn \__exam_print_answer_box: { \par\smallskip \begin{tcolorbox}[ enhanced, breakable, colback=white, colframe=black, arc=0pt, outer~arc=0pt, boxrule=1pt, top=10pt, bottom=10pt, left=10pt, right=10pt, parbox=true, fontupper=\linespread{1.3}\selectfont, before~upper={\begin{flushright}}, after~upper={\end{flushright}}, coltitle=black, fonttitle=\bfseries, title={نموذج~الإجابة}, attach~boxed~title~to~top~right={ xshift=-5mm, yshift=-3mm, yshifttext=-1mm }, boxed~title~style={ colback=white, colframe=white, left=5pt, right=5pt } ]{ \setlength{\baselineskip}{1.2\normalbaselineskip} \tl_use:N \g__question_answer_tl } \end{tcolorbox} \par\smallskip } % -------------------------------------------------- % 13. Question Environment % -------------------------------------------------- \dim_new:N \g__question_number_width_dim \dim_new:N \g__question_metadata_width_dim \dim_new:N \g__question_text_width_dim \NewDocumentEnvironment{Question}{ m m m m } { \int_gincr:N \g__question_number_int \tl_gset:Nn \g__question_type_tl {#1} \tl_gset:Nn \g__question_level_tl {#2} \tl_gset:Nn \g__question_marks_tl {#3} \tl_gclear:N \g__question_answer_tl \__question_build_seed: \tl_clear:N \l_tmpa_tl \bool_if:nT { \g__mode_type_bool } { \tl_put_right:Nn \l_tmpa_tl { [\prop_item:Nn \g__question_type_prop {#1}] } } \bool_if:nT { \g__mode_difficulty_bool } { \tl_put_right:Nn \l_tmpa_tl { ~[#2] } } \bool_if:nT { \g__mode_marks_bool } { \tl_put_right:Nn \l_tmpa_tl { ~[#3~درجات] } } \settowidth{\g__question_metadata_width_dim} { \footnotesize \l_tmpa_tl } \settowidth{\g__question_number_width_dim} { \bfseries سؤال~\ArNum{\g__question_number_int}:~ } \dim_set:Nn \g__question_text_width_dim { \linewidth - \g__question_number_width_dim - \g__question_metadata_width_dim - 1em } \dim_compare:nNnT { \g__question_text_width_dim } < { 0pt } { \dim_set:Nn \g__question_text_width_dim { 0pt } } \par\medskip \noindent \makebox[\linewidth][r] { \makebox[\g__question_number_width_dim][r] { \bfseries سؤال~\ArNum{\g__question_number_int}:~ } \parbox[t]{\g__question_text_width_dim} { \setlength{\baselineskip}{1.3\normalbaselineskip} \bfseries #4 \par \vspace{0.01em} } \hfill { \footnotesize \bool_if:nT { \g__mode_type_bool } { [\prop_item:Nn \g__question_type_prop {#1}] } \bool_if:nT { \g__mode_difficulty_bool } { ~[#2] } \bool_if:nT { \g__mode_marks_bool } { ~[#3~درجات] } } } \par\smallskip } { \bool_if:nT { \g__mode_teacher_bool && \g__mode_correction_bool } { \tl_if_empty:NF \g__question_answer_tl { \__exam_print_answer_box: } } \par\medskip } % -------------------------------------------------- % 14. Multiple Choice (MC) % -------------------------------------------------- \int_new:N \l__mc_question_counter_int \int_new:N \l__mc_option_counter_int \int_new:N \l__mc_columns_int \int_new:N \l__mc_correct_index_int \seq_new:N \l__mc_options_seq \tl_new:N \l__mc_question_text_tl \dim_new:N \l__mc_label_width_dim \dim_new:N \l__mc_label_sep_dim \dim_new:N \l__mc_col_sep_dim \dim_new:N \l__mc_text_width_dim \dim_set:Nn \l__mc_label_width_dim { 1.5em } \dim_set:Nn \l__mc_label_sep_dim { 0.8em } \dim_set:Nn \l__mc_col_sep_dim { 1.5em } \dim_new:N \l__mc_before_first_question_dim \dim_new:N \l__mc_after_question_text_dim \dim_new:N \l__mc_between_questions_dim \dim_new:N \l__mc_after_options_dim \dim_new:N \l__mc_between_option_lines_dim \dim_set:Nn \l__mc_before_first_question_dim { 0.5em } \dim_set:Nn \l__mc_after_question_text_dim { 0.3em } \dim_set:Nn \l__mc_between_questions_dim { 0.1em } \dim_set:Nn \l__mc_after_options_dim { 0.3em } \dim_set:Nn \l__mc_between_option_lines_dim { 0.3em } \NewDocumentEnvironment{MC}{ O{4} } { \int_set:Nn \l__mc_columns_int {#1} \int_zero:N \l__mc_question_counter_int \int_zero:N \l__mc_option_counter_int \par } { \int_compare:nNnT { \l__mc_option_counter_int } > { 0 } { \__mc_display_options: } \par } \NewDocumentCommand{\MCQuestion}{ m m } { \int_compare:nNnT { \l__mc_option_counter_int } > { 0 } { \__mc_display_options: \par\vspace{\l__mc_after_options_dim} } \int_incr:N \l__mc_question_counter_int \int_compare:nNnTF { \l__mc_question_counter_int } = { 1 } { \par\vspace{\l__mc_before_first_question_dim} } { \par\vspace{\l__mc_between_questions_dim} } \par\noindent \makebox[2.65mm][c]{\bfseries\ArNum{\l__mc_question_counter_int}}% \makebox[2.65mm][r]{\bfseries.}% \hspace{0.7mm}% \parbox[t]{\dim_eval:n{\linewidth-6.0mm}}{ \setlength{\baselineskip}{1.3\normalbaselineskip} \bfseries#1} \par\vspace{\l__mc_after_question_text_dim} \int_set:Nn \l__mc_correct_index_int {#2} \int_zero:N \l__mc_option_counter_int \seq_clear:N \l__mc_options_seq } \NewDocumentCommand{\MCOption}{ m } { \int_incr:N \l__mc_option_counter_int \seq_put_right:Nn \l__mc_options_seq {#1} } \cs_new_protected:Npn \__mc_display_options: { \int_compare:nNnT { \l__mc_option_counter_int } = { 0 } { \msg_warning:nn { mc } { no-options } \par \scan_stop: } \tl_set:Nx \l_tmpa_tl { \seq_item:Nn \l__mc_options_seq { \l__mc_correct_index_int } } \seq_shuffle:N \l__mc_options_seq \int_set:Nn \l_tmpa_int { \int_mod:nn { \l__mc_option_counter_int } { \l__mc_columns_int } } \int_compare:nNnT { \l_tmpa_int } > { 0 } { \int_set:Nn \l_tmpb_int { \l__mc_columns_int - \l_tmpa_int } \prg_replicate:nn { \l_tmpb_int } { \seq_put_right:Nn \l__mc_options_seq { \hspace{0pt} } } } \dim_set:Nn \l_tmpb_dim { \int_eval:n { \l__mc_columns_int - 1 } \l__mc_col_sep_dim } \dim_set:Nn \l_tmpa_dim { ( \linewidth - \l_tmpb_dim ) / \l__mc_columns_int } \dim_set:Nn \l__mc_text_width_dim { \dim_eval:n { \l_tmpa_dim - \l__mc_label_width_dim - \l__mc_label_sep_dim } } \dim_compare:nNnT { \l__mc_text_width_dim } < { 0pt } { \dim_set:Nn \l__mc_text_width_dim { 0pt } } \noindent \int_step_inline:nn { \seq_count:N \l__mc_options_seq } { \tl_set:Nx \l_tmpb_tl { \seq_item:Nn \l__mc_options_seq { ##1 } } \makebox[\l_tmpa_dim][r] { \makebox[\l__mc_label_width_dim][l] { \int_compare:nNnTF { ##1 } > { \l__mc_option_counter_int } { \hspace{0pt} } { \seq_item:Nn \g_exam_letters_seq {##1}) } }% \hspace{\l__mc_label_sep_dim}% \parbox[t]{\l__mc_text_width_dim} { \setlength{\baselineskip}{1.3\normalbaselineskip} \raggedleft \arbstrut \l_tmpb_tl \par } } \int_compare:nNnT { ##1 } < { \l__mc_option_counter_int + 1 } { \tl_if_eq:VVT \l_tmpb_tl \l_tmpa_tl { \tl_gput_right:Nx \g__question_answer_tl { \exp_not:N \makebox[4em][r] { (\ArNum{\l__mc_question_counter_int}) ~{$\;\Leftarrow\;$}~ (\seq_item:Nn \g_exam_letters_seq {##1}) }% \qquad } } } \int_compare:nNnF { \int_mod:nn {##1} { \l__mc_columns_int } } = { 0 } { \hspace{\l__mc_col_sep_dim} } \int_compare:nNnT { \int_mod:nn {##1} { \l__mc_columns_int } } = { 0 } { \par\prevdepth=\dp\strutbox% \vspace{\l__mc_between_option_lines_dim} } } \par } \msg_new:nnn { mc } { no-options } { تحذير:~لا~توجد~خيارات~للسؤال~\int_use:N \l__mc_question_counter_int. } % -------------------------------------------------- % 15. True/False (TF) % -------------------------------------------------- \int_new:N \l__tf_question_counter_int \tl_new:N \l__tf_question_text_tl \tl_new:N \l__tf_correct_answer_tl \bool_new:N \l__tf_style_bool \dim_const:Nn \l__tf_number_width_dim { 5.3mm } \dim_const:Nn \l__tf_bracket_width_dim { 3em } \dim_const:Nn \l__tf_option_width_dim { 8em } \dim_new:N \l__tf_before_first_question_dim \dim_new:N \l__tf_between_questions_dim \dim_set:Nn \l__tf_before_first_question_dim { 0.5em } \dim_set:Nn \l__tf_between_questions_dim { 0.3\baselineskip } \NewDocumentEnvironment{TF}{ O{bracket} } { \int_zero:N \l__tf_question_counter_int \str_if_eq:nnTF {#1} {bracket} { \bool_set_true:N \l__tf_style_bool } { \bool_set_false:N \l__tf_style_bool } } {} \NewDocumentCommand{\TFQuestion}{ m m } { \int_incr:N \l__tf_question_counter_int \int_compare:nNnTF { \l__tf_question_counter_int } = { 1 } { \par\vspace{\l__tf_before_first_question_dim} } { \par\vspace{\l__tf_between_questions_dim} } \par\noindent \makebox[2.65mm][c]{\ArNum{\l__tf_question_counter_int}}% \makebox[2.65mm][r]{.}% \bool_if:NTF \l__tf_style_bool { \parbox[t]{\dim_eval:n{\linewidth-10.0mm}} { \setlength{\baselineskip}{1.3\normalbaselineskip} \arbstrut#1\unskip\nobreak\hspace{1em}% \makebox[3em][c]{(\hspace{2em})} \par } } { \parbox[t]{\dim_eval:n{\linewidth-10.0mm-\l__tf_option_width_dim}} { \setlength{\baselineskip}{1.3\normalbaselineskip} \arbstrut#1 \par }% \hfill \makebox[\l__tf_option_width_dim][c] { \makebox[3em][c]{صح}% \hspace{1em}% \makebox[3em][c]{خطأ} } } \par\prevdepth=\dp\strutbox% \tl_gput_right:Nx \g__question_answer_tl { \exp_not:N \makebox[4em][r] { (\ArNum{\l__tf_question_counter_int}) ~{$\;\Leftarrow\;$}~ #2 }% \qquad } } % -------------------------------------------------- % 16. Ordering % -------------------------------------------------- \int_new:N \l__ord_question_counter_int \int_new:N \l__ord_option_counter_int \int_new:N \l__ord_columns_int \seq_new:N \l__ord_options_seq \seq_new:N \l__ord_original_order_seq \tl_new:N \l__ord_answer_tl \bool_new:N \l__ord_answer_pending_bool \dim_new:N \l__ord_answer_width_dim \dim_set:Nn \l__ord_answer_width_dim { 5mm } \dim_new:N \l__ord_label_width_dim \dim_new:N \l__ord_label_sep_dim \dim_new:N \l__ord_col_sep_dim \dim_new:N \l__ord_text_width_dim \dim_set:Nn \l__ord_label_width_dim { 1.5em } \dim_set:Nn \l__ord_label_sep_dim { 0.8em } \dim_set:Nn \l__ord_col_sep_dim { 1.5em } \dim_new:N \l__ord_before_first_question_dim \dim_new:N \l__ord_after_question_text_dim \dim_new:N \l__ord_between_questions_dim \dim_new:N \l__ord_after_options_dim \dim_new:N \l__ord_between_option_lines_dim \dim_set:Nn \l__ord_before_first_question_dim { 0.5em } \dim_set:Nn \l__ord_after_question_text_dim { 0.3em } \dim_set:Nn \l__ord_between_questions_dim { 0.1em } \dim_set:Nn \l__ord_after_options_dim { 0.3em } \dim_set:Nn \l__ord_between_option_lines_dim { 0.3em } \NewDocumentEnvironment{Ordering}{ O{4} } { \int_set:Nn \l__ord_columns_int {#1} \int_zero:N \l__ord_question_counter_int \int_zero:N \l__ord_option_counter_int \tl_clear:N \l__ord_answer_tl \seq_clear:N \l__ord_options_seq \seq_clear:N \l__ord_original_order_seq \bool_set_false:N \l__ord_answer_pending_bool \par } { \int_compare:nNnT { \l__ord_option_counter_int } > { 0 } { \__ord_display_options: } \par } \NewDocumentCommand{\OrderQuestion}{ m } { \int_compare:nNnT { \l__ord_option_counter_int } > { 0 } { \__ord_display_options: \par\vspace{\l__ord_after_options_dim} } \int_incr:N \l__ord_question_counter_int \int_compare:nNnTF { \l__ord_question_counter_int } = { 1 } { \par\vspace{\l__ord_before_first_question_dim} } { \par\vspace{\l__ord_between_questions_dim} } \par\noindent \makebox[2.65mm][c]{\bfseries\ArNum{\l__ord_question_counter_int}}% \makebox[2.65mm][r]{\bfseries.}% \hspace{0.7mm}% \parbox[t]{\dim_eval:n{\linewidth-6.0mm}}{ \setlength{\baselineskip}{1.3\normalbaselineskip} \bfseries#1} \par\vspace{\l__ord_after_question_text_dim} \int_zero:N \l__ord_option_counter_int \seq_clear:N \l__ord_options_seq \seq_clear:N \l__ord_original_order_seq \bool_set_false:N \l__ord_answer_pending_bool } \NewDocumentCommand{\OrderOption}{ m } { \int_incr:N \l__ord_option_counter_int \seq_put_right:Nn \l__ord_options_seq {#1} \seq_put_right:Nn \l__ord_original_order_seq {#1} } \NewDocumentCommand{\OrderAnswer}{ O{5mm} } { \bool_set_true:N \l__ord_answer_pending_bool \dim_set:Nn \l__ord_answer_width_dim {#1} } \cs_new_protected:Npn \__ord_print_answer: { \par\noindent الترتيب:\quad \int_step_inline:nn { \l__ord_option_counter_int } { \underline{\hspace{\l__ord_answer_width_dim}}\, \int_compare:nNnT { ##1 } < { \l__ord_option_counter_int } { ,\ } } \par\vspace{0.5\baselineskip} } \cs_new_protected:Npn \__ord_display_options: { \int_compare:nNnT { \l__ord_option_counter_int } = { 0 } { \msg_warning:nn { ord } { no-options } \par \scan_stop: } \seq_shuffle:N \l__ord_options_seq \int_set:Nn \l_tmpa_int { \int_mod:nn { \l__ord_option_counter_int } { \l__ord_columns_int } } \int_compare:nNnT { \l_tmpa_int } > { 0 } { \int_set:Nn \l_tmpb_int { \l__ord_columns_int - \l_tmpa_int } \prg_replicate:nn { \l_tmpb_int } { \seq_put_right:Nn \l__ord_options_seq { \hspace{0pt} } } } \dim_set:Nn \l_tmpb_dim { \int_eval:n { \l__ord_columns_int - 1 } \l__ord_col_sep_dim } \dim_set:Nn \l_tmpa_dim { ( \linewidth - \l_tmpb_dim ) / \l__ord_columns_int } \dim_set:Nn \l__ord_text_width_dim { \dim_eval:n { \l_tmpa_dim - \l__ord_label_width_dim - \l__ord_label_sep_dim } } \dim_compare:nNnT { \l__ord_text_width_dim } < { 0pt } { \dim_set:Nn \l__ord_text_width_dim { 0pt } } \noindent \int_step_inline:nn { \seq_count:N \l__ord_options_seq } { \tl_set:Nx \l_tmpb_tl { \seq_item:Nn \l__ord_options_seq { ##1 } } \makebox[\l_tmpa_dim][r] { \makebox[\l__ord_label_width_dim][l] { \int_compare:nNnTF { ##1 } > { \l__ord_option_counter_int } { \hspace{0pt} } { \seq_item:Nn \g_exam_letters_seq {##1}) } }% \hspace{\l__ord_label_sep_dim}% \parbox[t]{\l__ord_text_width_dim} { \setlength{\baselineskip}{1.3\normalbaselineskip} \raggedleft \arbstrut \l_tmpb_tl \par } } \int_compare:nNnF { \int_mod:nn {##1} { \l__ord_columns_int } } = { 0 } { \hspace{\l__ord_col_sep_dim} } \int_compare:nNnT { \int_mod:nn {##1} { \l__ord_columns_int } } = { 0 } { \par\prevdepth=\dp\strutbox% \vspace{\l__ord_between_option_lines_dim} } } \par \__ord_build_correct_order: \bool_if:NT \l__ord_answer_pending_bool { \__ord_print_answer: \bool_set_false:N \l__ord_answer_pending_bool } } \cs_new_protected:Npn \__ord_build_correct_order: { \tl_clear:N \l_tmpa_tl \int_step_inline:nn { \l__ord_option_counter_int } { \int_zero:N \l_tmpb_int \tl_set:Nx \l_tmpb_tl { \seq_item:Nn \l__ord_original_order_seq {##1} } \int_step_inline:nn { \l__ord_option_counter_int } { \tl_set:Nx \l_tmpc_tl { \seq_item:Nn \l__ord_options_seq {####1} } \tl_if_eq:NNT \l_tmpb_tl \l_tmpc_tl { \int_set:Nn \l_tmpb_int {####1} } } \tl_put_right:Nx \l_tmpa_tl { \seq_item:Nn \g_exam_letters_seq { \int_use:N \l_tmpb_int } } \int_compare:nNnF {##1} = { \l__ord_option_counter_int } { \tl_put_right:Nn \l_tmpa_tl { ~،~ } } } \tl_put_right:Nx \l__ord_answer_tl { \exp_not:N \makebox[4em][r] { (\ArNum{\l__ord_question_counter_int}) ~{$\;\Leftarrow\;$}~ \l_tmpa_tl }% \par } \tl_gset_eq:NN \g__question_answer_tl \l__ord_answer_tl } \msg_new:nnn { ord } { no-options } { تحذير:~لا~توجد~خيارات~للسؤال~\int_use:N \l__ord_question_counter_int. } % -------------------------------------------------- % 17. FillBlank % -------------------------------------------------- \int_new:N \l__fb_question_counter_int \tl_new:N \l__fb_answer_tl \bool_new:N \l__fb_wordbank_bool \dim_const:Nn \l__fb_number_width_dim { 5.3mm } \dim_new:N \l__fb_before_first_question_dim \dim_new:N \l__fb_between_questions_dim \dim_set:Nn \l__fb_before_first_question_dim { 0.2em } \dim_set:Nn \l__fb_between_questions_dim { 0.5em } \NewDocumentEnvironment{FillBlank}{ O{false} } { \int_zero:N \l__fb_question_counter_int \tl_clear:N \l__fb_answer_tl \str_if_eq:nnTF {#1} {true} { \bool_set_true:N \l__fb_wordbank_bool } { \bool_set_false:N \l__fb_wordbank_bool } } { \smallskip \tl_gset_eq:NN \g__question_answer_tl \l__fb_answer_tl } \NewDocumentCommand{\WordBank}{ O{\quad} m } { \bool_if:NT \l__fb_wordbank_bool { \par\vspace{0.5em}\noindent \tl_clear:N \l_tmpa_tl \clist_set:Nn \l_tmpa_clist {#2} \hbox_set:Nn \l_tmpa_box { \clist_use:Nn \l_tmpa_clist {#1} } \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box } \dim_set:Nn \l_tmpb_dim { 0.9\linewidth } \dim_compare:nNnTF { \l_tmpa_dim } > { \l_tmpb_dim } { \dim_set:Nn \l_tmpa_dim { \l_tmpb_dim } } { } \dim_add:Nn \l_tmpa_dim { 10pt } \makebox[\linewidth][c] { \fbox {% \begin{minipage}{\l_tmpa_dim} \centering \vspace{4pt} \setlength{\baselineskip}{1.3\normalbaselineskip} \clist_use:Nn \l_tmpa_clist {#1} \vspace{3pt} \end{minipage}% } }% \par\vspace{0.5em} } } \NewDocumentCommand{\Blank}{ O{15mm} } { \underline{\hspace{#1}} } \NewDocumentCommand{\FullBlank}{} { \leavevmode\unskip\enspace\hrulefill\enspace } \NewDocumentCommand{\FillQuestion}{ m m } { \int_incr:N \l__fb_question_counter_int \int_compare:nNnTF { \l__fb_question_counter_int } = { 1 } { \par\vspace{\l__fb_before_first_question_dim} } { \par\vspace{\l__fb_between_questions_dim} } \par\noindent \makebox[2.65mm][c]{\ArNum{\l__fb_question_counter_int}}% \makebox[2.65mm][r]{.}% \parbox[t]{\dim_eval:n{\linewidth-6.0mm}} { \setlength{\baselineskip}{1.3\normalbaselineskip} \arbstrut#1 \par } \par\prevdepth=\dp\strutbox% \tl_put_right:Nx \l__fb_answer_tl { \exp_not:N (\ArNum{\l__fb_question_counter_int}) ~{$\;\Leftarrow\;$}~ #2% \par } } % -------------------------------------------------- % 18. Matching % -------------------------------------------------- \seq_new:N \l__match_left_seq % التعريفات (سيظهر في اليسار) \seq_new:N \l__match_right_seq % المصطلحات (سيظهر في اليمين) \seq_new:N \l__match_index_seq \int_new:N \l__match_count_int \tl_new:N \l__match_answer_tl \dim_new:N \l__match_label_width_dim \dim_new:N \l__match_label_sep_dim \dim_new:N \l__match_col_sep_dim \dim_new:N \l__match_left_text_width_dim \dim_new:N \l__match_right_text_width_dim \dim_new:N \l__match_left_width_dim \dim_new:N \l__match_right_width_dim \dim_new:N \l__match_before_first_dim \dim_new:N \l__match_between_pairs_dim \dim_set:Nn \l__match_label_width_dim { 1.75em } \dim_set:Nn \l__match_label_sep_dim { 0.5em } \dim_set:Nn \l__match_col_sep_dim { 2em } \dim_set:Nn \l__match_before_first_dim { 0.5em } \dim_set:Nn \l__match_between_pairs_dim { 0.2em } \msg_new:nnn { matching } { empty-pair } { خطأ~في~نمط~التوصيل:~لا~يوجد~أزواج!~ أضف~أزواجاً~باستخدام~\token_to_str:N \MatchPair. } \msg_new:nnn { matching } { odd-number } { تحذير:~عدد~العناصر~في~العمودين~غير~متساوٍ.~ العمود~الأيمن:~#1،~العمود~الأيسر:~#2. } \NewDocumentEnvironment{Matching}{ O{0.5} } { \seq_clear:N \l__match_left_seq \seq_clear:N \l__match_right_seq \seq_clear:N \l__match_index_seq \tl_clear:N \l__match_answer_tl \dim_set:Nn \l__match_right_width_dim { #1\linewidth - \l__match_label_width_dim - \l__match_label_sep_dim } \dim_set:Nn \l__match_left_width_dim { \linewidth - \l__match_right_width_dim - \l__match_col_sep_dim } \dim_set:Nn \l__match_right_text_width_dim { \l__match_right_width_dim - \l__match_label_width_dim - \l__match_label_sep_dim } \dim_set:Nn \l__match_left_text_width_dim { \l__match_left_width_dim - \l__match_label_width_dim - \l__match_label_sep_dim } } { \int_compare:nNnT { \seq_count:N \l__match_left_seq } = { 0 } { \msg_error:nn { matching } { empty-pair } } \int_compare:nNnF { \seq_count:N \l__match_left_seq } = { \seq_count:N \l__match_right_seq } { \msg_warning:nnx { matching } { odd-number } { \int_use:N \seq_count:N \l__match_left_seq } { \int_use:N \seq_count:N \l__match_right_seq } } \int_set:Nn \l__match_count_int { \seq_count:N \l__match_right_seq } \int_step_inline:nn { \l__match_count_int } { \seq_put_right:Nn \l__match_index_seq {##1} } \seq_shuffle:N \l__match_index_seq \par\vspace{\l__match_before_first_dim} \noindent \begin{minipage}[t]{\l__match_right_width_dim} \raggedleft \int_step_inline:nn { \l__match_count_int } { \makebox[\l__match_label_width_dim][l] { \ArNum{##1}) }% \hspace{\l__match_label_sep_dim}% \parbox[t]{\l__match_right_text_width_dim} { \setlength{\baselineskip}{1.3\normalbaselineskip} \raggedleft \arbstrut \seq_item:Nn \l__match_right_seq {##1} \par \vspace{0.1em} } \par\prevdepth=\dp\strutbox% \vspace{\l__match_between_pairs_dim} } \end{minipage} \hspace{\l__match_col_sep_dim} \begin{minipage}[t]{\l__match_left_width_dim} \raggedleft \int_step_inline:nn { \l__match_count_int } { \makebox[\l__match_label_width_dim][l] { \seq_item:Nn \g_exam_letters_seq {##1}) }% \hspace{\l__match_label_sep_dim}% \parbox[t]{\l__match_left_text_width_dim} { \setlength{\baselineskip}{1.3\normalbaselineskip} \raggedleft \arbstrut \seq_item:Nn \l__match_left_seq { \seq_item:Nn \l__match_index_seq {##1} } \par \vspace{0.1em} } \par\prevdepth=\dp\strutbox% \vspace{\l__match_between_pairs_dim} } \end{minipage} \par\vspace{0.1em} \tl_clear:N \l__match_answer_tl \int_step_inline:nn { \l__match_count_int } { \int_zero:N \l_tmpa_int \int_step_inline:nn { \l__match_count_int } { \int_compare:nNnT { \seq_item:Nn \l__match_index_seq {####1} } = { ##1 } { \int_set:Nn \l_tmpa_int {####1} } } \tl_put_right:Nx \l__match_answer_tl { \exp_not:N \makebox[5.25em][r] { (\ArNum{##1}) ~{$\;\Leftarrow\;$}~ (\seq_item:Nn \g_exam_letters_seq { \int_use:N \l_tmpa_int }) }% \qquad } } \tl_gset_eq:NN \g__question_answer_tl \l__match_answer_tl } \NewDocumentCommand{\MatchPair}{mm} { \seq_put_right:Nn \l__match_left_seq {#1} % التعريفات \seq_put_right:Nn \l__match_right_seq {#2} % المصطلحات } % -------------------------------------------------- % 19. Essay % -------------------------------------------------- \int_new:N \l__essay_question_counter_int \tl_new:N \l__essay_answer_tl \bool_new:N \l__essay_lines_bool \dim_const:Nn \l__essay_number_width_dim { 5.3mm } \dim_new:N \l__essay_line_skip_dim \dim_set:Nn \l__essay_line_skip_dim { 0.4\baselineskip } \dim_new:N \l__essay_before_first_question_dim \dim_new:N \l__essay_between_questions_dim \dim_new:N \l__essay_after_question_dim \dim_new:N \l__essay_user_line_skip_dim \dim_set:Nn \l__essay_before_first_question_dim { 0.5em } \dim_set:Nn \l__essay_between_questions_dim { 0.8\baselineskip } \dim_set:Nn \l__essay_after_question_dim { 0.7\baselineskip } \dim_set:Nn \l__essay_user_line_skip_dim { 1.4\baselineskip } \NewDocumentEnvironment{Essay}{ O{true} } { \int_zero:N \l__essay_question_counter_int \tl_clear:N \l__essay_answer_tl \str_if_eq:nnTF {#1} {true} { \bool_set_true:N \l__essay_lines_bool } { \bool_set_false:N \l__essay_lines_bool } } { \tl_gset_eq:NN \g__question_answer_tl \l__essay_answer_tl } \NewDocumentCommand{\EssayQuestion}{ O{4} m m } { \int_incr:N \l__essay_question_counter_int \int_compare:nNnTF { \l__essay_question_counter_int } = { 1 } { \par\vspace{\l__essay_before_first_question_dim} } { \par\vspace{\l__essay_between_questions_dim} } \par\noindent \makebox[2.65mm][c]{\ArNum{\l__essay_question_counter_int}}% \makebox[2.65mm][r]{.}% \hspace{0.7mm}% \parbox[t]{\dim_eval:n{\linewidth-6.0mm}} { \setlength{\baselineskip}{1.3\normalbaselineskip} #2 \par } \par\prevdepth=\dp\strutbox% \par\vspace{\l__essay_after_question_dim} \bool_if:NTF \l__essay_lines_bool { \int_step_inline:nn {#1} { \noindent \hspace*{6.0mm}% \rule{\dim_eval:n{\linewidth-6.0mm}}{0.4pt} \par\vspace{\l__essay_line_skip_dim} } } { \int_step_inline:nn {#1} { \par\vspace{\l__essay_user_line_skip_dim} } } \tl_put_right:Nx \l__essay_answer_tl { \exp_not:N (\ArNum{\l__essay_question_counter_int}) ~{$\;\Leftarrow\;$}~ #3 \par } } % -------------------------------------------------- % 20. ShortAnswer % -------------------------------------------------- \int_new:N \l__short_question_counter_int \tl_new:N \l__short_answer_tl \bool_new:N \l__short_lines_bool \dim_const:Nn \l__short_number_width_dim { 5.3mm } \dim_new:N \l__short_line_height_dim \dim_new:N \l__short_line_after_dim \dim_set:Nn \l__short_line_height_dim { 0.4\baselineskip } \dim_set:Nn \l__short_line_after_dim { 0.4\baselineskip } \dim_new:N \l__short_before_first_question_dim \dim_new:N \l__short_between_questions_dim \dim_new:N \l__short_after_question_dim \dim_set:Nn \l__short_before_first_question_dim { 0.5em } \dim_set:Nn \l__short_between_questions_dim { 0.1\baselineskip } \dim_set:Nn \l__short_after_question_dim { 0.7\baselineskip } \NewDocumentEnvironment{ShortAnswer}{ O{true} } { \int_zero:N \l__short_question_counter_int \tl_clear:N \l__short_answer_tl \str_if_eq:nnTF {#1} {true} { \bool_set_true:N \l__short_lines_bool } { \bool_set_false:N \l__short_lines_bool } } { \tl_gset_eq:NN \g__question_answer_tl \l__short_answer_tl } \NewDocumentCommand{\ShortQuestion}{ O{1} m m } { \int_incr:N \l__short_question_counter_int \int_set:Nn \l_tmpa_int {#1} \int_compare:nNnT {#1} > { 2 } { \int_set:Nn \l_tmpa_int { 2 } } \int_compare:nNnTF { \l__short_question_counter_int } = { 1 } { \par\vspace{\l__short_before_first_question_dim} } { \par\vspace{\l__short_between_questions_dim} } \par\noindent \makebox[2.65mm][c]{\ArNum{\l__short_question_counter_int}}% \makebox[2.65mm][r]{.}% \hspace{0.7mm}% \parbox[t]{\dim_eval:n{\linewidth-6.0mm}} { \setlength{\baselineskip}{18pt} #2 \int_compare:nNnT { \l_tmpa_int } = { 0 } { \quad \underline{\hspace{7em}} } } \par\prevdepth=\dp\strutbox% \vspace{\l__short_after_question_dim} \int_compare:nNnT { \l_tmpa_int } > { 0 } { \int_step_inline:nn { \l_tmpa_int } { \par \noindent \hspace*{6.0mm}% \rule{\dim_eval:n{\linewidth-6.0mm}} { \bool_if:NTF \l__short_lines_bool {0.4pt} {0pt} } \par\vspace{\l__short_line_height_dim} } \vspace{\l__short_line_after_dim} } \par \tl_put_right:Nx \l__short_answer_tl { \exp_not:N (\ArNum{\l__short_question_counter_int}) ~{$\;\Leftarrow\;$}~ #3 \par } } % -------------------------------------------------- % 21. Reading Passage % -------------------------------------------------- \NewDocumentEnvironment{ReadingPassage}{ O{} m } { \par \begin{tcolorbox}[ enhanced, breakable, colback=white, colframe=black, arc=0pt, outer~arc=0pt, boxrule=1pt, top=10pt, bottom=10pt, left=10pt, right=10pt, parbox=true, fontupper=\linespread{1.4}\selectfont, before~upper={\begin{RTL}}, after~upper={\end{RTL}}, coltitle=black, fonttitle=\bfseries, title={\textbf{\tl_if_empty:nTF {#2} {قطعة~القراءة} {#2}}}, #1, attach~boxed~title~to~top~center={ yshift=-3mm, yshifttext=-1mm }, boxed~title~style={ colback=white, colframe=white, left=5pt, right=5pt } ] } { \end{tcolorbox} \par\smallskip } % -------------------------------------------------- % 22. End % -------------------------------------------------- \ExplSyntaxOff % \end{macrocode} % \iffalse % % \fi % \Finale