#!/usr/bin/env python3
"""
合作阅读（core_reading_order）多步 prompt 模板。

生成流水线:
  Step 1: 阅读材料格式化  (中间步骤, 文本输出)
  Step 2: 学习材料格式化  (中间步骤, 文本输出)
  Step 3: 学习过程配置    (中间步骤, 文本输出)
  Step 4: taskData        (最终JSON)
  Step 5: textData        (最终JSON)
  Step 6: sequenceData    (最终JSON)
  Step 7: learningData    (最终JSON)

占位符使用 $xxx$ 风格，避免与 prompt 中的 {} 冲突。
"""

# ============================================================
# Step 1: 阅读材料格式化
# 输入: $材料配置$
# 输出: 格式化后的材料文本
# ============================================================

STEP1_FORMAT_READING_MATERIAL = r"""# 任务描述
按顺序依次转换 {材料配置} 中的 每段材料 。 注意: 只做格式转换，不要增加或改动文本内容！！

# 输入格式参考
 {材料配置}一般为以下格式:
```
 # 材料 1
## 材料类型
手环|一张纸|一本书 等
## 材料内容
1. 标题
... ...

2. 正文
... ...
```

# 输出格式
```
# 材料1
类型：手环|一张纸|一本书 等 (如果未提供则写"默认")
标题：xxx (如果未提供则写"无")
正文:
xxx
```
# 转换要求
## 单个类型的文本转换规则
说明: 换行用<br>体现。

1.副标题类型
原始:
```
副标题：XXXXXXXXXX
```
转换后:
```
## XXXXXXXXXX
```
2. 有序列表类型
原始:
```
1. XXXXXXXXXX
2. XXXXXXXXXX
3. XXXXXXXXXX
```
转换后:
```
1. XXXXXXXXXX<br>2. XXXXXXXXXX<br>3. XXXXXXXXXX
```
3.无序列表类型
原始:
```
- XXXXXXXXXX
- XXXXXXXXXX
- XXXXXXXXXX
```
转换后:
```
- XXXXXXXXXX<br>- XXXXXXXXXX<br>- XXXXXXXXXX
```
4.图片类型
严格转换为以下格式(**要使用英文冒号:及英文逗号,如果原始输入中是中文冒号"："，也要转为英文":"**)：
单个图片(多个图片之间有其他文本片段，也要逐个解析，不能合并):
```
图片:[图片1名称]<br>...图片:[图片2名称]<br>...
```
如果是连续的多个图片类型，且中间没有其他文本片段，则合并:
```
图片:[图片1名称,图片2名称]
```

5.表格类型
*默认类型，所有列等宽*
原始:
```
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
```
转换后:
```
| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |
```

*特殊类型，包含table1标注*
原始:
```
| #table_1
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
```
转换后:
```
| #table_1<br>| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |
```

6.分栏类型:
原始:
```
&
# 标题1
xxx
# 标题2
xxx
&
```
转换后:
```
&<br># 标题1<br>xxx<br># 标题2<br>xxx<br>&
```

7.引用类型
原始:
```
引用：XXXXXXXXXX
```
转换后:
```
> XXXXXXXXXXX
```

## 多类型文本的拼接规则
1.在每个类型片段段落的开始位置，添加<sp>标记。
2.如果材料内容为连续的普通正文类型段落，不需添加<sp>标记。并仅在段落间添加<br>。

# 输出样例
以下是一些参考输出样例:
样例1
```
# 材料1
类型：默认
标题: A guide for Planet Vala
正文:
<sp>Going on a journey to a far planet VALA is a big adventure (冒险) ! A few special things are recommended (推荐) to make your journey easier.<br>1. abcdefg<br>2. hijklmn<br>3. opqrst<br><sp>## A Camera<br>First, you should pack a camera. A camera can let you take pictures of all the amazing things in space and on planet VALA.<br>- uvwxyz<br>- 012345<br>- 678910<br><sp>## A Personal Weapon<br>One more thing you should bring is a personal weapon like a small knife. It sounds somehow weird (奇怪), but this will keep you safe and less scared when dangerous things happen during the journey.<br><sp>图片:[0000001_文件名]<br><sp>| #table_1<br>| Time | 任务一 | 任务二 |<br>| 08:00 | She starts at 8 in the morning by practicing the piano.  | She starts at 8 in the morning by practicing the piano.  |<br>| 14:00 | She practices her dance moves. Dancing is an important part of her shows. | She practices her dance moves. Dancing is an important part of her shows. |<br><sp>&<br># This is column title 1<br>Going on a journey to a far planet  VALA is a big adventure (冒险) ! <br>1. abcdefg<br>2. hijklmn<br>3. opqrst<br># This is column title 2<br>A few special things are recommended (推荐) to make your journey easier.<br>- uvwxyz<br>- 012345<br>- 678910<br>&<br><sp>> Sky Street is having a big treasure hunt! It's a fun game with lots of surprises. Everyone can join and have a great time.<br>

# 材料2 (如果有)
... ...
```

样例2
```
# 材料1
标题: Summer Plan - Skylar
正文:
<sp>This is my plan for the summer holiday.<br>
<sp>| #table_1<br>
| Date | What I'm Going To Do |<br>
| 7.15-8.4 | Going to Scholar City with my parents (Repair my camera before leaving!).|<br>
| 8.5-8.18 | Stay at home to prepare for my return to Planet Vala. |<br>
| 8.19 | Meet my classmates at the airport, and go back to Vala Academy together. |<br>
<sp>## P.S.<br>
If there's an emergency, send me a message anytime to contact me.<br>

# 材料2
标题: Summer Plan - Otis
正文:
<sp>I'm going to spend my holiday with my friends. I sent a message to my friends and agree on a meeting time.<br>
<sp>| #table_1<br>
| Date | What I'm Going To Do |<br>
| 7.15-7.21 | Go back to Mechanic City and meet Lee.|<br>
| 7.22-7.28 | Chat with Linda and get some advice. |<br>
| 7.29-8.4 | Hang out with William.|<br>
| 8.5-8.18 | Get ready for going back to Planet Vala .|<br>
| 8.19 | Meet my friends at the airport, and go back to Vala Academy together. |<br>
<sp>I believe all these good time will become my precious memory.<br>
```


# 输入
{材料配置}:
$材料配置$

# 输出
现在按照以上要求，直接输出转换后的阅读材料。
如果 {材料配置}中 无有效文本，则直接输出"无"。"""


# ============================================================
# Step 2: 学习材料格式化
# 输入: $材料配置$  (same raw material, but paragraph-based output)
# 输出: 段落化的学习材料
# ============================================================

STEP2_FORMAT_LEARNING_MATERIAL = r"""# 转换要求
按顺序依次转换 {材料配置} 中的 每个段落 。 注意: 只对"正文"做格式转换，不要增加或改动文本内容！！
整体样式：
```
# 段落1
重点词汇: xxx
正文:
---
格式转换之后的文本
---
```

## 单个类型的文本转换规则
说明: 换行用<br>体现。
1.副标题类型
原始: 副标题：XXXXXXXXXX
转换后: ## XXXXXXXXXX
2. 有序列表类型
原始:
```
1. XXXXXXXXXX
2. XXXXXXXXXX
3. XXXXXXXXXX
```
转换后:
```
1. XXXXXXXXXX<br>2. XXXXXXXXXX<br>3. XXXXXXXXXX
```
3.无序列表类型
原始:
```
- XXXXXXXXXX
- XXXXXXXXXX
- XXXXXXXXXX
```
转换后:
```
- XXXXXXXXXX<br>- XXXXXXXXXX<br>- XXXXXXXXXX
```
4.图片类型
严格转换为以下格式(**要使用英文冒号:及英文逗号,如果原始输入中是中文冒号"："，也要转为英文":"**)：
单个图片(多个图片之间有其他文本片段，也要逐个解析，不能合并):
```
图片:[图片1名称]<br>...图片:[图片2名称]<br>...
```
如果是连续的多个图片类型，且中间没有其他文本片段，则合并:
```
图片:[图片1名称,图片2名称]
```
5.表格类型
*默认类型，所有列等宽*
原始:
```
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
```
转换后:
```
| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |
```
*特殊类型，包含table1标注*
原始:
```
| #table_1
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
| XXXXX | XXXXX | XXXXX |
```
转换后:
```
| #table_1<br>| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |<br>| XXXXX | XXXXX | XXXXX |
```
6.分栏类型:
原始:
```
&
# 标题1
xxx
# 标题2
xxx
&
```
转换后:
```
&<br># 标题1<br>xxx<br># 标题2<br>xxx<br>&
```
7.引用类型
原始:
```
引用：XXXXXXXXXX
```
转换后:
```
> XXXXXXXXXXX
```
## 多类型文本的拼接规则
1.在每个类型片段的开始位置，添加<sp>标记。
2.如果材料内容为连续的普通正文类型内容，不需添加<sp>标记。并仅在段落间添加<br>。


# 输出样例
以下是部分输出样例(为方便你参考，下面的正文一般比实际配置长很多，可能包含多类型):
样例1
```
# 段落1
重点词汇: xxx
正文:
---
<sp>Going on a journey to a far planet VALA is a big adventure (冒险) ! A few special things are recommended (推荐) to make your journey easier.<br>1. abcdefg<br>2. hijklmn<br>3. opqrst<br><sp>## A Camera<br>First, you should pack a camera. A camera can let you take pictures of all the amazing things in space and on planet VALA.<br>- uvwxyz<br>- 012345<br>- 678910<br><sp>## A Personal Weapon<br>One more thing you should bring is a personal weapon like a small knife. It sounds somehow weird (奇怪), but this will keep you safe and less scared when dangerous things happen during the journey.<br><sp>图片:[0000001_文件名]<br><sp>| #table_1<br>| Time | 任务一 | 任务二 |<br>| 08:00 | She starts at 8 in the morning by practicing the piano.  | She starts at 8 in the morning by practicing the piano.  |<br>| 14:00 | She practices her dance moves. Dancing is an important part of her shows. | She practices her dance moves. Dancing is an important part of her shows. |<br><sp>&<br># This is column title 1<br>Going on a journey to a far planet  VALA is a big adventure (冒险) ! <br>1. abcdefg<br>2. hijklmn<br>3. opqrst<br># This is column title 2<br>A few special things are recommended (推荐) to make your journey easier.<br>- uvwxyz<br>- 012345<br>- 678910<br>&<br><sp>> Sky Street is having a big treasure hunt! It's a fun game with lots of surprises. Everyone can join and have a great time.<br>
---
# 段落2
... ...
```

样例2
```
# 段落1
重点词汇: xxx
正文:
---
<sp>This is my plan for the summer holiday.<br>
<sp>| #table_1<br>
| Date | What I'm Going To Do |<br>
| 7.15-8.4 | Going to Scholar City with my parents (Repair my camera before leaving!).|<br>
| 8.5-8.18 | Stay at home to prepare for my return to Planet Vala. |<br>
| 8.19 | Meet my classmates at the airport, and go back to Vala Academy together. |<br>
<sp>## P.S.<br>
If there's an emergency, send me a message anytime to contact me.<br>
---
# 段落2
... ...
```

# 输入
{材料配置}:
$材料配置$

# 输出
现在按照以上要求，直接输出转换后的阅读材料。
如果 {材料配置}中 无有效文本，则直接输出"无"。"""


# ============================================================
# Step 3: 学习过程配置
# 输入: $文章材料$ (Step1输出), $学习内容$ (Step2输出), $专有词汇$
# 输出: 段落化的学习过程（含题目）
# ============================================================

STEP3_LEARNING_PROCESS = r"""# 任务
参考 {文章材料} 整体的语义和设计。 对 {学习内容} 中 所圈定的 段落，为每个段落生成学习题目。

# 输出格式及内容要求
每个段落的输出按照以下格式:
```
# 段落1
## 段落内容(直接抽取{学习内容} 中对应的段落"正文"原文，不要修改任何文本或符号)
---
xxx
---
## 互动题目
(要求:均以Brainy的口吻给出，Brainy是我们设计的助教的名字。)
Brainy: 讲解段落中的重点词汇。注意，重点词汇要选择常见的实词，不要选择 人名、地名、机器名 等 专有名词。
(每个题目给出两个选项，其中一个选项为正确选项，并标出"正确"，位置随机。每个选项，要给出一句Brainy口吻的反馈。)
1. 句意选择题
Brainy：题干内容 (考察段落中包含了重点词汇的句子，不要过长.干扰项围绕重点词汇设计)
- 选项1内容。
  Brainy：选项1反馈
- 选项2内容。 [正确]
  Brainy：选项2反馈

举例:
1)
重点词汇:digging
正确选项:他们在永冻城的冰洞中秘密挖掘思维晶石。
干扰项: 他们在永冻城的冰洞中秘密寻找思维晶石。
2)
重点词汇:switch
正确选项:按下地上的黄色开关。
干扰项: 按下地上的黄色面板。

2. 段落大意题（可选。如果段落内容较短，则不提供此题目）
Brainy：题干内容 （询问段落内容整体的语义信息。干扰项围绕段落的关键语义设计。）
- 选项1内容。  [正确]
  Brainy：选项1反馈
- 选项2内容。
  Brainy：选项2反馈

# 段落2
... ...
# 完结反馈
Brainy:  以Brainy的口吻给出学习流程整体结束的反馈。
```

# 其他规则
在输出的文本中，如果涉及英文专有词汇的中文翻译，当该英文词汇在 {专有词汇} 表中时， 请使用  {专有词汇}  表中的中文翻译。

# 输出样例
以下是一些参考配置样例

样例1
```
# 段落 1
## 段落内容
---
<sp>Going on a journey to a far planet VALA is a big adventure (冒险) ! A few special things are recommended (推荐) to make your journey easier.<br>1. xxx <br>2. xxx <br>3. xxx <br><sp>
---
## 互动题目
Brainy：我们来认识一下这段话中的关键单词 journey。journey 的意思是旅程、旅行。长途旅行可以说 long journey。
1. 句意选择题
Brainy：接下来，我们来看下包含 journey 的句子 Going on a journey to a far Planet Vala is a big adventure! 是什么意思呢？
- 去瓦拉星球冒险是一次很好的旅行。
  Brainy：你把句子的前后顺序弄反了，去瓦拉旅行是一次冒险，而不是讲冒险是旅行。再确认下正确答案吧。
- 去遥远的瓦拉星球的旅行是一次巨大的冒险。[正确]
  Brainy：完美回答！你已经掌握了句中的关键单词 journey 和整个句子的意思了～
2. 段落大意题
Brainy：了解了关键单词和关键句子的意思，那我们来一起看看这一段主要在说什么呢？你觉得作者想告诉我们关于 journey 的什么信息呢？
- 每个人都必须带很多很多行李去 VALA。
  Brainy：不太对哦，文中说的是 a few special things ，不是"大包小包"。再读一读试试看！
- 去 VALA 星球是一场大冒险，建议带上一些特别的物品。[正确]
  Brainy：太棒了！你抓住了 big adventure 和 special things 这两个重点！
# 段落 2
## 段落内容
---
You also need a suitcase, and it has to be a small one, under 20 inches. A small suitcase is easy for us to carry and it won't take up too much space on the spaceship. You can put all your important things inside, like clothes or digital devices.<br>
---
## 互动题目
Brainy：本段围绕一个关键词 suitcase 展开，你认识这个单词吗？suitcase 是行李箱的意思。东西多时，我们需要 a large suitcase 来装行李；少时，我们需要 a small suitcase。
1. 句意选择题
Brainy：接下来我们看看包含 suitcase 的句子 You also need a suitcase, and it has to be a small one, under 20 inches. 你知道它是什么意思吗？
- 你需要一个背包，应该小一点儿，在20 寸以内。
  Brainy：背包的英文表达是 backpack 哦，并不是我们讲的 suitcase，再认真看看正确的释义吧
- 你需要一个行李箱，必须小一点儿，在20寸以内。[正确]
  Brainy：完美回答！你已经掌握了文中的关键单词 suitcase 和关键句子的意思了～

2. 段落大意题
Brainy：下面，让我们来看看这一段主要在讲什么。
- 建议带一个小于 20 英寸的行李箱，方便携带，也不会占用飞船空间。[正确]
  Brainy：答得好！尺寸、原因和场景你都记住啦！
- 数码设备不能带上飞船。
  Brainy：小心看哦～文中明明说可以放 digital devices 呢！再仔细看看正确的释义吧！
# 完结反馈
Brainy：太棒了！你已经完成了全部的学习流程！
```

# 输入
{文章材料}：
$文章材料$

{学习内容} ：
$学习内容$

{专有词汇}:
$专有词汇$

# 输出
按照 # 任务 要求，输出完整的配置文本。
如果 {文章材料} 中不包含有效的文章信息，则直接输出 "无"。"""


# ============================================================
# Step 4: taskData (最终JSON)
# 输入: $ID$, $任务配置$, $通关知识$, $角色配置$
# 输出: 单行JSON
# ============================================================

STEP4_TASK_DATA = r"""# 字段内容要求
{
    "cType": "core_reading_order",
    "cId": {ID},
    "title": {任务配置}中的任务名称,
    "sceneDesc": {任务配置}中的任务背景,
    "img": "",
    "key"({通关知识}中的知识定义): [
        {
            "desc": 类型名称定义,
            "keyList": [
                {
                    "type": "default",
                    "content": 知识点内容,
                    "desc": 知识点解释
                },
                 ... ...
            ]
        },
        ...
    ],
    "resourceMapping"(抽取出{角色配置}中的全部 name:id映射 可为空。id必须为int类型):
    {
    样例:
    "Tom":43,
    "Jerry":10
    }
}

# 输出格式
- 整个输出必须在一行内完成，**不要换行**。
- **不要使用 markdown 代码块**（如 ```json）包裹输出。

样例:
{"cType":"core_reading_order","cId":"","title":"和 Sarah 一起阅读《星际旅行须知》","sceneDesc":"因为Tommy的原因，电梯发生了故障。为了从电梯里脱困，你通过紧急对讲系统联系到专业电梯工程师。现已收到工程师发送的《电梯脱困指南》，请仔细研读文档中的说明，按指南进行自救，确保安全脱离困境。","img":"","key":[{"desc":"物品类","keyList":[{"type":"default","content":"Journey","desc":"n. 旅行"},{"type":"default","content":"Adventure","desc":"n. 冒险"}]}],"resourceMapping":{}}

# 输入
{ID}:
$ID$

{任务配置}：
$任务配置$

{通关知识}：
$通关知识$

{角色配置}:
$角色配置$

# 输出
现在基于输入字段和格式要求，生成***可以直接解析的单行json文本***，***注意前后不要输出任何额外符号！！！***
如果{任务配置}中没有有效文本，则输出"无"。"""


# ============================================================
# Step 5: textData (最终JSON)
# 输入: $ID$, $材料正文$ (Step1输出), $互动题目$ (Step3输出), $角色配置$
# 输出: 单行JSON
# ============================================================

STEP5_TEXT_DATA = r"""# 字段内容要求
{
    "text"(每个元素，依次对应，{材料正文}中 #材料1 、#材料2 ... 的内容部分): [
        {
            "textType": "xxx",
            "textTitle":  # 材料1  的  标题(如果材料中标题为"无"，则输出  "textTitle":""),
            "textBody": 直接抽取 # 材料1 的"正文"部分内容。 去除其中的"\n"。 要保证输出的json可以合法解析。如果文本内容本身有双引号，需要加转义符。例如: "I am \"cool\"."。保留其他全部文本及<xxx>符号。不要做改动。
        },
        {xxx},
        ... ...
    ],
    "question"(基于{互动题目}依次抽取. 每个item对应1道题目): [
        {
            "type": "npc",
            "npcName": "xxx",
            "content": "xxx",
            "optionList": [
                {
                    "option": "xxx",
                    "feedback": {
                        "type": "npc",
                        "npcName": "xxx",
                        "content": "xxx"
                    }
                },
                {
                    "option": "xxx",
                    "feedback": {
                        "type": "npc",
                        "npcName": "xxx",
                        "content": "xxx"
                    }
                }
            ],
            "answer": [int],
            "meaning": 题目内容中的 "学习意义",
            "explain": 题目内容中的 "题目解析"
        },
        ... ...
    ]
}

补充规则:
1. 关于*npcName*字段的特殊规定：
a.文本本身要严格与输入文本中一致，包括大小写。
b. 如果 {角色配置}非空，且其中提供了npcName名字对应的id，则npcName字段的取值都要追加id，用#连接。如未提供该npcName对应的id，则不需追加。
c.以上规则仅限于npcName字段。不适用于其他字段的文本(content、desc 等)。
例如:
---
角色配置: Tom: 45
则: npcName: Tom#45
      content: I will tell Tom.
---
角色配置: Jerry: 45
则: npcName: Tom
      content: Jerry is my sister.
---

2. textType 映射规则: "手环"->"Band","一张纸"->"Paper","一本书"->"Book","电子屏"->"Lcd","默认"->"Default"。 未提供则填写"Default"

# 输出格式
- 整个输出必须在一行内完成，**不要换行**。
- **不要使用 markdown 代码块**（如 ```json）包裹输出。


样例:
{"text": [{"textType": "Default", "textTitle": "Checklist for the Journey to Planet Vala", "textBody": "That's xxx xxx"}], "question": [{"type": "npc", "npcName": "Sarah", "content": "First off, we need to make sure robots aren't too big. Do you know how big the robots can be in the competition?", "optionList": [{"option": "Robots must be built no larger than 50 cm", "feedback": {"type": "npc", "npcName": "Sarah", "content": "Opps! You need to read carefully and do it again!"}}, {"option": "Robots must be built no larger than 10 cm", "feedback": {"type": "npc", "npcName": "Sarah", "content": "Nice! You are good at finding information!"}}], "answer": [1], "meaning": "能理解文章的整体结构与主旨信息", "explain": ""}]}


# 输入
{ID}:
$ID$

{材料正文}:
$材料正文$

{互动题目}:
$互动题目$

{角色配置}:
$角色配置$

# 输出
现在基于输入字段和格式要求，生成***可以直接解析的单行json文本***，***注意前后不要输出任何额外符号！！！***
如果{材料配置}中没有有效文本，则输出"无"。"""


# ============================================================
# Step 6: sequenceData (最终JSON)
# 输入: $ID$, $流程编排$, $角色配置$
# 输出: 单行JSON
# ============================================================

STEP6_SEQUENCE_DATA = r"""# 字段内容要求
基于 {流程编排} ， 整理成sequence序列。

保持原有  {流程编排} 中的顺序，根据不同类型分别处理:
{
  "sequence": [
    { "text": [int] },
    { "dialog": { "type": "npc", "npcName": "xxx", "content": "xxx" } },
   { "dialog": { "type": "user", "content": "..." } },
    { "question": [int] },
    ... ...
}

补充规则:
1. 关于*npcName*字段的特殊规定：
a.文本本身要严格与输入文本中一致，包括大小写。
b. 如果 {角色配置}非空，且其中提供了npcName名字对应的id，则npcName字段的取值都要追加id，用#连接。如未提供该npcName对应的id，则不需追加。
c.以上规则仅限于npcName字段。不适用于其他字段的文本(content、desc 等)。
例如:
---
角色配置: Tom: 45
则: npcName: Tom#45
      content: I will tell Tom.
---
角色配置: Jerry: 45
则: npcName: Tom
      content: Jerry is my sister.
---

2. content 、 desc 字段取值应与原始输入保持一致，不做改动。

3. [材料x] 标记转换为数字索引 x-1，如 [材料1] -> {"text": [0]}
4. [题目x] 标记转换为数字索引 x-1，如 [题目1] -> {"question": [0]}

# 输出格式
- 整个输出必须在一行内完成，**不要换行**。
- **不要使用 markdown 代码块**（如 ```json）包裹输出。

样例1:
{"sequence": [{"text": [0]}, {"dialog": {"type": "npc", "npcName": "Skylar", "content": "Let's start with the basics."}}, {"question": [0]}, {"dialog": {"type": "npc", "npcName": "Otis", "content": "Now, let's talk about Mike Hatton's skills."}}, {"question": [1]}, {"dialog": {"type": "npc", "npcName": "Bob", "content": "Let's focus on Mike Hatton's most famous dish."}}, {"question": [2]}, {"dialog": {"type": "npc", "npcName": "Bob", "content": "Now, let's talk about another dish Mike Hatton is known for."}}, {"question": [3]}]}

样例2:
{"sequence": [{"text": [0]}, {"question": [0]}, {"question": [1]}, {"question": [2]}, {"question": [3]}]}

# 输入
{ID}:
$ID$

{流程编排}:
$流程编排$

{角色配置}:
$角色配置$

# 输出
现在基于输入字段和格式要求，生成***可以直接解析的单行json文本***，***注意前后不要输出任何额外符号！！！***
（如果{流程编排}中没有有效文本，则直接输出"无"。）"""


# ============================================================
# Step 7: learningData (最终JSON)
# 输入: $学习配置$ (Step3输出)
# 输出: 单行JSON
# ============================================================

STEP7_LEARNING_DATA = r"""# 字段内容要求
基于{学习配置}内容抽取为以下结构。
{
        "closing": {
                "type":"npc",
                "content": "xxx",
                "npcName": "Brainy"
        },
        "learningPart"(每个段落为1个item): [{
                "leadIn": {
                        "desc": "xxx"
                },
                "type":"npc",
                "content": "xxx",
                "npcName": "Brainy",
                "learning": [{
                        "answer": [int],
                        "meaning": "xxx",
                        "optionList": [{
                                    "feedback": {
                                            "type":"npc",
                                            "content": "xxx",
                                            "npcName": "xxx"
                                    },
                                    "option": "xxx"
                                },
                                ... ...
                        ],
                        "question": {
                                "type":"npc",
                                "npcName": "Brainy",
                                "content": "xxx"
                        }
                },
                ... ...
                ]
        }]
}
注意:  双引号字符串文本中如果出现英文双引号，需要使用转义符  确保最终输出是合法的json。

说明:
- closing.content: 完结反馈文本
- leadIn.desc: 当前段落的正文内容(直接输出两个"---"中间的内容。不要修改或者增删任何内容，包括标点、空格、特殊符号等。)
- content: 互动题目的引导语
- learning[].answer: 正确答案对应的 optionList 数组索引
- learning[].meaning: 题型（如"句意选择题"、"段落大意题"）
- learning[].optionList[].option: 选项内容。**不要保留正确选项结尾的"[正确]"标记。**

# 输出格式
单行json输出。
- 整个输出必须在一行内完成，**不要换行**。
- **不要使用 markdown 代码块**（如 ```json）包裹输出。

样例:
{"closing":{"type":"npc","content":"太棒了！你已经完成了全部的学习流程！","npcName":"Brainy"},"learningPart":[{"leadIn":{"desc":"Going on a journey to a far planet VALA is a big adventure! A few special things are recommended to make your journey easier."},"type":"npc","content":"我们来认识一下这段话中的关键单词 journey。journey 的意思是旅程、旅行。长途旅行可以说 long journey。","npcName":"Brainy","learning":[{"answer":[1],"meaning":"句意选择题","optionList":[{"option":"去瓦拉星球冒险是一次很好的旅行。","feedback":{"type":"npc","content":"你把句子的前后顺序弄反了，去瓦拉旅行是一次冒险，而不是讲冒险是旅行。再确认下正确答案吧。","npcName":"Brainy"}},{"option":"去遥远的瓦拉星球的旅行是一次巨大的冒险。","feedback":{"type":"npc","content":"完美回答！你已经掌握了句中的关键单词 journey 和整个句子的意思了～","npcName":"Brainy"}}],"question":{"type":"npc","content":"接下来，我们来看下包含 journey 的句子 Going on a journey to a far Planet Vala is a big adventure! 是什么意思呢？","npcName":"Brainy"}},{"answer":[1],"meaning":"段落大意题","optionList":[{"option":"每个人都必须带很多很多行李去 VALA。","feedback":{"type":"npc","content":"不太对哦，文中说的是\"a few special things\"，不是\"大包小包\"。再读一读试试看！","npcName":"Brainy"}},{"option":"去 VALA 星球是一场大冒险，建议带上一些特别的物品。","feedback":{"type":"npc","content":"太棒了！你抓住了 big adventure 和 special things 这两个重点！","npcName":"Brainy"}}],"question":{"type":"npc","content":"了解了关键单词和关键句子的意思，那我们来一起看看这一段主要在说什么呢？你觉得作者想告诉我们关于 journey 的什么信息呢？","npcName":"Brainy"}}]}]}

# 输入
{学习配置}:
$学习配置$

# 输出
现在基于输入字段和格式要求，生成***可以直接解析的单行json文本***，***注意前后不要输出任何额外符号！！！*** 以"{"开始输出。
（如果{学习配置}中没有有效文本，则直接输出"无"。）"""


# ============================================================
# 统一接口
# ============================================================

CORE_READING_STEPS = {
    "step1_format_reading": {
        "prompt": STEP1_FORMAT_READING_MATERIAL,
        "placeholders": ["材料配置"],
        "output_type": "text",
        "description": "阅读材料格式化",
    },
    "step2_format_learning": {
        "prompt": STEP2_FORMAT_LEARNING_MATERIAL,
        "placeholders": ["材料配置"],
        "output_type": "text",
        "description": "学习材料格式化",
    },
    "step3_learning_process": {
        "prompt": STEP3_LEARNING_PROCESS,
        "placeholders": ["文章材料", "学习内容", "专有词汇"],
        "output_type": "text",
        "description": "学习过程配置",
    },
    "step4_task_data": {
        "prompt": STEP4_TASK_DATA,
        "placeholders": ["ID", "任务配置", "通关知识", "角色配置"],
        "output_type": "json",
        "description": "taskData",
    },
    "step5_text_data": {
        "prompt": STEP5_TEXT_DATA,
        "placeholders": ["ID", "材料正文", "互动题目", "角色配置"],
        "output_type": "json",
        "description": "textData",
    },
    "step6_sequence_data": {
        "prompt": STEP6_SEQUENCE_DATA,
        "placeholders": ["ID", "流程编排", "角色配置"],
        "output_type": "json",
        "description": "sequenceData",
    },
    "step7_learning_data": {
        "prompt": STEP7_LEARNING_DATA,
        "placeholders": ["学习配置"],
        "output_type": "json",
        "description": "learningData",
    },
}


def build_step_prompt(step_key, variables):
    """
    构建某一步的完整prompt。

    Args:
        step_key: CORE_READING_STEPS 中的 key
        variables: dict, 占位符名 → 值

    Returns:
        str: 填充后的 prompt
    """
    step = CORE_READING_STEPS[step_key]
    prompt = step["prompt"]
    for ph in step["placeholders"]:
        placeholder = f"${ph}$"
        value = variables.get(ph, "无")
        prompt = prompt.replace(placeholder, str(value))
    return prompt
