tree.py 3.8 KB
Newer Older
F
feilong 已提交
1 2 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
from genericpath import exists
import json
import os
import uuid
import sys
import re


def load_json(p):
    with open(p, 'r') as f:
        return json.loads(f.read())


def dump_json(p, j, exist_ok=False, override=False):
    if os.path.exists(p):
        if exist_ok:
            if not override:
                return
        else:
            print(f"{p} already exist")
            sys.exit(0)

    with open(p, 'w') as f:
        f.write(json.dumps(j, indent=2, ensure_ascii=False))


def parse_no_name(d):
    p = r'(\d+)\.(.*)'
    m = re.search(p, d)

    try:
        no = int(m.group(1))
        dir_name = m.group(2)
    except:
        sys.exit(0)

    return no, dir_name


def gen_tree(data_path):
    root = {}

    def gen_node_id():
        return ''.join(str(uuid.uuid5(uuid.NAMESPACE_URL, 'skill_tree')).split('-'))

    def list_dir(p):
        v = os.listdir(p)
        v.sort()
        for no_name in v:
            no_dir = os.path.join(p, no_name)
            if os.path.isdir(no_dir):
                yield no_dir, no_name

M
Mars Liu 已提交
54 55 56 57 58 59 60 61 62 63 64
    def ensure_id_helper(node):
        if node.get('node_id') is None:
            node['node_id'] = gen_node_id()

        if 'children' in node:
            for c in node["children"]:
                ensure_id_helper(list(c.values())[0])
    
    def ensure_node_id(cfg_path, cfg):    
        ensure_id_helper(cfg)
        dump_json(cfg_path, cfg, exist_ok=True, override=True)
F
feilong 已提交
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

    def make_node(name, node_id, keywords, children=None):
        node = {}
        node_children = children or []
        node[name] = {
            'node_id': node_id,
            'keywords': keywords,
            'children': node_children
        }
        return node, node_children

    # 根节点
    cfg_path = os.path.join(data_path, 'config.json')
    cfg = load_json(cfg_path)
    ensure_node_id(cfg_path, cfg)
    tree_node = {
        "node_id": cfg['node_id'],
        "keywords": cfg['keywords'],
        "children": []
    }
    root[cfg['tree_name']] = tree_node

    # 难度节点
    for level_no_dir, level_no_name in list_dir(data_path):
        print(level_no_dir)
        no, level_name = parse_no_name(level_no_name)
        cfg_path = os.path.join(level_no_dir, 'config.json')
        cfg = load_json(cfg_path)
        ensure_node_id(cfg_path, cfg)

        level_node, level_node_children = make_node(
            level_name, cfg['node_id'], cfg['keywords'])
        tree_node['children'].append(level_node)

M
Mars Liu 已提交
99 100
        

F
feilong 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
        # 章节点
        for chapter_no_dir, chapter_no_name in list_dir(level_no_dir):
            no, chapter_name = parse_no_name(chapter_no_name)
            cfg_path = os.path.join(chapter_no_dir, 'config.json')
            ensure_node_id(cfg_path, cfg)
            cfg = load_json(cfg_path)

            chapter_node, chapter_node_children = make_node(
                chapter_name, cfg['node_id'], cfg['keywords'])
            level_node_children.append(chapter_node)

            # 知识点
            for section_no_dir, section_no_name in list_dir(chapter_no_dir):
                no, section_name = parse_no_name(section_no_name)
                cfg_path = os.path.join(section_no_dir, 'config.json')
                cfg = load_json(cfg_path)
M
Mars Liu 已提交
117
                ensure_node_id(cfg_path, cfg)
F
feilong 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131

                section_node, section_node_children = make_node(
                    section_name, cfg['node_id'], cfg['keywords'], cfg['children'])
                chapter_node_children.append(section_node)

                # 确保习题分配了习题ID
                for export in cfg['export']:
                    if export.get('exercise_id') is None:
                        export['exercise_id'] = gen_node_id()
                dump_json(cfg_path, cfg, exist_ok=True, override=True)

    # 保存技能树骨架
    tree_path = os.path.join(data_path, 'tree.json')
    dump_json(tree_path, root, exist_ok=True, override=True)