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

F
feilong 已提交
3
`C 语言技能树`[技能森林](https://gitcode.net/csdn/skill_tree)的一部分。
F
feilong 已提交
4

F
feilong 已提交
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 100 101
## 初始化

```
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 已提交
102
目前我们支持使用 markdown 语法直接编辑习题和各选项。
F
feilong 已提交
103

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


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


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


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

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


````mardown
# Hello World

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

## 答案
F
feilong 已提交
138 139 140 141

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

M
Mars Liu 已提交
147 148 149 150
## 选项

### main 函数定义错误

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

M
Mars Liu 已提交
159 160
### Print 函数调用错误

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

M
Mars Liu 已提交
169
### Java 风格的导入
F
feilong 已提交
170

M
Mars Liu 已提交
171 172
```c
import stdio;
F
feilong 已提交
173

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

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

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

### 增强信息

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

````markdown

## aop

### before
F
feilong 已提交
200 201

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

M
Mars Liu 已提交
205 206
### after

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

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

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

````markdwon

## template

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

F
feilong 已提交
228 229
```

M
Mars Liu 已提交
230 231 232 233
````

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

F
feilong 已提交
234 235 236 237 238
## 技能树合成

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