数学建模竞赛中文论文编译与合规检查。编译 PDF 并检查页数、匿名、格式等竞赛要求。Use when user says "编译竞赛论文", "compile competition paper".
argument-hint
["paper-directory"]
allowed-tools
Bash(*), Read, Write, Edit, Grep, Glob
Competition Paper Compile & Compliance (Chinese)
Compile and validate: $ARGUMENTS
Constants
ENGINE = xelatex
MAX_COMPILE_ATTEMPTS = 3
PAPER_DIR = paper/
MAX_PAGES / COMPETITION — From Additional Parameters.
Workflow
Step 1: Verify environment
if ! which xelatex 2>/dev/null; thenecho"xelatex not found, attempting install..."ifwhich miktex 2>/dev/null; then
miktex packages install xetex ctex xecjk gbt7714 fontspec
miktex fndb refresh
elifwhich initexmf 2>/dev/null; then
initexmf --set-config-value=[MPM]AutoInstall=1
fifiwhich xelatex && which bibtex && echo"ready" || echo"xelatex/bibtex not found"
fc-list :lang=zh | head -5
kpsewhich gbt7714.sty 2>/dev/null || echo"gbt7714.sty not found (will auto-install on first compile)"
Step 2: Pre-compile cleanup
if [ -f "_utils/compile_utils.sh" ]; then
bash _utils/compile_utils.sh paper/
elif [ -f "skills/shared-scripts/compile_utils.sh" ]; then
bash skills/shared-scripts/compile_utils.sh paper/
elseecho"compile_utils.sh not found, manual cleanup needed"fi
The script auto-handles: special chars cleanup, table format fixes, includegraphics path correction (figures/ → ../figures/), hidelinks, figures/figures/ nesting, math_commands conflicts, wide table resizebox wrapping, narrow table resizebox removal, light-color text fixes, TikZ library injection.
If script not found, perform these steps manually.
Also check ref/label matching and embed missing figures:
If labels are missing, find corresponding figure/table code in figures/*.tex and embed into the correct section file.
Also check compile_utils.sh output for "UNEMBEDDED" warnings — each one means a figure or table from figures/ is not in any section.
MANDATORY FIX LOOP — do NOT proceed to compilation until all figures AND tables are embedded:
UNEMBED=0
# Check PDF figuresfor pdf in figures/*.pdf; do
[ -f "$pdf" ] || continue
bn=$(basename"$pdf")
grep -rq "$bn" paper/sections/*.tex paper/main.tex 2>/dev/null || { echo"UNEMBEDDED PDF: $bn"; UNEMBED=$((UNEMBED+1)); }
done# Check TABLE_*.tex filesfor tbl in figures/TABLE_*.tex; do
[ -f "$tbl" ] || continue
bn=$(basename"$tbl")
# Check if any label from this table file appears in sectionsfor lbl in $(grep -oh '\\label{[^}]*}'"$tbl" 2>/dev/null); do
grep -rq "$lbl" paper/sections/*.tex paper/main.tex 2>/dev/null || { echo"UNEMBEDDED TABLE: $lbl (from $bn)"; UNEMBED=$((UNEMBED+1)); }
donedone# Check latex_includes.tex labelsif [ -f figures/latex_includes.tex ]; thenfor lbl in $(grep -oh '\\label{[^}]*}' figures/latex_includes.tex 2>/dev/null);
grep -rq paper/sections/*.tex paper/main.tex 2>/dev/null || { ; UNEMBED=$((UNEMBED+)); }
If UNEMBED > 0, you MUST fix ALL of them before compiling. For each unembedded item:
PDF figure: copy the \begin{figure}...\end{figure} block from figures/latex_includes.tex into the target section
TABLE_*.tex: copy the \begin{table}...\end{table} block from figures/TABLE_*.tex into the target section (use \input{../figures/TABLE_xxx.tex} or paste the tabular code directly)
Add 1-2 sentences of lead-in text before and 3-5 sentences of analysis after each embedded item
Re-run the count check above — repeat until UNEMBED = 0
Do NOT compile with unembedded figures or tables — the PDF will have missing content.
# Check all figures/*.pdf are referenced in bodyfor pdf in figures/*.pdf; do
[ -f "$pdf" ] || continue
bn=$(basename"$pdf")
grep -rq "$bn" paper/sections/*.tex paper/main.tex 2>/dev/null || echo"⚠ $bn not referenced"done
Step 3: Compile (manual steps, no latexmk)
cd paper/
xelatex -interaction=nonstopmode main.tex
bibtex main
xelatex -interaction=nonstopmode main.tex
xelatex -interaction=nonstopmode main.tex
Step 4: Error fix loop (MANDATORY — do NOT skip)
After each compilation, check main.log for CRITICAL errors. You MUST fix ALL errors before declaring compilation complete.
# Count critical errors
MATH_ERR=$(grep -c 'Bad math environment delimiter\|Missing \$ inserted\|begin{document} ended by' paper/main.log 2>/dev/null || echo 0)
LR_ERR=$(grep -c 'Not allowed in LR mode' paper/main.log 2>/dev/null || echo 0)
UNDEF_CS=$(grep -c 'Undefined control sequence' paper/main.log 2>/dev/null || echo 0)
TOTAL_ERR=$((MATH_ERR + LR_ERR))
echo"Math errors: $MATH_ERR, LR mode errors: $LR_ERR, Undefined CS: $UNDEF_CS"if [ "$TOTAL_ERR" -gt 0 ]; thenecho"CRITICAL: $TOTAL_ERR errors — MUST FIX before proceeding"# Show error locations
grep -B2 'Bad math\|Missing \$ inserted\|begin{document} ended\|Not allowed in LR mode' paper/main.log | grep -E '^\./|^l\.' | head -20
fi
Error fix rules (iterate up to 5 times, not 3):
Math environment errors (Bad math environment delimiter, Missing $ inserted, \begin{document} ended by \end{equation}):
Read the error location from main.log (e.g., ./sections/3_model_theory.tex:42)
Open the file and find the broken math: usually \X(t)$ should be $X(t)$, or \mu$ should be $\mu$
Common cause: a sed/cleanup script stripped the opening $ but left the closing $
Fix: ensure every math expression has matching $...$ or \[...\] delimiters
Do NOT use broad sed patterns to fix math — read each error location and fix individually
LR mode errors (Not allowed in LR mode):
Usually caused by \begin{figure} or \begin{table} inside a paragraph without proper separation
Fix: add \par or blank line before the float environment
Undefined control sequence:
Missing package → add \usepackage{xxx} to main.tex preamble
Typo in command → fix the command name
BibTeX failures:
If BibTeX fails because of earlier LaTeX errors, fix the LaTeX errors first, then recompile
Check that \bibliography{references} and \bibliographystyle{plainnat} exist in main.tex
Check that references.bib has no syntax errors (unmatched braces, missing commas)
After each fix, recompile and recheck:
cd paper/
xelatex -interaction=nonstopmode main.tex
bibtex main 2>&1 | tail -5
xelatex -interaction=nonstopmode main.tex
xelatex -interaction=nonstopmode main.tex
cd ..
# Recheck
MATH_ERR=$(grep -c 'Bad math environment delimiter\|Missing \$ inserted' paper/main.log 2>/dev/null || echo 0)
echo"Remaining math errors: $MATH_ERR"
⛔ Do NOT proceed to Step 5 until MATH_ERR = 0 and LR_ERR = 0. BibTeX will also fail if there are LaTeX errors upstream — fix LaTeX first.
When fixing errors in main.tex, only fix the specific error (e.g., add a missing package, fix a typo). Do not rewrite or restructure main.tex — the template's preamble, cover page, page margins, section numbering format, and header/footer settings must remain unchanged.
⛔ If GATE_FAIL > 0, you MUST go back and fix every ❌ item, recompile, and re-run this gate. Do NOT output the final report with any ❌ remaining. Repeat until GATE_FAIL = 0.
Step 8: Output report
Competition name, status, PDF path, total pages, body pages, compliance pass/fail.
Key Rules
No latexmk — manual step-by-step compilation
Do not delete .bbl file after compilation (bibliography data)
Figure paths auto-corrected by compile_utils.sh: figures/ → ../figures/
Body pages ≥ MAX_PAGES (can exceed, must not fall short)
"❌ $STACKING figure stacking — add analysis text between figures"
1
# 16. TOC
if
'tableofcontents'
then
echo
"✅ TOC generated"
echo
"❌ TOC empty — running extra compile pass..."
cd
cd
echo
"✅ TOC generated after extra compile"
echo
"❌ TOC still empty"
1
fi
# 17. Abstracts (Chinese papers)
if
'ctex'
then
'摘.*要'
echo
"✅ Chinese abstract"
echo
"❌ No Chinese abstract"
1
'Abstract'
echo
"✅ English abstract"
echo
"❌ No English abstract"
1
fi
# 18. Run compile_check.sh + writing_check.sh for full details
echo
""
echo
"--- Full check scripts ---"
"$WC_EXIT"
echo
"✅ Writing checks passed"
echo
"❌ Writing checks failed (exit=$WC_EXIT)"
1
# 19. 符号说明 longtable 检查
echo
"--- Symbol table format ---"
for
in
do
"$f"
continue
if
'\\section{符号说明}\|\\section.*符号'
"$f"
then
if
'\\begin{longtable}'
"$f"
then
echo
"✅ 符号说明使用 longtable"
elif
'\\begin{table}'
"$f"
then
echo
"❌ 符号说明仍用 table(应转 longtable 防分页)"
1
fi
fi
done
# 20. 正文长表格检查(>15行应用 longtable)
echo
"--- Long table check ---"
for
in
do
"$f"
continue
echo
"$(basename $f)"
'symbol\|appendix\|A_code'
continue
if
'\\begin{tabular}'
"$f"
then
'/\\begin\{tabular\}/,/\\end\{tabular\}/'
"$f"
'&'
echo
"$ROW_COUNT"
echo
"❌ $(basename $f): $ROW_COUNT 行表格应转 longtable"
1
fi
done
# 21. babel[english] 冲突
echo
"--- babel check ---"
if
'ctex\|cumcmthesis\|gmcmthesis'
then
'babel.*english'
echo
"❌ 中文论文有 babel[english]"
1
echo
"✅ 无 babel 冲突"
fi
# 22. 数值一致性(JSON vs 论文)
echo
"--- Numerical consistency ---"
if
then
"
import json, re, os
with open('figures/all_results.json','r',encoding='utf-8') as f: results=json.load(f)
def extract(obj,p=''):
n={}
if isinstance(obj,dict):
for k,v in obj.items(): n.update(extract(v,f'{p}.{k}'))
elif isinstance(obj,(int,float)) and not isinstance(obj,bool):
if 0.001<abs(obj)<1e10: n[p]=obj
return n
jn=extract(results); pn=set()
for tf in sorted(os.listdir('paper/sections')):
if not tf.endswith('.tex'): continue
with open(f'paper/sections/{tf}','r',encoding='utf-8',errors='ignore') as f: t=f.read()
for m in re.finditer(r'(?<![a-zA-Z])(\d+\.?\d+)(?![a-zA-Z_{}])',t):
try: pn.add(float(m.group(1)))
except: pass
miss=sum(1 for k,v in jn.items() if not any(abs(p-v)<abs(v)*0.01+0.001 for p in pn) and any(w in k.lower() for w in ['rmse','r2','accuracy','f1','objective','optimal','best']))
print(f'❌ {miss} key values missing in paper' if miss else '✅ Key values consistent')
import sys; sys.exit(1 if miss>3 else 0)
"
1
fi
# 22.5 "太完美"结果检测(AI 编造或过拟合特征)
echo
"--- Unrealistic values check ---"
if
then
"
import json
with open('figures/all_results.json','r',encoding='utf-8') as f: data=json.load(f)
suspicious = []
def check(name, val):
if not isinstance(val,(int,float)) or isinstance(val,bool): return
key = name.lower()
if any(w in key for w in ['r2','r_squared','accuracy','acc','precision','recall','f1','auc']) and val > 0.999:
suspicious.append(f'{name}={val:.4f} 过于完美(>0.999)')
if any(w in key for w in ['rmse','mae','mse','loss']) and val == 0:
suspicious.append(f'{name}=0 完美误差')
if ('p_value' in key or 'pvalue' in key) and val == 0:
suspicious.append(f'{name}=0 完美显著')
if any(w in key for w in ['improvement','speedup','gain','提升']) and val > 10:
suspicious.append(f'{name}={val} 提升过大({val*100:.0f}%)')
def walk(obj, path=''):
if isinstance(obj,dict):
for k,v in obj.items(): walk(v, f'{path}.{k}')
elif isinstance(obj,list):
for i,v in enumerate(obj): walk(v, f'{path}[{i}]')
else: check(path, obj)
walk(data)
if suspicious:
print(f'🚩 {len(suspicious)} 处可疑的完美结果(可能过拟合或数值编造):')
for s in suspicious[:5]: print(f' {s}')
print(' 需在论文中说明合理性,或回到 comp-code 检查数据泄漏')
else:
print('✅ 数值合理性通过')
"