#!/usr/bin/env bash
# gen_chapter.sh — 《人工智能基础》某章 知识库/问答库 逐节生成（调用本机 grok）
# 用法: gen_chapter.sh "<章目录名>" "<节号前缀>" <语料文件> [附加语料...]
set -u
BASE="/home/zyw/Downloads/dl-hub/01-AI课程设计项目/知识库问答库"
CHAPTER="$1"; PREFIX="$2"; CORPUS="$3"; EXTRA="${4:-}"
KB_DIR="$BASE/知识库/$CHAPTER"; QB_DIR="$BASE/问答库/$CHAPTER"
mkdir -p "$KB_DIR" "$QB_DIR"
S=~/.dsh/skills/grok-run/scripts/grok-run.sh
LOG="$KB_DIR/生成日志.md"
echo "# 生成日志：$CHAPTER" > "$LOG"
echo "" >> "$LOG"
TOTAL_Q=0; NODE_OK=0; NODE_FAIL=0

# 从 目录.txt 提取本章节（形如 "5.1.1|计算机视觉的概念与发展历程"；匹配 5/.5.1/5.1.1 等）
grep -E "^${PREFIX//./\\.}[0-9.]*\|" "$BASE/目录.txt" > /tmp/ch-$$.list
while IFS='|' read -r nid name; do
  [ -z "$nid" ] && continue
  nid=$(echo "$nid" | tr -d ' ')
  name=$(echo "$name" | tr -d ' ')
  fname="$nid-$name.md"
  if [ -f "$KB_DIR/$fname" ] && [ -f "$QB_DIR/$fname" ]; then
    echo "跳过（已存在）: $fname"; continue
  fi
  echo "== 生成 [$CHAPTER] $fname =="
  PROMPT="你是AI课程内容专家。请阅读语料 $BASE/课程语料/$CORPUS 与 $BASE/课程语料/$EXTRA，遵循 $BASE/生成规范.md，为小节「$name」（节号$nid，属于$CHAPTER）生成内容。输出必须含两个区块，先「# 知识库」后「# 问答库」：知识库 400-800字（概念、关键点、示例、结尾给##关键要点列表）；问答库至少10题（单选/多选/判断/简答，含难度、选项、答案、解析；代码题的代码必须语法正确可运行，用代码块包裹）。数字/人名/年份以语料为准，禁止编造教材不存在的引用。不要输出思考前言，直接以「# 知识库」开头输出。不要写入任何文件，直接在回复中输出内容。"
  "$S" "$PROMPT" --out "/tmp/ch-$$-tmp.md" --max-turns 20 2>>"$LOG" || { echo "  !! grok失败: $fname" >> "$LOG"; NODE_FAIL=$((NODE_FAIL+1)); continue; }
  # 拆分两区块（用 Python 统一完成拆分+写文件+题数统计）
  PYRES=$(python3 - "$nid" "$name" "$KB_DIR" "$QB_DIR" "/tmp/ch-$$-tmp.md" <<'PY'
import sys, re, os
nid,name,kbd,qbd,tmpf=sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5]
txt=open(tmpf,encoding='utf-8').read()
# 去掉前言：取最后一个 "# 知识库" 作为正式内容起点
i_kb=txt.rfind('# 知识库')
content=txt[i_kb:] if i_kb>=0 else txt
m=re.split(r'#\s*问答库', content, maxsplit=1)
kb=m[0].strip().lstrip('\n') if m else ''
qb=m[1].strip() if len(m)>1 else ''
# 知识库去掉自身的前缀标题里多余的 #（保留小节H1）
open(os.path.join(kbd,f'{nid}-{name}.md'),'w',encoding='utf-8').write('# '+nid+' '+name+'\n\n'+kb+'\n')
open(os.path.join(qbd,f'{nid}-{name}.md'),'w',encoding='utf-8').write('# '+nid+' '+name+'（问答库）\n\n'+qb+'\n')
nq=len(re.findall(r'^\d+\.\s*【', qb, re.M))
print(nq)
PY
)
  qn=$(echo "$PYRES" | tail -1)
  if [ "$qn" -ge 10 ] 2>/dev/null; then
    NODE_OK=$((NODE_OK+1)); TOTAL_Q=$((TOTAL_Q+qn))
    echo "  OK: $qn 题" | tee -a "$LOG"
  else
    echo "  !! 题数不足($qn)，重试一次" | tee -a "$LOG"
    "$S" "$PROMPT 注意：上一次输出题目数不足10，请确保至少10题。不要输出思考前言，直接以「# 知识库」开头输出。" --out "/tmp/ch-$$-tmp.md" --max-turns 20 2>>"$LOG" || true
    PYRES=$(python3 - "$nid" "$name" "$KB_DIR" "$QB_DIR" "/tmp/ch-$$-tmp.md" <<'PY'
import sys, re, os
nid,name,kbd,qbd,tmpf=sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5]
txt=open(tmpf,encoding='utf-8').read()
i_kb=txt.rfind('# 知识库')
content=txt[i_kb:] if i_kb>=0 else txt
m=re.split(r'#\s*问答库', content, maxsplit=1)
kb=m[0].strip().lstrip('\n') if m else ''
qb=m[1].strip() if len(m)>1 else ''
open(os.path.join(kbd,f'{nid}-{name}.md'),'w',encoding='utf-8').write('# '+nid+' '+name+'\n\n'+kb+'\n')
open(os.path.join(qbd,f'{nid}-{name}.md'),'w',encoding='utf-8').write('# '+nid+' '+name+'（问答库）\n\n'+qb+'\n')
nq=len(re.findall(r'^\d+\.\s*【', qb, re.M))
print(nq)
PY
)
    qn2=$(echo "$PYRES" | tail -1)
    if [ "$qn2" -ge 10 ] 2>/dev/null; then NODE_OK=$((NODE_OK+1)); TOTAL_Q=$((TOTAL_Q+qn2)); else NODE_FAIL=$((NODE_FAIL+1)); echo "  !! 仍不足，标记失败" >> "$LOG"; fi
  fi
done < /tmp/ch-$$.list
rm -f /tmp/ch-$$.list
echo "" >> "$LOG"
echo "## 总结: 成功 $NODE_OK 节 / 失败 $NODE_FAIL 节 / 总题数 $TOTAL_Q" | tee -a "$LOG"
echo "DONE $CHAPTER"