skill_tree_python
Python 技能树
是技能森林的一部分。
初始化
pip install -r requirements.txt
目录结构说明
- 技能树
骨架文件
:- 位置:
data/tree.json
- 说明:该文件是执行
python main.py
生成的,请勿人工编辑
- 位置:
- 技能树
根节点
配置文件:- 位置:
data/config.json
- 说明:可编辑配置关键词等字段,其中
node_id
字段是生成的,请勿编辑
- 位置:
- 技能树
难度节点
:- 位置:
data/xxx
,例如:data/1.python初阶
- 说明:
- 每个技能树有 3 个等级,目录前的序号是必要的,用来保持文件夹目录的顺序
- 每个目录下有一个
config.json
可配置关键词信息,其中node_id
字段是生成的,请勿编辑
- 位置:
- 技能树
章节点
:- 位置:
data/xxx/xxx
,例如:data/1.python初阶/1.预备知识
- 说明:
- 每个技能树的每个难度等级有 n 个章节,目录前的序号是必要的,用来保持文件夹目录的顺序
- 每个目录下有一个
config.json
可配置关键词信息,其中node_id
字段是生成的,请勿编辑
- 位置:
- 技能树
知识节点
:- 位置:
data/xxx/xxx
,例如:data/1.python初阶/1.预备知识
- 说明:
- 每个技能树的每章有 n 个知识节点,目录前的序号是必要的,用来保持文件夹目录的顺序
- 每个目录下有一个
config.json
- 其中
node_id
字段是生成的,请勿编辑 - 其中
keywords
可配置关键字字段 - 其中
children
可配置该知识节点
下的子树结构信息,参考后面描述 - 其中
export
可配置该知识节点
下的导出习题信息,参考后面描述
- 其中
- 位置:
知识节点
子树信息结构
例如 data/1.python初阶/1.预备知识/1.Python简介/config.json
里配置对该知识节点子树信息结构:
{
// ...
"children": [
{
"Python都能做什么": {
"keywords": [],
"children": [],
"node_id": "python-4-0"
}
},
{
"python起源和发展": {
"keywords": [],
"children": [],
"node_id": "python-insert-2"
}
},
{
"python语言特点": {
"keywords": [],
"children": [],
"node_id": "python-insert-3"
}
}
],
}
知识节点
的习题配置规则(一)
例如 data/1.python初阶/1.预备知识/1.Python简介/config.json
里配置对该知识节点导出的习题
{
// ...
"export": [
"helloworld.json"
// ...
]
}
其中"helloworld.json"
是习题的配置文件,文件如下:
{
"exercise_id": 33,
"source": "helloworld.py",
"depends": [],
"multiline": [
{
"str1 = \"Hello,\"": "",
"str2 = \"World!\"": "str = \"Hello,World!\"",
"print('str1'+'str2')": "print(str)"
},
{
"str1 = \"Hello,\"": "",
"str2 = \"World!\"": "",
"print('str1'+'str2')": "print(\"Hello\" +\",\" +\"World!\")"
},
{
"print('str1'+'str2')": "print(str1+str2)"
}
]
}
其中:
-
"exercise_id"
是脚本填充的字段,编辑的时候不用填写 -
"source"
指定了习题的来源文件 -
"depends"
: 指定了习题依赖的同知识点下的其他源文件 -
"multiline"
: 是习题选项替换的规则之一
习题源代码
"helloworld.py"
的源代码如下:
# -*- coding: UTF-8 -*-
# 作者:幻灰龙
# 标题:Hello World
# 描述:输出 "Hello,World!" 字符串,找出错的那项。
if __name__ == '__main__':
str1 = "Hello,"
str2 = "World!"
print('str1'+'str2')
源代码的头部注释固定格式,配置作者
,标题
,描述
,其中描述可以是MarkDown格式
习题源代码替换规则
对于习题代码 "helloworld.py"
的代码变种替换规则配置在"helloworld.json"
里面。有两种替换规则:
单行替换规则:
- 配置由
one_line
字段指定的单行替换字典 - 格式是:
"<源字符串>"
: ["<替换字符串A>"
,<替换字符串B>
,...],- 其中每个
"<源字符串>"
/
"<替换字符串A>"
被生成为是一个替换选项 - 指定的配置应该能至少生成
3+
个替换选项
- 其中每个
{
"one_line": {
"printf": ["print"],
"return 0;": ["return 0"],
"(\"Hello,Wrold!\")": [" \"Hello,Wrold!\""]
}
}
上面的替换规则会将代码替换成 3 个变种的代码:
// 变种代码1
#include <stdio.h>
int main(int argc, char** argv){
print("Hello,Wrold!");
return 0;
}
// 变种代码2
#include <stdio.h>
int main(int argc, char** argv){
print("Hello,Wrold!");
return 0
}
// 变种代码3
#include <stdio.h>
int main(int argc, char** argv){
print "Hello,Wrold!";
return 0
}
这些变种代码将会作为技能树该知识点该代码选择题的选项。
多行替换规则:
- 配置由
multiline
字段指定的多行替换数组 - 数组的每个元素是一组替换规则,会整组被替换
例如:
{
"multiline": [
{
"printf": "print"
},
{
"int main(int argc, char** argv){" : "int main(char** argv){",
"return 0;" : "return 0",
},
{
"#include <stdio.h>": ""
}
]
}
同样,该配置将支持将源代码生成3个变种代码
// 变种代码1
#include <stdio.h>
int main(int argc, char** argv){
print("Hello,Wrold!");
return 0;
}
// 变种代码2, 注意第2组替换规则,包含了两行替换
#include <stdio.h>
int main(char** argv){
print("Hello,Wrold!");
return 0
}
// 变种代码3
int main(int argc, char** argv){
print("Hello,Wrold!");
return 0;
}
知识节点
的习题配置规则(二)
另外一种更便利的配置习题的方式是直接基于 MarkDown 格式配置。还是以"helloworld.json"
为例子展开描述。
此时,"helloworld.json"
简化为:
{
"type": "code_options",
"author": "幻灰龙",
"source": "helloworld.md",
}
其中 type 字段目前都固定是 code_options
。根据具体情况写好其它字段,注意这里 source
的文件名,我们指定了一个 Markdown 文件。现在我们新建一个 helloworld.md
并编辑为:
# Hello World
输出 "Hello,World!" 字符串,找出错的那项。
## template
```python
# this part is used to be displayed in jupyter notebook
if ___name__ == '__main__':
str1 = "Hello,"
str2 = "World!"
print('str1' + 'str2')
```
## 答案
```python
if __name__ == '__main__':
str1 = "Hello,"
str2 = "World!"
print('str1' + 'str2')
```
## 选项
### 两字符串变量拼接
```python
if __name__ == '__main__':
str1 = "Hello,"
str2 = "World!"
print(str1+str2)
```
### 两字符串字面量拼接
```python
if __name__ == '__main__':
print("Hello,"+"World!")
```
### 两字符串字面量拼接成字符串变量
```python
if __name__ == '__main__':
str = "Hello," + "World!"
print(str)
```
这是一个最基本的习题结构,它包含标题、答案、选项,注意这几个一级和二级标题必须填写正确,解释器会读取这几个标题。而选项的标题会被直接忽略掉,在 最终生成的习题中不包含选项的三级标题,所以这个标题可以用来标注一些编辑信息,例如“此选项没有关闭文件连接”,“类型错误”等等。
习题配置规则的选择
我们介绍了两种习题编辑规则,目前Python技能树这里大量使用了规则(一),这是历史编辑遗留。新增习题建议使用规则(二),更简洁方便。
技能树合成
在根目录下执行 python main.py
会合成技能树文件,合成的技能树文件: data/tree.json
- 合成过程中,会自动检查每个目录下
config.json
里的node_id
是否存在,不存在则生成 - 合成过程中,会自动检查每个知识点目录下
config.json
里的export
里导出的习题配置,检查是否存在exercise_id
字段,如果不存在则生成