From 149a7f215cf441c0063d3de41f55f46ed06584c0 Mon Sep 17 00:00:00 2001 From: Mars Liu Date: Wed, 8 Dec 2021 23:17:55 +0800 Subject: [PATCH] add rfc 002 --- rfc/rfc_002.md | 186 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 rfc/rfc_002.md diff --git a/rfc/rfc_002.md b/rfc/rfc_002.md new file mode 100644 index 0000000..5db192e --- /dev/null +++ b/rfc/rfc_002.md @@ -0,0 +1,186 @@ +# 习题和相关工具 + + +技能树习题使用 markdown 定义。工具脚本会根据习题的结构生成对应的元信息。 + +## 习题的格式 + +习题是一个 markdown 文本,当前仅支持单选题,习题文本需要描述题干、习题答案、选项。对于设计为生成 notebook 的习题,还可以携带用于填充 +notebook 的模板或 aop 章节。 + +### 题干 + +一个典型的习题结构如下: + +````markdown +# Hello World + +以下 `Hello World` 程序中,能够正确输出内容的是: + +## 答案 + +```java + +public class App { + public static void main(String[] args){ + System.out.println("Hello World"); + } +} +``` + +## 选项 + +### A + +```java +public class App { + public int main(){ + System.out.printf("Hello World"); + return 0; + } +} +``` + +### B + +```java +public class App { + public static void main(String[] args){ + println("Hello World"); + } +} +``` + +### C + +```java +import stdout + +public class App { + public int main(){ + print("Hello World\n"); + return 0; + } +} + +``` + +```` + +这个习题文件分为几个部分。 + +首先是一级标题,这个标题会出现在最终的习题页面。作为题目的标题。 + +然后是习题的描述,习题的描述可以有多段,除了文本,也可以是有序号或无序号的列表,也可以是代码段等合法的 markdown 格式。 + +目前题干不支持内部的子结构,这是出于简化设计的考虑。与下面介绍的习题章节结构设计有关。 + +### 习题的答案 + +习题答案是一个二级标题为 `答案` 的章节 + +```markdown +## 答案 + +答案内容 +``` + +这个内容应紧跟着习题描述,在这之前可能有可选的模板或 aop 定义,但是不会再有其它内容,关于用来生成notebook的模板或aop结构,我们放在后面讨论。 + +答案的标题一定是 `答案`,这个二级标题不会出现在问题页。如果习题没有包含答案,后续处理时会报错。 + +### 习题的选项 + +在答案只有,应该有一个二级标题,名为 `选项` ,它列举了除正确答案之外的所有被选项。后续的技能树服务会在生成习题页面时,随机选择三个选项,与答案 +一起展示给用户。因此,至少需要三个备选项。选项章节的形态如下: + +````markdown +## 选项 + +### 带有代码段的选项 + +```java +,,, +``` + +### 文本选项 + +这段内容会成为问题页面上的选项 + +### 文本选项 + +选项也可以包含多个段落 + +```` + +原则上,我们鼓励尽可能多的选项,给学习者提供更好的体验。每个选项的三级标题不会出现在题目页,我们可以利用它叙述一些简短的信息。 + +### 习题代码和 notebook + +每个习题的markdown文件,对应一个同名的json文件,例如 `hello.md` ,仓库的维护者会通过工具脚本或钩子生成一个对应的 `hello.json`。 +它的内容如下: + +```json +{ + "type": "code_options", + "author": "ccat", + "source": "hello.md", + "notebook_enable": false, + "exercise_id": "ee4d10ae488b4900835e52d184822962" +} +``` + +这些配置信息可以由程序自动生成,但是有时可能我们需要做一些调整。例如当我们设置 `notebook_enable` 为 `true` 时,技能树服务会为其生成对应的 +notebook 页,这些 notebook 页可以为学习者提供可执行的程序环境。 + +目前 CSDN 的 notebook 服务支持 c、python、java 三种语言,对于一些程序示例,特别是 C 或 Java 代码,可能整个可执行代码放进题目中过于冗长, +因此我们允许将题目中的代码嵌入到预先定义的模板中,组合成完整的可执行代码,再组装成 notebook 单元。而这些代码不需要出现在题目页。 + +为此我们支持两种代码包装形式:模板或 AOP 。 + +如果我们在题干之后,答案之前,插入一个名为 `template` 的章节,那么它的正文中定义的代码会当作模板处理: + +````markdown +## template + +```c +#inlcude + +int main(int argc, char** argv){ + $code +} +``` +```` + +组装 notebook 页时,$code 占位符会被替换成 `答案` 中的代码段。这个占位符形式遵循 python 标准库 `string.Template` 类型的模板语法。 + +一些代码示例,可能需要更复杂的代码"外壳",把它分成在 `code` 之前和之后两部分更合适,此时我们可以使用 `aop` 章节。 + +````markdown +## aop + +### before + +```java +package app; +public class Main{ + public static void main(String[] argv){ +``` + +### after + +```java + System.out.println("hello"); + } +} + +``` + +```` + +章节标题 aop 来自 Java 的`面向方面编程(AOP)`。这里的三级标题 before 和 after 如果存在,它们的正文内容会在组装 notebook 页时出现在答案 +的前面和后面。 + +AOP 章节可以只包含 before 和 after 中的某一个,并不需要两部分都齐全。 + +AOP 或模板章节,需要放在题干之后,答案之前。未来可能会调整位置,允许写到习题文本的最后。 \ No newline at end of file -- GitLab