README.md 5.9 KB
Newer Older
幻灰龙's avatar
幻灰龙 已提交
1 2
# skill_tree_c

F
feilong 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
## 初始化

```
pip install -r requirement.txt
```


## 目录结构说明

* 技能树`骨架文件`
    * 位置:`data/tree.json` 
    * 说明:该文件是执行 `python main.py` 生成的,请勿人工编辑
* 技能树`根节点`配置文件:
    * 位置:`data/config.json`
    * 说明:可编辑配置关键词等字段,其中 `node_id` 字段是生成的,请勿编辑
* 技能树`难度节点`
    * 位置:`data/xxx`,例如: `data/1.C语言初阶`
    * 说明:
        * 每个技能树有 3 个等级,目录前的序号是必要的,用来保持文件夹目录的顺序
        * 每个目录下有一个 `config.json` 可配置关键词信息,其中 `node_id` 字段是生成的,请勿编辑
* 技能树`章节点`
    * 位置:`data/xxx/xxx`,例如:`data/1.C语言初阶/1.C语言概述`
    * 说明:
        * 每个技能树的每个难度等级有 n 个章节,目录前的序号是必要的,用来保持文件夹目录的顺序
        * 每个目录下有一个 `config.json` 可配置关键词信息,其中 `node_id` 字段是生成的,请勿编辑
* 技能树`知识节点`
    * 位置:`data/xxx/xxx`,例如:`data/1.C语言初阶/1.C语言概述`
    * 说明:
        * 每个技能树的每章有 n 个知识节点,目录前的序号是必要的,用来保持文件夹目录的顺序
        * 每个目录下有一个 `config.json`
            * 其中 `node_id` 字段是生成的,请勿编辑
            * 其中 `keywords` 可配置关键字字段
            * 其中 `children` 可配置该`知识节点`下的子树结构信息,参考后面描述
            * 其中 `export` 可配置该`知识节点`下的导出习题信息,参考后面描述


## `知识节点` 子树信息结构

例如 `data/1.C语言初阶/1.C语言概述/1.C语言发展史/config.json` 里配置对该知识节点子树信息结构:
```json
{
    // ...

    "children": [
        {
        "C语言的起源": {
            "keywords": [
            "C语言的起源",
            "起源",
            "C语言"
            ],
            "children": []
        }
        },
        {
        "C语言的发展与应用": {
            "keywords": [
            "C语言的发展",
            "C语言的应用",
            "发展",
            "应用",
            "C语言"
            ],
            "children": []
        }
        }
    ],
}
```



## `知识节点` 的导出习题编辑

例如 `data/1.C语言初阶/1.C语言概述/1.C语言发展史/config.json` 里配置对该知识节点导出的习题

```json
{
    // ...
    "export": [
        {
            "file": "helloworld.c",
            "variants": "helloworld.json",
            "depends": []
        },
        // ...
    ]
}
```

格式说明:
* `file`: 指定该目录下的习题源文件
* `variants`: 指定习题同名的json选项配置文件,参考下一节
* `depends`: 如果习题依赖同目录下的其他习题源代码,则在此字段里配置依赖的其他习题源文件名

## `知识节点` 的导出习题选项配置编辑

M
Mars Liu 已提交
100
目前我们支持使用 markdown 语法直接编辑习题和各选项。
F
feilong 已提交
101

M
Mars Liu 已提交
102 103 104 105 106 107 108 109 110
首先,编辑知识节点的配置,导出习题:


```json
{
    // ...
    "export": [
        "hellowworld.json"
    ]
F
feilong 已提交
111 112 113 114
}
```


M
Mars Liu 已提交
115
然后在 `data/1.C语言初阶/1.C语言概述/1.C语言发展史/` 下增加一个`helloworld.json`定义文件:
F
feilong 已提交
116 117 118 119


```json
{
M
Mars Liu 已提交
120
    "type": "code_options",
L
luxin 已提交
121
    "author": "ccat",
M
Mars Liu 已提交
122 123
    "source": "helloworld.md",
    "notebook_enable": true
F
feilong 已提交
124 125 126
}
```

M
Mars Liu 已提交
127 128 129 130 131 132 133 134 135
其中 type 字段目前都固定是 `code_options`,notebook_enable 字段决定这个习题是否生成对应的 notebook 。根据具体情况写好其它字段,注意这里 source 的文件名,我们指定了一个 markdwon 文件。现在我们新建一个 HelloWorld.md 并编辑为:


````mardown
# Hello World

以下 `Hello World` 程序中,能够正确输出内容的是:

## 答案
F
feilong 已提交
136 137 138 139

```c
#include <stdio.h>
int main(int argc, char** argv){
M
Mars Liu 已提交
140
    printf("Hello,Wrold!");
F
feilong 已提交
141 142 143 144
    return 0;
}
```

M
Mars Liu 已提交
145 146 147 148
## 选项

### main 函数定义错误

F
feilong 已提交
149 150
```c
#include <stdio.h>
M
Mars Liu 已提交
151 152 153
void main(){
    printf("Hello,Wrold!");
    return 0;
F
feilong 已提交
154 155 156
}
```

M
Mars Liu 已提交
157 158
### Print 函数调用错误

F
feilong 已提交
159 160 161
```c
#include <stdio.h>
int main(int argc, char** argv){
M
Mars Liu 已提交
162 163
    printf("Hello,Wrold!");
    return 0;
F
feilong 已提交
164 165 166
}
```

M
Mars Liu 已提交
167
### Java 风格的导入
F
feilong 已提交
168

M
Mars Liu 已提交
169 170
```c
import stdio;
F
feilong 已提交
171

M
Mars Liu 已提交
172 173 174
int main(int argc, char** argv){
    stdio.printf("Hello,Wrold!");
    return 0;
F
feilong 已提交
175 176 177
}
```

M
Mars Liu 已提交
178
### 函数错误
F
feilong 已提交
179 180 181 182 183 184 185 186

```c
#include <stdio.h>
int main(int argc, char** argv){
    print("Hello,Wrold!");
    return 0;
}
```
M
Mars Liu 已提交
187 188 189 190 191 192 193 194 195 196 197
````

### 增强信息

为了编写习题和生成 notebook 的需要,markdown 解释器支持两种模板能力,如果我们在答案之前,有一个名为 aop 的二级标题:

````markdown

## aop

### before
F
feilong 已提交
198 199

```c
M
Mars Liu 已提交
200
print("hello world");
F
feilong 已提交
201 202
```

M
Mars Liu 已提交
203 204
### after

F
feilong 已提交
205
```c
M
Mars Liu 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
main(0, NULL);
```
````

那么在创建notebook的时候,before 会插入到源代码前一个单元,after 则会插入到源代码后。aop 章节可以只包含 before 或 after 中的某一个,也可以两个都有。

另一些情况下,我们可能需要把各个选项中重复的代码提取出来,建立一个模板,此时可以在答案之前建立一个名为 template 的二级标题,例如:

````markdwon

## template

```c
```c
#include <stdio.h>
F
feilong 已提交
221
int main(int argc, char** argv){
M
Mars Liu 已提交
222
    $code
F
feilong 已提交
223 224
    return 0;
}
M
Mars Liu 已提交
225

F
feilong 已提交
226 227
```

M
Mars Liu 已提交
228 229 230 231
````

注意这里的代码中,有一个 `$code` 占位符,它在管道程序处理过程中,会替换成答案和个选项内容中的代码

F
feilong 已提交
232 233 234 235 236
## 技能树合成

在根目录下执行 `python main.py` 会合成技能树文件,合成的技能树文件: `data/tree.json`
* 合成过程中,会自动检查每个目录下 `config.json` 里的 `node_id` 是否存在,不存在则生成
* 合成过程中,会自动检查每个知识点目录下 `config.json` 里的 `export` 里导出的习题配置,检查是否存在`exercise_id` 字段,如果不存在则生成