# skill_tree_rust

Rust 技能树

## 环境准备

技能树仓库提供了辅助的工具脚本和 git hook 程序，在开始编辑工作之前，需要初始化环境依赖，我们推荐使用 python 3.8 或更高版本的 python。

首先，请确认系统中已经安装 python 和 git，然后执行下列命令克隆仓库：

```shell
git clone git@codechina.csdn.net:csdn/skill_tree_java.git
```

然后进入 skill_tree_java 目录，执行下列命令安装依赖：

```shell
pip install -r requrirements.txt
```

然后执行下列命令安装钩子：

```shell
pre-commit install
```

## 初始化技能树

技能树合成和id生成脚本目前用Python脚本统一处理

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


## 目录结构说明

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


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

例如 `data/1.rust初阶/1.预备知识/1.rust简介/config.json` 里配置对该知识节点子树信息结构，用来增加技能树服务在该知识节点上的深度数据匹配：

```json
{
    // ...

    "children": [
        {
            "Rust的起源": {
                "keywords": [
                    "Rust的起源",
                    "起源",
                    "Rust"
                ],
                "children": []
            }
        }
    ],
}
```


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

例如 `data/1.rust初阶/1.预备知识/1.rust简介/config.json` 里配置对该知识节点导出的习题

```json
{
    // ...
    "export": [
        "helloworld.json",
        // ...
    ]
}
```

在 `export` 字段中，我们列出习题定义的`json`文件列表 ，下面我们了解如何编写习题。

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

目前我们支持使用 markdown 语法直接编辑习题和各选项。

如前文内容，我们在知识节点下增加习题 `helloworld`的定义文件，即在`data/1.rust初阶/1.预备知识/1.rust简介` 目录增加一个`helloworld.json`文件：

```json
{
    "type": "code_options",
    "author": "幻灰龙",
    "source": "helloworld.md",
    "notebook_enable": true
}
```

其中

* `type` 字段目前都固定是 `code_options`，
* `notebook_enable` 字段决定这个习题是否生成对应的 `notebook` 
* `source` 字段代表习题编辑的 `markdwon` 文件。

现在我们新建一个 `helloworld.md` 并编辑为：

````markdown
# Hello World

编写一个输出 "Hello,World!" 的 Rust 程序，以下错误的是？

## 答案

```rust
fn main() {
    let str1 = "Hello,";
    let str2 = "World!";
    println!("{}", str1+str2);
}
```

## 选项

### 直接打印

```rust
fn main() {
    let str = "Hello,World!";
    println!("{}", str);
}
```

### 使用格式划宏拼接

```rust
fn main() {
    let str = "Hello";
    let str = format!("{},World", str);
    println!("{}", str);
}
```

### 使用 String::from

```rust
fn main() {
    let str1 = String::from("Hello");
    let str2 = String::from("World");
    let str = format!("{},{}!", str1, str2);
    println!("{}", str);
}

```

### 使用mut+push_str

```rust
fn main() {
    let mut str1 = String::from("Hello,");
    let str2 = String::from("World!");
    str1.push_str(str2.as_str());
    println!("{}", str1);
}
```
````

这是一个最基本的习题结构，它包含标题、答案、选项，注意这几个一级和二级标题必须填写正确，解释器会读取这几个标题。而选项的标题会被直接忽略掉，在
最终生成的习题中不包含选项的三级标题，所以这个标题可以用来标注一些编辑信息，例如“使用mut+push_str”，“使用格式划宏拼接”等等。

## 可选的习题源代码项目

编辑习题中，为了测试方便，可以直接在知识点目录下创建对应的 `rust源代码项目目录`

例如 `data/1.rust初阶/1.预备知识/1.rust简介/helloworld/`，就是通过`cargo new helloworld` 创建的测试 `helloworld.md` 里描述的习题用的 rust 源代码项目。执行命令 `cargo build` 和 `cargo run` 可以便利地测试程序。


## 技能树合成

在根目录下执行 `python main.py` 会合成技能树文件，合成的技能树文件为: `data/tree.json`
* 合成过程中，会检查章节目录下是否有 `config.json` 文件，如果没有，会自动生成，需要注意的是，这时 config.json是不完
  整的，没有 keywords 信息
* 每个知识点目录（即技能树最末端的叶子节点）的 config.json ，需要设定关键字，如果 `config.json` 的 keywords 为空，执行
  main.py 会提示错误并中途退出，执行`git commit`时，commit 钩子也会拒绝提交
* 合成过程中，会自动检查每个目录下 `config.json` 里的 `node_id` 是否存在，不存在则生成
* 合成过程中，会修复目录的序号，保持每一个章节目录的子目录总是从 1 开始的整数序列
* 合成过程中，会自动检查每个知识点目录下的 markdown 文件，是否有对应的配置信息，如果不存在则生成
    * 生成的习题配置信息中，author是根据git环境信息填写的，如果这个作者名不是您的csdn账户名，您可以手工编辑修改
    * config.json 的 export 字段定义了同一个知识点下习题的顺序，如果需要定义不同的顺序，您可以手工调整
    * 技能树仓库钩子和辅助工具都会检查信息完整性，并尝试做必要的修补，因此可能在提交时发现有一些新文件
      生成，请在后续的提交中将它们也发送到服务器仓库