Files
ouc_latex_template/exam/oucexam.sty
T
laoyang 47158f2add add exam: 试卷与参考答案及评分标准模板
- exam/oucexam.sty    试卷版式包(195x270mm 专用试卷纸)
- exam/ouckey.sty     答案与评分标准版式包(默认 A4,可选 exampaper)
- exam/试卷题型示例.tex        16 类题型,6 页
- exam/参考答案与评分标准示例.tex  8 大题 / 满分 100,3 页
- exam/README.md      用法与书写注意事项
- .gitignore          忽略 LaTeX 编译中间文件
2026-10-22 16:27:54 +08:00

700 lines
35 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
%======================================================================
% oucexam.sty — 中国海洋大学 期末考试试卷 版式包
% 依据:数字逻辑 2025 秋 B 卷(195mm × 270mm 专用试卷纸)
% 所有尺寸单位 bp(PDF 点,1bp = 1/72in),与原卷 PDF 逐项对齐
%
% 用法见同目录 example-数字逻辑B卷.tex
%======================================================================
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{oucexam}[2026/10/21 v1.0 OUC exam paper layout]
\RequirePackage{geometry}
\RequirePackage{fontspec}
\RequirePackage{xeCJK}
\RequirePackage{tikz}
\RequirePackage{graphicx}
\RequirePackage{eso-pic}
\RequirePackage{lastpage}
\RequirePackage{keyval}
\RequirePackage{ragged2e} % \justifying:原卷第3页设计题是两端对齐
\usetikzlibrary{calc}
%======================================================================
% 1. 页面版心
% 195mm × 270mm;左边距 29mm(装订侧),版心宽 154mm
% 版心上边界 34.13bp;首行基线落在 46.13bp
%======================================================================
\geometry{
paperwidth = 195mm,
paperheight = 270mm,
left = 82.2bp,
textwidth = 436.55bp,
top = 34.13bp,
textheight = 665.87bp,
headheight = 0pt,
headsep = 0pt,
footskip = 0pt,
}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0pt}
\setlength{\topskip}{12bp} % 首行基线 = 34.13 + 12 = 46.13bp
\pagestyle{empty}
\raggedright % 左对齐,右端不拉伸(与原卷一致)
% 注意:ctexart 会在 \begin{document} 时把 \linespread 设为 1.3,
% 必须用同一钩子(后注册者后执行)压回 1,否则基线网格全乱。
\AtBeginDocument{\linespread{1}\Fivhao\selectfont}
%======================================================================
% 2. 字体
% SimSun 宋体(标题/大题用 AutoFakeBold 模拟原卷描边加粗)
% KaiTi 楷体(卷头) SimHei 黑体(装订栏“专业年级”)
% Times New Roman 西文数字
%======================================================================
% 正文西文默认用 SimSun 的等宽西文字形(原卷正文 Mealy / 2026 / RS 等
% 实测每个 ASCII 字符步距恒为 5.28bp 且 font 名为 SimSun,即为宋体西文)。
% 需要真正 Times 的地方(化简题、页脚、卷头年份)显式 \tnr / \tnrb。
\setmainfont{SimSun}
\setCJKmainfont{SimSun}[AutoFakeBold=2.86]
\newCJKfontfamily\songti{SimSun}[AutoFakeBold=2.86]
\newCJKfontfamily\heiti{SimHei}
\newCJKfontfamily\kaiti{KaiTi}
\newfontfamily\tnr{Times New Roman}
\newfontfamily\tnrb{Times New Roman Bold}
\newfontfamily\sunfont{SimSun}
%----------------------------------------------------------------------
% ⚠️ xeCJK 陷阱:字体切换命令若紧邻 \par(或位于段落末尾),
% 该段结束时的字体状态会"溢出"到后续段落,导致后面的 ASCII
% 字符全部被排成 Times(实测:\tnr{ABC}\par 会让下一段的 "3" 变 Times)。
% 故所有局部字体切换一律走下面两个包装:内部显式 \normalfont 收尾。
% ⇒ 正文中请用 \TNR{...} / \TNRB{...} / \SUN{...},不要裸用 \tnr。
%----------------------------------------------------------------------
\newcommand{\TNR}[1]{{\tnr #1\normalfont}}
\newcommand{\TNRB}[1]{{\tnrb #1\normalfont}}
\newcommand{\SUN}[1]{{\sunfont #1\normalfont}}
% Word「字符间距展开」模拟:逐字之间插入固定胶
% \spreadtext{0.30}{文字} —— 0.30bp 即 10.50→10.80bp 的步距
% 实现:先输出首字,再对余下每个字"先插空隙、后出字"(首字前不插,否则整体右移)
\newcommand{\spreadtext}[2]{%
\begingroup\spread@amt=#1bp\relax
\expandafter\@spreadtext#2\@nil\endgroup}
\newdimen\spread@amt
\def\@spreadtext#1#2\@nil{#1\@spreadeach#2\@nil}
\def\@spreadeach#1{%
\ifx#1\@nil\else\hspace*{\spread@amt}#1\expandafter\@spreadeach\fi}
% 中文与西文间自动间距:原卷实测固定 2.70bp(不随字号缩放,
% 故用绝对 bp 而非 em;原卷 10.5bp 与 12bp 处均为 2.7bp)
\xeCJKsetup{CJKecglue={\hskip 2.70bp\relax},PunctStyle=plain}
%======================================================================
% 3. 字号(bp,直接对应原卷)
%======================================================================
\newcommand{\Fivhao}{\fontsize{10.5bp}{15.6bp}\selectfont} % 五号 正文(原卷 10.5bp)
\newcommand{\Sihao}{\fontsize{12bp}{15bp}\selectfont} % 小四 大题
\newcommand{\DaSihao}{\fontsize{14.05bp}{16bp}\selectfont} % 四号 卷头
\newcommand{\Xiaowu}{\fontsize{9bp}{11bp}\selectfont} % 小五 图题
\AtBeginDocument{\Fivhao}
%======================================================================
% 4. 卷头参数
%======================================================================
\def\ouc@year{}\def\ouc@term{}\def\ouc@course{}\def\ouc@college{}
\def\ouc@type{}\def\ouc@proposer{}\def\ouc@reviewer{}
\def\ouc@mode{}\def\ouc@allowed{}
\define@key{ouc}{year}{\def\ouc@year{#1}}
\define@key{ouc}{term}{\def\ouc@term{#1}}
\define@key{ouc}{course}{\def\ouc@course{#1}}
\define@key{ouc}{college}{\def\ouc@college{#1}}
\define@key{ouc}{type}{\def\ouc@type{#1}}
\define@key{ouc}{proposer}{\def\ouc@proposer{#1}}
\define@key{ouc}{reviewer}{\def\ouc@reviewer{#1}}
\define@key{ouc}{mode}{\def\ouc@mode{#1}}
\define@key{ouc}{allowed}{\def\ouc@allowed{#1}}
\newcommand{\examsetup}[1]{\setkeys{ouc}{#1}}
%----------------------------------------------------------------------
% 页脚是否印"试卷类型字母"(课程名之后那个 A / B)
%
% ★ 原卷实测:A 卷页脚【没有】字母(数字逻辑 + 一串短横线),
% B 卷页脚【有】B(392.48 处)。
% 即:这是出卷人手工敲的,不是规则。故默认不印,需要时显式打开:
% \examsetup{foottype = {B}} → 页脚印 B
% \examsetup{foottype = {}} → 页脚不印(默认)
%----------------------------------------------------------------------
\def\ouc@foottype{}
\define@key{ouc}{foottype}{\def\ouc@foottype{#1}}
%======================================================================
% 5. 页脚:+…………………………课程名称 X……… 第 N 页 共 M 页 + 基线 713.33bp
%
% 本地实测(原卷字符级):
% 82.20 '+' | 91.20~343.20 连续 29 个 '…'(每个步距 9.00)
% 352.20 起课程名(长度不定)| 类型字母在 390.48
% 396.48 起 3 个 '…' | 432.48 '第' | 443.64 页码 | 448.20 '页'
% 461.64 '共' | 472.92 总页 | 477.48 '页' | 499.92 '+'
%
% ★ 课程名长度可变,前面那串圆点必须"自动伸缩":
% · 课程名 ≤ 36bp(4 个汉字)→ 左锚保持 352.20,点区 29 个点(与原卷一致)
% · 课程名更长 → 左锚左移,点区自动缩短(这就是用户要的"按名称长度缩减")
% 点区终点固定在左锚前 3bp,绝不与课程名重叠。
%======================================================================
\newbox\ouc@dotbox
\newdimen\ouc@cnw
\newdimen\ouc@cstart
\newdimen\ouc@fw
\newdimen\ouc@tstart
\newdimen\ouc@tfw
% 测课程名宽度 -> 定左锚 -> 定点区宽度(shipout 时执行,读的是 \ouc@course)
\newcommand{\ouc@prepfooter}{%
\setbox\ouc@dotbox\hbox{\fontsize{9bp}{9bp}\selectfont\ouc@course}%
\ouc@cnw=\wd\ouc@dotbox
\ifdim\ouc@cnw>36bp
% 偏长:右端钉在 388.20,向左生长(点区自动变短)
\ouc@cstart=\dimexpr 388.20bp-\ouc@cnw\relax
\else
% 不长:用原卷锚点(此时点区正好 29 个点)
\ouc@cstart=352.20bp
\fi
% 点区宽度 = 左锚 - 起点 91.20
% ★ 不减空隙:\leaders 按整步距铺,最后一点的右缘正好落在左锚上
% (原卷正是这样:点占 91.20~352.20,课程名紧接 352.20 起)
\ouc@fw=\dimexpr\ouc@cstart-91.20bp\relax
\ifdim\ouc@fw<9bp \ouc@fw=9bp \fi
% ---- 无字母模式:三点从课程名右缘 +4bp 起,铺到"第"(432.48) 之前 ----
\ifx\ouc@foottype\@empty
\ouc@tstart=\dimexpr\ouc@cstart+\ouc@cnw+4bp\relax
\ouc@tfw=\dimexpr 432.48bp-\ouc@tstart\relax
\ifdim\ouc@tfw<9bp \ouc@tfw=9bp \fi
\fi}
% 点区:\leaders 按 9bp 步距自动铺满(个数自动取整)
\newcommand{\ouc@dotsfill}{%
\hbox to \ouc@fw{\leaders\hbox{\makebox[9bp][c]{…}}\hfill}}
% 无字母模式下课程名之后的点区(步距 9bp,铺到"第"之前)
\newcommand{\ouc@taildots}{%
\hbox to \ouc@tfw{\leaders\hbox{\makebox[9bp][c]{…}}\hfill}}
\newcommand{\ouc@makefooter}{%
\ouc@prepfooter
\begin{tikzpicture}[remember picture,overlay]
\coordinate (F) at ([yshift=-713.33bp]current page.north west);
% 左端 +
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=82.20bp]F) {+};
% 伸缩圆点区(\leaders 自动铺满,步距 9bp)
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=91.20bp]F) {\ouc@dotsfill};
% 课程名(左锚随长度自动左移)
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=\ouc@cstart]F) {\ouc@course};
% 类型字母(可选)+ 后随 3 点
% ★ 原卷 A 卷无字母、B 卷有 B,属手工差异 ⇒ 由 foottype 开关控制,
% 默认空(不印)。印字母时字母在 390.48、三点从 396.48 起;
% 不印时三点紧接课程名右侧 4bp 处(与原卷 A 卷一致)。
\ifx\ouc@foottype\@empty
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=\ouc@tstart]F) {\ouc@taildots};
\else
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=390.48bp]F) {\ouc@foottype};
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=396.48bp]F) {\makebox[27bp][l]{………}};
\fi
% 逐段定位,避开 xeCJK 在中西文之间自动加的间距
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=432.48bp]F) {第};
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=443.64bp]F) {\thepage};
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=448.20bp]F) {页};
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=461.64bp]F) {共};
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=472.92bp]F) {\pageref{LastPage}};
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=477.48bp]F) {页};
% 右端 +
\node[anchor=base west,inner sep=0pt,font=\fontsize{9bp}{9bp}\selectfont]
at ([xshift=499.92bp]F) {+};
\end{tikzpicture}%
}
% ★ 挂到 shipout 钩子:每页自动出页脚,\ouc@prepfooter 在 shipout 时机测宽度
\AddToShipoutPictureFG{\ouc@makefooter}
%======================================================================
% 6. 装订线(左侧竖栏)
%
% ★ 印张规则:试卷用大纸双面印刷,偶数页拼在奇数页背面(同一张纸)。
% "装订线 + 学号/姓名/…" 只印在**奇数页**(右页,即正面);
% 偶数页是它的背面,不能再印一遍,否则折进去看不见、还浪费。
% ⇒ 默认自动判断:本页是奇数页才画(用 \ifodd\value{page})。
%
% 用法:
% \bindstrip → 自动(奇数页画、偶数页不画)★推荐
% \bindstrip[on] → 强制画(比如检查偶数页效果)
% \bindstrip[off] → 强制不画
% \bindstrip[1.3] → 自动 + 纵向整体下移 1.3bp(复刻原卷该页瑕疵)
% \bindstrip[1.3,on] → 强制画 + 下移
% 局部覆盖单页:\ouc@bindforce 置 1/0
%
% 本地实测(原卷 p1,x 坐标全部 bp):
% 竖虚线 x=33.8,5 段:101.1~148.5 / 222.4~290.8 / 359.4~427.9
% 489.3~557.8 / 600.0~668.6
% 18bp Times 连字符串 x=55.69("装/订/线"三字压在上面,白底遮断)
% 栏目名 x=32.65(竖排,自下而上);冒号单列在 x=32.89
% ★ 竖线每段 = 对应栏目的"填写区"(冒号之后向上延伸),共 6 段。
% 第 6 段 37.6~69.4 是"座号"的填写区——原 B 卷 PDF 里漏画了这一段,
% 看起来就是"座号后面没横线",学生无处可填。此处按 A 卷补齐。
% 另有一圈细边框(x=17.4 / 60.2 两条竖线 + 上下横封)。
%======================================================================
\newdimen\ouc@bindshift
%--------------------------------------------------------------------
% 开关:\bindstriptrue / \bindstripfalse(全局是否启用装订线)
% \bindstripoddfalse(默认 false = 只在奇数页画)
% \bindstripoffset{1.3bp}(整体纵向偏移,复刻原卷瑕疵)
%--------------------------------------------------------------------
\newif\ifouc@bindon \ouc@bindontrue
\newif\ifouc@bindodd \ouc@bindoddfalse % false: 只画奇数页
\newcommand{\ouc@bindshiftdimen}{0bp}
\newcommand{\bindstripoffset}[1]{\setlength{\ouc@bindshift}{#1}}
\setlength{\ouc@bindshift}{0pt}
% \bindstrip:保留兼容。现在只在需要"本页强制"时才用它;
% 正常情况装订线由 shipout 钩子自动画(见文件末尾),无需逐页调用。
\newcommand{\bindstrip}[1][]{%
\ifx\relax#1\relax\else
\ifx\@empty#1\@empty\else \setlength{\ouc@bindshift}{#1bp}\fi
\fi}
\newcommand{\ouc@dobindstrip}{%
\begin{tikzpicture}[remember picture,overlay]
\coordinate (B) at ([yshift=-\ouc@bindshift]current page.north west);
% ---- ★ 原卷此处【没有】外框 ----
% 曾误把 PDF 里 x=17.4/18.12/60.15/60.87 那组线当成黑色外框,
% 实测它们是 fill=(1,1,1) 的**白色遮挡块**(Word 里盖住页眉页脚
% 的底色块),可见黑线只有 x=33.80 那 6 段竖虚线。
% 故此处不画任何竖线/封口线。
% ---- 竖虚线:每段 = 对应栏目的"填写区"(紧接栏目名冒号之后,向上延伸)----
% 原卷 6 段,逐段对应:
% 600.05~668.60 ← 学号(冒号止于 668.6)
% 489.30~557.80 ← 姓名(止于 557.8)
% 359.35~427.85 ← 专业年级(止于 427.8)
% 222.40~290.80 ← 授课教师
% 101.10~148.50 ← 考场教室号(止于 148.5)
% 37.60~ 69.40 ← 座号(冒号止于 69.6)★ 原 B 卷 PDF 漏画,此处补上
% —— 这就是"座号后面那条线",缺了学生没法填座号。
\foreach \a/\b in {37.60/69.40, 101.10/148.50, 222.40/290.80,
359.35/427.85, 489.30/557.80, 600.05/668.60}{%
\draw[line width=0.48bp,line cap=butt]
([xshift=33.8bp,yshift=-\a bp]B) -- ([xshift=33.8bp,yshift=-\b bp]B);}
% ---- 虚线段(原卷用 18bp Times 连字符排成,不是画线)----
% 四段的连字符个数原卷各不相同(16 / 30 / 28 / 24),逐段复刻
\foreach \s/\pos in {----------------/677.32,
---------------- -------------/571.00,
--- ------------------------/382.12,
------------------------/205.36}{%
\node[anchor=base west,rotate=90,inner sep=0pt,
font=\fontsize{18bp}{18bp}\selectfont\tnr]
at ([xshift=55.69bp,yshift=-\pos bp]B) {\s};}
% ---- 竖排栏目名(自下而上读)----
% 原卷只有"姓名:""授课教师:"把冒号连排,其余冒号单独一行
\foreach \lab/\pos in {学号/694.06, 姓名:/585.10, 专业年级/474.46,
授课教师:/349.78, 考场教室号/207.46, 座号/96.70}{%
\node[anchor=base west,rotate=90,inner sep=0pt,fill=white,inner xsep=0.7bp,
font=\fontsize{10.45bp}{12bp}\selectfont]
at ([xshift=32.65bp,yshift=-\pos bp]B) {\lab};}
% ---- 单独的冒号行:学号 / 专业年级 / 考场教室号 / 座号 ----
\foreach \pos in {672.94, 432.22, 154.66, 75.70}{%
\node[anchor=base west,rotate=90,inner sep=0pt,fill=white,inner xsep=0.7bp,
font=\fontsize{10.45bp}{12bp}\selectfont]
at ([xshift=32.89bp,yshift=-\pos bp]B) {:};}
% ---- 装 / 订 / 线 ----
\foreach \lab/\pos in {装/581.44, 订/392.68, 线/215.80}{%
\node[anchor=base west,rotate=90,inner sep=0pt,fill=white,inner xsep=1.2bp,
font=\fontsize{10.45bp}{12bp}\selectfont]
at ([xshift=52.69bp,yshift=-\pos bp]B) {\lab};}
\end{tikzpicture}%
}
%======================================================================
% 7. 成绩表(题号 / 得分)
% 默认 8 个题号 + 总分共 9 栏,与原卷逐项对齐(栏宽 44.05bp)。
% 大题数不是 8 时,用 \examsetup{nsec = 11} 指定,自动按等宽重算。
%======================================================================
\def\ouc@nsec{8}
\define@key{ouc}{nsec}{\def\ouc@nsec{#1}}
% 题号汉字(支持到十六)
\newcommand{\ouc@cnnum}[1]{%
\ifcase\numexpr#1\relax\or 一\or 二\or 三\or 四\or 五\or 六%
\or 七\or 八\or 九\or 十\or 十一\or 十二%
\or 十三\or 十四\or 十五\or 十六\fi}
\newcommand{\scoretable}{%
\begin{tikzpicture}[remember picture,overlay]
\coordinate (S) at (current page.north west);
\ifnum\ouc@nsec=8
% ---- 原卷版:坐标逐项硬对齐 ----
\foreach \y in {159.04,181.99,212.44}{%
\draw[line width=0.48bp,line cap=butt]
([xshift=122.81bp,yshift=-\y bp]S) -- ([xshift=478.24bp,yshift=-\y bp]S);}
\foreach \x in {123.05,167.10,201.10,235.10,269.10,303.10,337.10,
371.10,405.10,439.10,478.00}{%
\draw[line width=0.48bp,line cap=butt]
([xshift=\x bp,yshift=-158.80bp]S) -- ([xshift=\x bp,yshift=-212.20bp]S);}
\node[anchor=base,inner sep=0pt,font=\fontsize{12bp}{12bp}\selectfont\kaiti]
at ([xshift=145.075bp,yshift=-174.89bp]S) {题号};
\node[anchor=base,inner sep=0pt,font=\fontsize{12bp}{12bp}\selectfont\kaiti]
at ([xshift=145.075bp,yshift=-201.53bp]S) {得分};
\foreach \name/\cx in {一/184.10, 二/218.10, 三/252.10, 四/286.10,
五/320.10, 六/354.10, 七/388.10, 八/422.10,
总分/458.55}{%
\node[anchor=base,inner sep=0pt,font=\fontsize{12bp}{12bp}\selectfont\kaiti]
at ([xshift=\cx bp,yshift=-174.89bp]S) {\name};}
\else
% ---- 自适应版:标签栏 + nsec 格 + 总分格 ----
% 横向:标签栏 123.05~163.05(宽 40),其后 nsec+1 格等分到 478.00
% 12 个大题时每格 (478-163.05)/13 = 24.2bp,正好容得下"十一"(12bp×2=24)
\pgfmathsetmacro{\ouc@cwl}{163.05}
\pgfmathsetmacro{\ouc@cw}{(478.00-\ouc@cwl)/(\ouc@nsec+1)}
% 题号字号自适应:两字题号(如“十一”)需 2×字号 ≤ 格宽 - 2bp 余量
% 12 题 → 格宽 24.2bp → 字号 11.1bp(仍按 12bp 上限,视觉不变)
% 16 题 → 格宽 18.5bp → 字号 8.3bp(自动缩小,不溢出)
\pgfmathsetlengthmacro{\ouc@fs}{min(12,(\ouc@cw-2)/2)*1bp}
% 三条横线(原卷 159.04 / 181.99 / 212.44)
\foreach \y in {159.04,181.99,212.44}{%
\draw[line width=0.48bp,line cap=butt]
([xshift=123.05bp,yshift=-\y bp]S) -- ([xshift=478.00bp,yshift=-\y bp]S);}
% 内容区竖线(标签栏右界即第一格左界,一并画上)
\foreach \i in {0,...,\the\numexpr\ouc@nsec+1\relax}{%
\pgfmathsetmacro{\ouc@xx}{\ouc@cwl+\i*\ouc@cw}%
\draw[line width=0.48bp,line cap=butt]
([xshift=\ouc@xx bp,yshift=-158.80bp]S) --
([xshift=\ouc@xx bp,yshift=-212.20bp]S);}
% 标签栏左侧那条竖线(原卷 123.05)
\draw[line width=0.48bp,line cap=butt]
([xshift=123.05bp,yshift=-158.80bp]S) --
([xshift=123.05bp,yshift=-212.20bp]S);
% 标签栏文字
\node[anchor=base,inner sep=0pt,font=\fontsize{\ouc@fs}{\ouc@fs}\selectfont\kaiti]
at ([xshift=143.05bp,yshift=-174.89bp]S) {题号};
\node[anchor=base,inner sep=0pt,font=\fontsize{\ouc@fs}{\ouc@fs}\selectfont\kaiti]
at ([xshift=143.05bp,yshift=-201.53bp]S) {得分};
% 题号 一…十二(居中于各自格子)
\foreach \i in {0,...,\the\numexpr\ouc@nsec-1\relax}{%
\pgfmathsetmacro{\ouc@xx}{\ouc@cwl+(\i+0.5)*\ouc@cw}%
\node[anchor=base,inner sep=0pt,font=\fontsize{\ouc@fs}{\ouc@fs}\selectfont\kaiti]
at ([xshift=\ouc@xx bp,yshift=-174.89bp]S)
{\ouc@cnnum{\numexpr\i+1\relax}};}
% 总分
\pgfmathsetmacro{\ouc@xx}{\ouc@cwl+(\ouc@nsec+0.5)*\ouc@cw}%
\node[anchor=base,inner sep=0pt,font=\fontsize{\ouc@fs}{\ouc@fs}\selectfont\kaiti]
at ([xshift=\ouc@xx bp,yshift=-174.89bp]S) {总分};
\fi
\end{tikzpicture}%
}
%======================================================================
% 8. 卷头
% 标题 + 三行填空 + 成绩表;随后补足垂直空白,
% 使正文首行基线正好落在 240.41bp
%======================================================================
\newcommand{\kh}[1]{\node[anchor=base west,inner sep=0pt,
font=\fontsize{10.45bp}{12bp}\selectfont\kaiti] at ([xshift=#1]H)}
\newcommand{\examhead}[1][184.39bp]{%
\begin{tikzpicture}[remember picture,overlay]
\coordinate (H) at (current page.north west);
% ---- 标题 ----
\node[anchor=base west,inner sep=0pt,
font=\fontsize{14.05bp}{16bp}\selectfont\bfseries]
at ([xshift=151.92bp,yshift=-54.65bp]H) {中国海洋大学全日制本科课程期末考试试卷};
% ---- 第 1 行 ----
\kh{113.52bp,yshift=-96.29bp} {\ouc@year};
\kh{139.80bp,yshift=-96.29bp} {年};
\kh{160.80bp,yshift=-96.29bp} {\ouc@term};
\kh{181.80bp,yshift=-96.29bp} {季学期};
\kh{224.04bp,yshift=-96.29bp} {考试科目:};
\kh{287.16bp,yshift=-96.29bp} {\ouc@course};
\kh{360.84bp,yshift=-96.29bp} {学院:};
\kh{402.96bp,yshift=-96.29bp} {\ouc@college};
\draw[line width=0.96bp,line cap=butt]
([xshift=113.50bp,yshift=-97.80bp]H) -- ([xshift=139.80bp,yshift=-97.80bp]H);
\draw[line width=0.96bp,line cap=butt]
([xshift=150.20bp,yshift=-97.80bp]H) -- ([xshift=181.80bp,yshift=-97.80bp]H);
\draw[line width=0.96bp,line cap=butt]
([xshift=276.70bp,yshift=-97.80bp]H) -- ([xshift=360.80bp,yshift=-97.80bp]H);
\draw[line width=0.48bp,line cap=butt]
([xshift=402.95bp,yshift=-97.40bp]H) -- ([xshift=508.40bp,yshift=-97.40bp]H);
% ---- 第 2 行 ----
\kh{116.40bp,yshift=-119.69bp} {试卷类型:};
\kh{184.92bp,yshift=-119.69bp} {\ouc@type};
\kh{207.60bp,yshift=-119.69bp} {卷};
\kh{228.60bp,yshift=-119.69bp} {命题人:};
\kh{276.00bp,yshift=-119.69bp} {\ouc@proposer};
\kh{363.60bp,yshift=-119.69bp} {审核人:};
\kh{410.00bp,yshift=-119.69bp} {\ouc@reviewer};
\draw[line width=0.96bp,line cap=butt]
([xshift=169.20bp,yshift=-121.20bp]H) -- ([xshift=207.60bp,yshift=-121.20bp]H);
\draw[line width=0.96bp,line cap=butt]
([xshift=269.00bp,yshift=-121.20bp]H) -- ([xshift=358.30bp,yshift=-121.20bp]H);
\draw[line width=0.96bp,line cap=butt]
([xshift=405.70bp,yshift=-121.20bp]H) -- ([xshift=495.00bp,yshift=-121.20bp]H);
% ---- 第 3 行:考试说明 ----
\kh{108.48bp,yshift=-154.73bp} {考试说明:本课程为\ouc@mode 考试,共};
\kh{264.84bp,yshift=-154.73bp} {\pageref{LastPage}};
\kh{275.40bp,yshift=-154.73bp} {页,除考场规定的必需用品外还可携带的文具有};
\kh{497.90bp,yshift=-154.73bp} {\ouc@allowed。};
\draw[line width=0.48bp,line cap=butt]
([xshift=259.55bp,yshift=-156.10bp]H) -- ([xshift=275.40bp,yshift=-156.10bp]H);
\draw[line width=0.48bp,line cap=butt]
([xshift=492.60bp,yshift=-156.10bp]H) -- ([xshift=513.60bp,yshift=-156.10bp]H);
\end{tikzpicture}%
\scoretable
\par\vspace*{#1}\nointerlineskip
}
%======================================================================
% 9. 正文构件
%======================================================================
% 大题标题:宋体小四伪粗;与下一行基线距 15.0bp(正文 15.6bp)
% 标题内数字/括号用 Times Bold,中文与它们之间是固定 bp 空隙(原卷如此),
% 故局部关掉 xeCJK 自动间距,空隙一律显式给:\oucsp{6}
\newcommand{\oucsp}[1]{\hspace*{#1bp}}
\newcommand{\examheading}[2][0bp]{%
\par\ifdim#1>0bp\vspace*{#1}\fi
\noindent{\xeCJKsetup{CJKecglue={}}\fontsize{12bp}{15bp}\selectfont\bfseries #2}\par
\vspace*{\ouc@headgap}}
% 小题:\qi[题号栏宽]{题号}{题干}
% 原卷第 1 页题号用宋体半角("1." 占 10.44bp)+ 5.28bp 空隙 = 栏宽 15.72bp
% 第 2/3 页题号用 Times("1." 占 8.16bp)+ 空格,栏宽 13.08bp
% 少数题(如 3. 6.)题号后不留空,栏宽 10.44bp
\newcommand{\qnum}[1]{\makebox[15.72bp][l]{\sunfont #1.}}
\newcommand{\qi}[3][15.72bp]{\par\noindent\makebox[#1][l]{\sunfont #2.}#3\par}
% 注意:\tnr 只包住题号本身,必须用 {\tnr #2.} 关掉,否则 Times 泄到正文
% ★ 题干内部换行一律用 \\*(禁止分页),不要用裸 \\:
% 裸 \\ 是"允许在此断页",题干会被切到上下两页,学生看到半句话。
\newcommand{\qiT}[3][13.08bp]{\par\noindent\makebox[#1][l]{{\tnr #2.}}\ignorespaces#3\par}
% 宋体题号版(第 3 页设计题:原卷 "1." 是 SimSun 10.45,且题号后无空格)
\newcommand{\qiS}[3][15.72bp]{\par\noindent\makebox[#1][l]{{\sunfont #2.}}\ignorespaces#3\par}
% 选项:每栏 84bp,标签栏 15.72bp(与原卷逐字对齐)
\newcommand{\opt}[2]{\makebox[84bp][l]{\qnum{#1}#2}}
\newcommand{\choices}[4]{%
\par\noindent\opt{A}{#1}\opt{B}{#2}\opt{C}{#3}\opt{D}{#4}\par}
\newcommand{\optone}[2]{\par\noindent\opt{#1}{#2}\par}
% 图题:小五,居中于版心
\newcommand{\examfigcaption}[1]{%
\par\nointerlineskip\centerline{\Xiaowu #1}\par\nointerlineskip}
% 图题(五号):原卷第 3 页 "图3" 实测 10.45bp
\newcommand{\examfigcaptioniii}[1]{%
\par\nointerlineskip\centerline{\Fivhao #1}\par\nointerlineskip\vspace*{5.40bp}}
% 插图:\examfig[水平偏移]{宽度}{文件}
% 用 \vspace* 精确控制与上一基线的距离,偏移以版心左边界为基准
\newcommand{\examfig}[3][0bp]{%
\par\nointerlineskip\vspace*{\ouc@figskip}%
\noindent\hspace*{#1}\includegraphics[width=#2]{#3}%
\par\nointerlineskip\vspace*{\ouc@figtail}}
\def\ouc@headgap{-0.6bp}
\def\ouc@figskip{0bp}
\def\ouc@figtail{0bp}
\newcommand{\figskip}[1]{\def\ouc@figskip{#1}}
\newcommand{\figtail}[1]{\def\ouc@figtail{#1}}
% 逻辑表达式:按原卷用宋体直排文本,不用数学模式(字距才对得上)
\newcommand{\logicexpr}[1]{{\sunfont #1}}
% 求和符号 Σ / 带 Φ 的 Σ,跟正文同高(原卷是混排文本,不是数学符号)
\newcommand{\sumsig}{\hbox{\sunfont ∑}}
\newcommand{\sumphisig}{\hbox{\sunfont ∑Φ}}
% 下标(原卷 M_L / M_S)
% 实测:L/S 字号 5.30bp(SimSun),基线相对正文下移 1.56bp;
% M(210.00) → L(215.16) 步距 5.16bp(M 的半角宽),
% L → 和 3.96bp,故 M 起点到"和"共 9.12bp。
% 用宽度 3.87bp 的盒接管下标宽度,使 5.25 + 3.87 = 9.12 对齐原卷。
\newcommand{\ssub}[1]{%
\raisebox{-1.56bp}{\makebox[3.87bp][l]{\fontsize{5.30bp}{5.30bp}\selectfont #1}}}
%======================================================================
% 10. 题型构件(通用)
% 设计原则:不依赖任何具体课程,只提供"骨架",
% 题目内容由正文填写。所有题型都沿用本卷实测的版面参数:
% · 正文 10.5bp / 行距 15.6bp
% · 中英之间 2.70bp(ecglue)
% · 题号栏 15.72bp(宋体题号,题号后空 5.28bp)
%======================================================================
%----------------------------------------------------------------------
% 10.1 分值标注(题号右侧、行尾右对齐)
% \qscore{5} → 在当前位置右对齐显示 "(5分)"
% 单独成行右对齐:\scorerow{5}
%----------------------------------------------------------------------
\newcommand{\qscore}[1]{{\Fivhao\hfill(#1分)}}
\newcommand{\scorerow}[1]{\par\noindent\hfill{\Fivhao(#1分)}\par}
%----------------------------------------------------------------------
% 10.2 填空横线
% \blank → 5 个下划线的短空(约 3 个汉字宽)
% \blank[8] → 指定字宽的横线(8 个字宽)
% \lblank → 通栏长横线(整行)
% 用 \rule 画,落在基线下方,与 Word 的下划线观感一致
%----------------------------------------------------------------------
\newlength\ouc@blw
\newcommand{\blank}[1][5]{%
\settowidth{\ouc@blw}{\Fivhao 国}%
\setlength{\ouc@blw}{\dimexpr\ouc@blw*#1\relax}%
\hspace*{0.6bp}\rule[0.35bp]{\ouc@blw}{0.5bp}\hspace*{0.6bp}}
\newcommand{\lblank}{\par\noindent\rule[0.35bp]{\linewidth}{0.5bp}\par}
%----------------------------------------------------------------------
% 10.3 括号填空(\tk 在括号内留出可写空间)
% \tk → 3 个字宽的括号空:\tk 写成 (\hspace.. )
%----------------------------------------------------------------------
\newcommand{\tk}{\makebox[2.4em]{\dotfill}}
%----------------------------------------------------------------------
% 10.4 选项:两种版式
% \choices{...}{...}{...}{...} 一行四栏(3 个汉字以内的短选项)
% \choicesII{...}{...}{...}{...} 两行两栏(长选项,每栏半行宽)
% \optgrid{...}{...} 任意栏数,自动按半行宽排
%----------------------------------------------------------------------
% 长选项:每栏半行宽(含标签栏)
\newlength\ouc@halfw
\newcommand{\optII}[2]{%
\setlength{\ouc@halfw}{\dimexpr\linewidth/2\relax}%
\makebox[\ouc@halfw][l]{\qnum{#1}#2}}
\newcommand{\choicesII}[4]{%
\par\noindent\optII{A}{#1}\optII{B}{#2}\par
\noindent\optII{C}{#3}\optII{D}{#4}\par}
% 任意栏数(每行 #1 栏)
% \optgrid{3}{甲,乙,丙,丁} → 每行 3 栏,逗号分隔
% ⚠️ 两个坑:
% (1) 不能用 LaTeX2e 的 \@for 遍历:它对每个元素做 \edef 展开,
% 中文(xeCJK 活动字符)会被提前展开,选项内容直接丢失。
% (2) expl3 里 @ 不是字母,控制序列名不能再含 @(\ouc@foo 会被读成
% \ouc + "@foo"),故 expl3 侧一律用 \__ouc_ 前缀。
\ExplSyntaxOn
\seq_new:N \l__ouc_opt_seq
\int_new:N \l__ouc_opt_i
\cs_new_protected:Npn \__ouc_optgrid:nn #1#2
{
\seq_set_split:Nnn \l__ouc_opt_seq {,} {#2}
\int_zero:N \l__ouc_opt_i
\seq_map_inline:Nn \l__ouc_opt_seq
{
\makebox[\dim_eval:n {\linewidth/#1}][l]{##1}
\int_incr:N \l__ouc_opt_i
\int_compare:nT { \l__ouc_opt_i = #1 }
{ \par \noindent \int_zero:N \l__ouc_opt_i }
}
\par
}
\NewDocumentCommand \optgrid { m m } { \par \noindent \__ouc_optgrid:nn {#1} {#2} }
\ExplSyntaxOff
%----------------------------------------------------------------------
% 10.5 判断题:括号在题首(原卷常见写法)
% \judge{序号}{题干} → "( )1. 题干",括号默认 3 字宽
% \judge[5]{序号}{题干} → 括号 5 字宽(长答案用)
% 括号用 \makebox + \hfill 撑开,"("居左、")"居右,中间留答题位。
% 括号在行尾的写法直接用 \qi{1}{题干(\hspace{1.67em})} 即可。
%----------------------------------------------------------------------
\newlength\ouc@jdw
\newlength\ouc@juw
\newcommand{\judge}[3][3]{%
\par\noindent
\settowidth{\ouc@juw}{\Fivhao 国}%
\setlength{\ouc@jdw}{\dimexpr\ouc@juw*#1\relax}%
\makebox[\ouc@jdw][l]{(\hfill )}%
\hspace*{2bp}\SUN{#2.}\hspace*{5.28bp}#3\par}
%----------------------------------------------------------------------
% 10.6 答题横线
% \answerlines[行数] → 在当前位置下方排 n 条等距横线(每条占 1 行距 15.6bp)
% 注意:不能用 \vbox 整体打包 —— 那样它会成为一个不可分割的原子块,
% 页面剩余空间不够时整块被推到下一页,页脚会留出大片空白。
% 改为逐条 "\par\nointerlineskip\vspace*{..}\hrule" 输出,允许跨页断开。
%----------------------------------------------------------------------
\newcommand{\answerlines}[1][3]{%
\par
\@tempcnta=0
\loop\ifnum\@tempcnta<#1
\nointerlineskip\vspace*{15.0bp}%
\noindent\hrule height 0.4bp width \linewidth
\par
\advance\@tempcnta by 1
\repeat
\nointerlineskip\vspace*{3bp}}
%----------------------------------------------------------------------
% 10.7 大题标题的"带分值"简写
% \bigsection{一}{填空题}{3 小题,每题 4 分,共 12 分}
% 中间的"共"字由宏自己补,第三个参数不要再写"共"
%----------------------------------------------------------------------
\newcommand{\bigsection}[3]{%
\examheading{#1、#2\TNRB{(}共\oucsp{6}#3\TNRB{)}}}
%----------------------------------------------------------------------
% 10.8 答题方框
% \answerbox{高度bp} → 通栏、指定高度的矩形框(作图 / 计算作答用)
%----------------------------------------------------------------------
\newcommand{\answerbox}[1]{%
\par\nointerlineskip\vspace*{4bp}\noindent
\framebox[\linewidth]{\rule{0pt}{#1}}%
\par\nointerlineskip\vspace*{6bp}}
%----------------------------------------------------------------------
% 10.10 配伍题(连线匹配)
% \mtpair{左侧内容}{右侧内容} → 左 44% | 中 12% 空白(供连线)| 右 44%
% 逐行写即可,行列自动对齐:
% \mtpair{\qnum{1} 甲}{A. 子}
% \mtpair{\qnum{2} 乙}{B. 丑}
% 中间空白留给学生画连线,不需要画虚线。
%----------------------------------------------------------------------
\newcommand{\mtpair}[2]{%
\par\noindent
\makebox[0.44\linewidth][l]{#1}%
\makebox[0.12\linewidth][c]{}%
\makebox[0.44\linewidth][l]{#2}\par}
% 配伍题整体上下留白
\newcommand{\matchinggap}{\par\vspace*{3bp}}
%----------------------------------------------------------------------
% 10.11 表格(成绩表 / 数据表):等宽 tabular,自动加横线
% \datatable{列格式}{表体}
% 表内数字请用 \TNR{},不要用 $...$(数学模式基线偏低,会与中文错行)
%----------------------------------------------------------------------
\newcommand{\datatable}[2]{%
\par\vspace*{5bp}%
\centerline{\begin{tabular}{@{}#1@{}}#2\end{tabular}}%
\par\vspace*{5bp}}
%======================================================================
% 11. 自动装订线钩子
% ★ 印张规则:试卷用大纸双面印,偶数页拼在奇数页背面(同一张纸)。
% "装订线 + 学号/姓名/专业年级/授课教师/考场教室号/座号"只印正面,
% 即**只画奇数页**;偶数页是背面,再画一遍折进去也看不见。
% ⇒ 钩到这里,按 \value{page} 自动判断,.tex 里不必逐页调用。
% ⚠️ 必须放在最后:\ouc@dobindstrip 依赖前面定义的 \ouc@bindshift 等。
%======================================================================
\AddToShipoutPictureFG{%
\ifouc@bindon
\ifouc@bindodd
\ouc@dobindstrip % 每页都画(nup 拼版等特殊需要)
\else
\ifodd\value{page}\ouc@dobindstrip\fi % 默认:只画奇数页
\fi
\fi}
\endinput