Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
CSDN 技术社区
skill_tree_web_in_action
提交
41bfb9e4
S
skill_tree_web_in_action
项目概览
CSDN 技术社区
/
skill_tree_web_in_action
通知
8
Star
3
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
skill_tree_web_in_action
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
41bfb9e4
编写于
11月 02, 2021
作者:
M
Mars Liu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
document; data basic structure init
上级
1bb7d17f
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
124 addition
and
154 deletion
+124
-154
README.md
README.md
+16
-132
data/1.toolchains初阶/1.GIT入门/config.json
data/1.toolchains初阶/1.GIT入门/config.json
+4
-0
data/1.toolchains初阶/config.json
data/1.toolchains初阶/config.json
+4
-0
data/2.toolchains中阶/config.json
data/2.toolchains中阶/config.json
+4
-0
data/3.toolchains高阶/config.json
data/3.toolchains高阶/config.json
+4
-0
src/tree.py
src/tree.py
+92
-22
未找到文件。
README.md
浏览文件 @
41bfb9e4
...
@@ -62,7 +62,7 @@ pip install -r requirements.txt
...
@@ -62,7 +62,7 @@ pip install -r requirements.txt
{
{
//
...
//
...
"export"
:
[
"export"
:
[
//
TODO
...
"hello.sh"
]
]
}
}
```
```
...
@@ -74,137 +74,17 @@ pip install -r requirements.txt
...
@@ -74,137 +74,17 @@ pip install -r requirements.txt
## `知识节点` 的导出习题选项配置编辑
## `知识节点` 的导出习题选项配置编辑
首先,在知识节点下增加一个习题代码,例如在
`data/1.toolchains初阶/1.git/4.push修改到远程创库`
下增加一个
`HelloWord.sh`
代码:
如前内容,我们在知识节点下增加一个习题定义,例如在
`data/1.toolchains初阶/1.git/4.push修改到远程创库`
下增加一个
`hello.json`
代码:
```
console
$
git add README.txt
$
git commit
-m
"first modify README.txt"
$
git push origin master
```
其次,增加一个同名的选项配置文件
`HelloWord.json`
,目前有三种配置规则
**单行替换规则**
:
*
配置由
`one_line`
字段指定的单行替换字典
*
格式是:
`"<源字符串>"`
: [
`"<替换字符串A>"`
,
`<替换字符串B>`
,...],
*
其中每个
`"<源字符串>"`
`/`
`"<替换字符串A>"`
被生成为是一个替换选项
*
指定的配置应该能至少生成
`3+`
个替换选项
```
json
{
"one_line"
:
{
"git add"
:
[
"git put"
,
"git in"
,
"git checkout"
]
}
}
```
上面的替换规则会将代码替换成 3 个变种的代码:
```
console
// 变种代码1
$
git put README.txt
$
git commit
-m
"first modify README.txt"
$
git push origin master
```
```
console
// 变种代码2
$
git
in
README.txt
$
git commit
-m
"first modify README.txt"
$
git push origin master
```
```
html
// 变种代码3
$ git checkout README.txt
$ git commit -m "first modify README.txt"
$ git push origin master
```
这些变种代码将会作为技能树该知识点该代码选择题的选项。
**多行替换规则**
:
*
配置由
`multiline`
字段指定的多行替换数组
*
数组的每个元素是一组替换规则,会整组被替换
例如:
```
json
{
"mulitiline"
:
[{
"git add"
:
"git put"
,
"git commit -m"
:
"git commit -a"
},
{
"git commit"
:
"git base"
,
"git push"
:
"git pull"
}]
}
```
同样,该配置将支持将源代码生成2个变种代码
```
console
// 变种代码1
$
git put README.txt
$
git commit
-a
"first modify README.txt"
$
git push origin master
```
```
console
// 变种代码2, 注意第2组替换规则,包含了两行替换
$
git add README.txt
$
git base
-m
"first modify README.txt"
$
git pull origin master
```
## 预制的替换规则
*
配置由
`prepared`
字段制定的预制文件数组
*
数组每一个元素是一个预制的代码文件的路径文件名
例如:
```
json
{
"prepared"
:
[
"HelloWord.1.sh"
,
"HelloWord.2.sh"
,
"HelloWord.3.sh"
]
}
```
同样,该配置将支持将源代码生成3个变种代码
```
console
// HelloWord.1.sh
$
git put README.txt
$
git commit
-a
"first modify README.txt"
$
git push origin master
```
```
console
$
git add README.txt
$
git base
-m
"first modify README.txt"
$
git pull origin master
```
## 使用 markdown 编写习题
如前内容,我们在知识节点下增加一个习题配置,例如在
`data/1.toolchains初阶/1.git/4.push修改到远程创库`
下增加一个
`HelloWorld.json`
代码:
```
json
```
json
{
{
"type"
:
"code_options"
,
"type"
:
"code_options"
,
"author"
:
"刘鑫"
,
"author"
:
"刘鑫"
,
"source"
:
"HelloWorld.md"
,
"source"
:
"hello.md"
,
"exercise_id"
:
"1190bb7834904da0b1f20915960714d5"
,
"notebook_enable"
:
false
"notebook_enable"
:
true
}
}
```
```
其中 type 字段目前都固定是
`code_options`
。
exercise_id 可以不写,处理程序会自动填补这个数据。
根据具体情况写好其它字段,注意这里 source 的文件名,我们指定了一个 markdwon 文件。现在我们新建一个 HelloWorld.md 并编辑为:
其中 type 字段目前都固定是
`code_options`
。根据具体情况写好其它字段,注意这里 source 的文件名,我们指定了一个 markdwon 文件。现在我们新建一个 HelloWorld.md 并编辑为:
````
markdown
````
markdown
# Hello World
# Hello World
...
@@ -222,7 +102,7 @@ $ git push origin master
...
@@ -222,7 +102,7 @@ $ git push origin master
## 选项
## 选项
###
A
###
add 子命令错误
```
console
```
console
// HelloWord.1.sh
// HelloWord.1.sh
...
@@ -231,7 +111,7 @@ $ git commit -a "first modify README.txt"
...
@@ -231,7 +111,7 @@ $ git commit -a "first modify README.txt"
$
git push origin master
$
git push origin master
```
```
###
B
###
commit 子命令错误
```
console
```
console
$
git add README.txt
$
git add README.txt
...
@@ -239,6 +119,13 @@ $ git base -m "first modify README.txt"
...
@@ -239,6 +119,13 @@ $ git base -m "first modify README.txt"
$
git pull origin master
$
git pull origin master
```
```
### push 子命令错误
```
console
$
git add README.txt
$
git commit
-m
"first modify README.txt"
$
git pull origin master
```
````
````
...
@@ -256,13 +143,13 @@ $ git pull origin master
...
@@ -256,13 +143,13 @@ $ git pull origin master
### before
### before
```
console
```
shell
echo
"do something before"
echo
"do something before"
```
```
### after
### after
```
console
```
shell
echo
"do something after"
echo
"do something after"
```
```
````
````
...
@@ -286,9 +173,6 @@ $ $code
...
@@ -286,9 +173,6 @@ $ $code
注意这里的代码中,有一个
`$code`
占位符,它在管道程序处理过程中,会替换成答案和个选项内容中的代码。
注意这里的代码中,有一个
`$code`
占位符,它在管道程序处理过程中,会替换成答案和个选项内容中的代码。
在后续的数据处理流程中,markdown 会被编译为 prepared 类型的习题。
## 技能树合成
## 技能树合成
...
...
data/1.toolchains初阶/1.GIT入门/config.json
0 → 100644
浏览文件 @
41bfb9e4
{
"keywords"
:
[]
}
\ No newline at end of file
data/1.toolchains初阶/config.json
0 → 100644
浏览文件 @
41bfb9e4
{
"keywords"
:
[]
}
\ No newline at end of file
data/2.toolchains中阶/config.json
0 → 100644
浏览文件 @
41bfb9e4
{
"keywords"
:
[]
}
\ No newline at end of file
data/3.toolchains高阶/config.json
0 → 100644
浏览文件 @
41bfb9e4
{
"keywords"
:
[]
}
\ No newline at end of file
src/tree.py
浏览文件 @
41bfb9e4
...
@@ -5,6 +5,7 @@ import uuid
...
@@ -5,6 +5,7 @@ import uuid
import
sys
import
sys
import
re
import
re
id_set
=
set
()
def
load_json
(
p
):
def
load_json
(
p
):
with
open
(
p
,
'r'
)
as
f
:
with
open
(
p
,
'r'
)
as
f
:
...
@@ -36,12 +37,26 @@ def parse_no_name(d):
...
@@ -36,12 +37,26 @@ def parse_no_name(d):
return
no
,
dir_name
return
no
,
dir_name
def
check_export
(
base
,
cfg
):
flag
=
False
exports
=
[]
for
export
in
cfg
.
get
(
'export'
,
[]):
ecfg_path
=
os
.
path
.
join
(
base
,
export
)
if
os
.
path
.
exists
(
ecfg_path
):
exports
.
append
(
export
)
else
:
flag
=
True
if
flag
:
cfg
[
"export"
]
=
exports
return
flag
def
gen_tree
(
data_path
):
def
gen_tree
(
data_path
):
root
=
{}
root
=
{}
def
gen_node_id
():
def
gen_node_id
():
return
''
.
join
(
str
(
uuid
.
uuid5
(
uuid
.
NAMESPACE_URL
,
'skill_tree'
)).
split
(
'-'
))
# return ''.join(str(uuid.uuid5(uuid.NAMESPACE_URL, 'skill_tree')).split('-'))
return
"c-"
+
uuid
.
uuid4
().
hex
def
list_dir
(
p
):
def
list_dir
(
p
):
v
=
os
.
listdir
(
p
)
v
=
os
.
listdir
(
p
)
...
@@ -51,10 +66,42 @@ def gen_tree(data_path):
...
@@ -51,10 +66,42 @@ def gen_tree(data_path):
if
os
.
path
.
isdir
(
no_dir
):
if
os
.
path
.
isdir
(
no_dir
):
yield
no_dir
,
no_name
yield
no_dir
,
no_name
def
ensure_node_id
(
cfg_path
,
cfg
):
def
ensure_id_helper
(
node
):
if
cfg
.
get
(
'node_id'
)
is
None
:
flag
=
False
cfg
[
'node_id'
]
=
gen_node_id
()
dump_json
(
cfg_path
,
cfg
,
exist_ok
=
True
,
override
=
True
)
if
(
node
.
get
(
'node_id'
)
is
None
)
or
node
.
get
(
'node_id'
)
in
id_set
:
node
[
'node_id'
]
=
gen_node_id
()
flag
=
True
id_set
.
add
(
node
[
'node_id'
])
if
'children'
in
node
:
for
c
in
node
[
"children"
]:
flag
=
flag
or
ensure_id_helper
(
list
(
c
.
values
())[
0
])
return
flag
def
ensure_node_id
(
cfg
):
return
ensure_id_helper
(
cfg
)
def
ensure_title_helper
(
node
,
cfg_path
,
title
=
""
):
flag
=
False
if
node
.
get
(
'title'
)
is
None
:
if
cfg_path
:
node
[
'title'
]
=
re
.
sub
(
"^[0-9]{1,3}\."
,
""
,
os
.
path
.
split
(
os
.
path
.
dirname
(
cfg_path
))[
-
1
])
else
:
node
[
'title'
]
=
title
flag
=
True
if
'children'
in
node
:
for
c
in
node
[
"children"
]:
flag
=
flag
or
ensure_title_helper
(
list
(
c
.
values
())[
0
],
None
,
list
(
c
.
keys
())[
0
])
return
flag
def
ensure_title
(
cfg
,
cfg_path
):
return
ensure_title_helper
(
cfg
,
cfg_path
)
def
make_node
(
name
,
node_id
,
keywords
,
children
=
None
):
def
make_node
(
name
,
node_id
,
keywords
,
children
=
None
):
node
=
{}
node
=
{}
...
@@ -69,7 +116,12 @@ def gen_tree(data_path):
...
@@ -69,7 +116,12 @@ def gen_tree(data_path):
# 根节点
# 根节点
cfg_path
=
os
.
path
.
join
(
data_path
,
'config.json'
)
cfg_path
=
os
.
path
.
join
(
data_path
,
'config.json'
)
cfg
=
load_json
(
cfg_path
)
cfg
=
load_json
(
cfg_path
)
ensure_node_id
(
cfg_path
,
cfg
)
if
ensure_node_id
(
cfg
):
dump_json
(
cfg_path
,
cfg
)
if
ensure_title
(
cfg
,
cfg_path
):
cfg
[
"title"
]
=
"C"
dump_json
(
cfg_path
,
cfg
,
exist_ok
=
True
,
override
=
True
)
tree_node
=
{
tree_node
=
{
"node_id"
:
cfg
[
'node_id'
],
"node_id"
:
cfg
[
'node_id'
],
"keywords"
:
cfg
[
'keywords'
],
"keywords"
:
cfg
[
'keywords'
],
...
@@ -81,41 +133,59 @@ def gen_tree(data_path):
...
@@ -81,41 +133,59 @@ def gen_tree(data_path):
for
level_no_dir
,
level_no_name
in
list_dir
(
data_path
):
for
level_no_dir
,
level_no_name
in
list_dir
(
data_path
):
print
(
level_no_dir
)
print
(
level_no_dir
)
no
,
level_name
=
parse_no_name
(
level_no_name
)
no
,
level_name
=
parse_no_name
(
level_no_name
)
cfg_path
=
os
.
path
.
join
(
level_no_dir
,
'config.json'
)
level_path
=
os
.
path
.
join
(
level_no_dir
,
'config.json'
)
cfg
=
load_json
(
cfg_path
)
level_cfg
=
load_json
(
level_path
)
ensure_node_id
(
cfg_path
,
cfg
)
if
ensure_node_id
(
level_cfg
)
or
check_export
(
level_no_dir
,
level_cfg
):
dump_json
(
level_path
,
level_cfg
,
exist_ok
=
True
,
override
=
True
)
if
ensure_title
(
level_cfg
,
level_path
):
dump_json
(
level_path
,
level_cfg
,
exist_ok
=
True
,
override
=
True
)
level_node
,
level_node_children
=
make_node
(
level_node
,
level_node_children
=
make_node
(
level_name
,
cfg
[
'node_id'
],
cfg
[
'keywords'
])
level_name
,
level_cfg
[
'node_id'
],
level_
cfg
[
'keywords'
])
tree_node
[
'children'
].
append
(
level_node
)
tree_node
[
'children'
].
append
(
level_node
)
# 章节点
# 章节点
for
chapter_no_dir
,
chapter_no_name
in
list_dir
(
level_no_dir
):
for
chapter_no_dir
,
chapter_no_name
in
list_dir
(
level_no_dir
):
no
,
chapter_name
=
parse_no_name
(
chapter_no_name
)
no
,
chapter_name
=
parse_no_name
(
chapter_no_name
)
cfg_path
=
os
.
path
.
join
(
chapter_no_dir
,
'config.json'
)
chapter_path
=
os
.
path
.
join
(
chapter_no_dir
,
'config.json'
)
ensure_node_id
(
cfg_path
,
cfg
)
chapter_cfg
=
load_json
(
chapter_path
)
cfg
=
load_json
(
cfg_path
)
if
ensure_node_id
(
chapter_cfg
)
or
check_export
(
chapter_no_dir
,
chapter_cfg
):
dump_json
(
chapter_path
,
chapter_cfg
,
exist_ok
=
True
,
override
=
True
)
if
ensure_title
(
chapter_cfg
,
chapter_path
):
dump_json
(
chapter_path
,
chapter_cfg
,
exist_ok
=
True
,
override
=
True
)
chapter_node
,
chapter_node_children
=
make_node
(
chapter_node
,
chapter_node_children
=
make_node
(
chapter_name
,
c
fg
[
'node_id'
],
cfg
[
'keywords'
])
chapter_name
,
c
hapter_cfg
[
'node_id'
],
chapter_
cfg
[
'keywords'
])
level_node_children
.
append
(
chapter_node
)
level_node_children
.
append
(
chapter_node
)
# 知识点
# 知识点
for
section_no_dir
,
section_no_name
in
list_dir
(
chapter_no_dir
):
for
section_no_dir
,
section_no_name
in
list_dir
(
chapter_no_dir
):
no
,
section_name
=
parse_no_name
(
section_no_name
)
no
,
section_name
=
parse_no_name
(
section_no_name
)
cfg
_path
=
os
.
path
.
join
(
section_no_dir
,
'config.json'
)
sec
_path
=
os
.
path
.
join
(
section_no_dir
,
'config.json'
)
ensure_node_id
(
cfg_path
,
cfg
)
sec_cfg
=
load_json
(
sec_path
)
cfg
=
load_json
(
cfg_path
)
flag
=
ensure_node_id
(
sec_cfg
)
or
check_export
(
section_no_dir
,
sec_cfg
)
section_node
,
section_node_children
=
make_node
(
section_node
,
section_node_children
=
make_node
(
section_name
,
cfg
[
'node_id'
],
cfg
[
'keywords'
],
cfg
[
'children'
]
)
section_name
,
sec_cfg
[
'node_id'
],
sec_cfg
[
'keywords'
],
sec_cfg
.
get
(
'children'
,
[])
)
chapter_node_children
.
append
(
section_node
)
chapter_node_children
.
append
(
section_node
)
# 确保习题分配了习题ID
# 确保习题分配了习题ID
for
export
in
cfg
[
'export'
]:
if
export
.
get
(
'exercise_id'
)
is
None
:
for
export
in
sec_cfg
.
get
(
"export"
,
[]):
export
[
'exercise_id'
]
=
gen_node_id
()
ecfg_path
=
os
.
path
.
join
(
section_no_dir
,
export
)
dump_json
(
cfg_path
,
cfg
,
exist_ok
=
True
,
override
=
True
)
ecfg
=
load_json
(
ecfg_path
)
if
(
ecfg
.
get
(
'exercise_id'
)
is
None
)
or
(
ecfg
.
get
(
'exercise_id'
)
in
id_set
):
ecfg
[
'exercise_id'
]
=
uuid
.
uuid4
().
hex
dump_json
(
ecfg_path
,
ecfg
,
exist_ok
=
True
,
override
=
True
)
id_set
.
add
(
ecfg
[
'exercise_id'
])
if
flag
:
dump_json
(
sec_path
,
sec_cfg
,
exist_ok
=
True
,
override
=
True
)
if
ensure_title
(
sec_cfg
,
sec_path
):
dump_json
(
sec_path
,
sec_cfg
,
exist_ok
=
True
,
override
=
True
)
# 保存技能树骨架
# 保存技能树骨架
tree_path
=
os
.
path
.
join
(
data_path
,
'tree.json'
)
tree_path
=
os
.
path
.
join
(
data_path
,
'tree.json'
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录