• 学术家族树的前端实现


    这初始的黄金之风luxiaoye

    What does not kill me makes me stronger

    链接

    github地址:https://github.com/O-VIGIA/031702414-031702444.git

    结对同学:031702444李尚佳

    具体分工

    031702414陆志阳:算法设计和实现,单元测试,代码优化

    031702444李尚佳:前端页面设计和实现

    共同完成:jstree的实现 博客内容撰写

    PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(h) 实际耗时(h)
    Planning 计划 3 4
    Estimate 估计这个任务需要多少时间 58 69
    Development 开发 5 8
    Analysis 需求分析 (包括学习新技术) 8 24
    Design Spec 生成设计文档 2 5
    Design Review 设计复审 1 2
    Coding Standard 代码规范 (为目前的开发制定合适的规范) 2 3
    Design 具体设计 2 2
    Coding 具体编码 10 8
    Code Review 代码复审 3 2
    Test 测试(自我测试,修改代码,提交修改) 4 3
    Reporting 报告 4 2
    Test Repor 测试报告 2 1
    Size Measurement 计算工作量 2 1
    Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 3 4
    合计 58 69

    解题思路描述与设计实现说明

    读完题目,分析要点如下:

    1. 文本数据的提取
    2. 文本数去提取完如何保存和传送
    3. 树状动态结构的生成
    4. 树状结构缩放的实现

    代码组织与内部实现设计(类图)

    说明算法的关键与关键实现部分流程图

    在没开始之前 我们两个 是这么想的 ((( :

    算法:

    缩放算法:

    定义 检查函数(节点)

    {

    ​ 检查该节点所有的父节点

    ​ 如果 其所有父节点的缩放标志全为1,该节点与所有的父节点连线消失并且该节点消失

    ​ 如果 其至少有一个父节点的缩放标志不为1,该节点只与缩放标志为1的父节点连线消失并且该节点不消失

    }

    定义 缩放函数(节点)

    {

    ​ 点击节点,以此节点为父节点,找到他的所有的儿子节点(第一层儿子节点),该节点缩放标志为1。

    ​ 检查节点(子节点)

    ​ 缩放函数(子节点)

    }

    主函数()

    {

    ​ 缩放函数(点击的节点);

    }

    在分工开始了之后我是这么想的

    算法

    。。。。。。。。。。。。。。

    最后是则个样子?!

    多行不E必自闭 ~

    好了正经起来:

    在打关联树的时候

    比较有意思的一个算法可能就是递归查找子节点了,就是当前树的根节点和前面树的节点是否有关联

    写这个算法的过程中,因为数据是json格式,所以求父节点下一级子节点的长度就是关键。

    刚开始憨憨写了个 json. length()/.size()...发现都不对,最后只能自己去手打,发现手打也没那么难

     //自定义json长度查找函数,返回json树的下层子节点的长度(个数)
    
    ​        function getJsonLength(jsonData) {
    
    ​            var json_length = 0;
    
    ​            for (var temp in jsonData) {
    
    ​                //alert("Son is " + item);
    
    ​                json_length++;
    
    ​            }
    
    ​            return jsonLength;
    
    ​        }
    

    剩下的就交给我的递归查找函数了,直接上代码,看注释

     		 /*
    ​        检查函数,遍历之前所有树的所有子节点,查找是否有导师的学生也是导师的情况,若有此种情况则此树重构 
    ​        */
    
    ​        //@nodes 源json树
    
    ​        //@find_name 要找的导师名
    
    ​        //@may_need 可能需要添加的json树 
    
    ​        function check(nodes, find_name, may_need, keke) {
    
    ​            var fanhui1 = 0;
    
    ​            var fanhui2 = 1;
    
    ​            // alert("checkcheckcheckcheckcheckcheck");
    
    ​            var length_now = getJsonLength(nodes.children);
    
    ​            // alert("chang = " + length_now)
    
    ​            for (var ll = 0; ll < length_now; ll++) {
    
    ​                // alert(nodes.children[ll].name);
    
    ​                if (nodes.children[ll].name == find_name) {//第ll个子节点的名字是否与要查找的相同
    
    ​                    // alert("hhhhhhhhhhhhhh");
    
    ​                    quanju_flag = 1;如果有一棵树和其他树有关联此变量为一树的颗数不增加
    
    ​                    //add_tree(nodes.children[ll].children, may_need, keke);
    
    ​                    // alert("add");
    
    ​                    // alert(getJsonLength(may_need));
    
    ​                    nodes.children[ll] = may_need;//将该json树添加到儿子节点作为关联
    
    ​                    // alert("add success");
    
    ​                    return fanhui2;
    
    ​                } else {
    
    ​                    check(nodes.children[ll], find_name, may_need, keke);
    
    ​                    // return;
    
    ​                }
    
    ​            }
    
    ​            return fanhui1;
    
    ​        }
    

    其他的地方,也就是搞json的时候的经常犯傻,不过最后还是渐渐清晰了。

    有关树的生成,我把队友的画图代码封装成函数,用json数据存放成当前所有的树,最后一起生成防止生成关联树之后又生成关联树的子树,树的棵树用模块独立树减去关联树统计画出。

    详细的生成树的逻辑思想见下面的流程图@lxy

    贴出你认为重要的/有价值的代码片段,并解释

    alert("宇宙最有价值的代码");
    

    这就是最有价值的代码☝

    正经一点开始正题

    在上面的“算法的关键与关键实现部分流程图 ”我其实已经列出了一些代码都是一些功能函数

    最有价值的就是主函数代码把,它。。多累啊

    解释看注释和上面流程图

           //追逐函数
    
    ​        /*
    ​        分割传输过来的数据并构造json树结构
    ​        相当于主函数功能
    ​        */
    ​        function chase() {
    ​            var count = 0; //定义儿子节点的编号
    ​            var flag = 0; //定义标志是否为关联树值为1
    ​            var all_data = document.getElementById("user").value;
    ​            var sclice_data = [];
    ​            var model_data = [];
    ​            model_data = all_data.split("
    
    ");
    ​            //生成树型结构数据
    ​            for (var j = 0; j < model_data.length; ++j) {
    ​                //初始化变量
    ​                count = 0;
    ​                //flag = 0;
    ​                quanju_flag = 0;
    ​                count_shu = 0
    ​                sclice_data = model_data[j].split("
    ");
    ​                for (var i = 0; i < sclice_data.length; ++i) {
    ​                    var head_tmp = "";
    ​                    var body_tmp = "";
    ​                    var hb = sclice_data[i].split(":"); //从冒号分割一层字符串
    ​                    head_tmp = hb[0];
    ​                    body_tmp = hb[1];
    ​                    //处理冒号前的部分
    ​                    if (head_tmp == "导师") {
    ​                        var daoshi2 = {
    ​                            "name": body_tmp,
    ​                            "parent": "null",
    ​                            "children": [{}]
    ​                        }
    ​                        treeData[j] = daoshi2; //将导师嵌入节点
    ​                    } else {
    ​                        var children = {
    ​                            "name": head_tmp,
    ​                            "parent": "null",
    ​                            "children": [{}]
    ​                        }
    ​                        treeData[j].children[count] = children; //将年级及职业嵌入节点
    ​                        var bodies = body_tmp.split("、");
    ​                        //document.write("姓名:");
    ​                        for (var kk = 0; kk < bodies.length; ++kk) {
    ​                            var children = {
    ​                                    "name": bodies[kk],
    ​                                    "parent": "null",
    ​                                    //"children": [{}]
    ​                                }
    ​                                //treeData.push(children);
    ​                            treeData[j].children[count].children[kk] = children; //将姓名嵌入节点
    ​                        }
    ​                        count++; //第二子节点编号加一,生成下一个第二子节点
    ​                    }
    ​                }
    ​                var tree_tmp = treeData[j];
    ​                var name_tmp = treeData[j].name;
    ​                for (num_tmp = 0; num_tmp < j; num_tmp++) {
    ​                    check(treeData[num_tmp], name_tmp, tree_tmp, num_tmp);
    ​                }
    ​                if (!quanju_flag) count_shu++;//若有关联树则独立树的棵数不增加
    ​            }
    ​            //生成所有树
    ​            alert("shu: " + count_shu);
    ​            for (var i = 0; i <= count_shu; i++) {
    ​                shuInit(i)
    ​            }
    ​        }
    

    附加特点设计与展示

    设计的创意独到之处以及设计的意义

    • 采用透明图片作为背景,增加界面的美观感
    • 左右四六分的格局,使界面显得整齐规整
    • 蓝绿透明框配色,极具简约感
      -支持多颗关联树

    实现思路

    • 用不同的div构建层次

    • css样式使用百分比宽高绝对定位

    • 算法和js操作详细请见上面的介绍

    实现成果展示

    • 前端输入界面:

    • 生成树状结构界面:

    • 家族树缩放界面:

    在博客中给出目录说明和使用说明

    说明你的目录是如何组织的

    目录

    • FT4.0

      • index.html(在chrome上运行)
      • style.css(外部样式表)
      • tree.js(生成家族书的函数)
      • background.jpg(背景图片)
      • d3.v3.min.js(d3库)
    • README:使用说明文件

    • 使用方式

      下载FT4.0到本地,解压后文件本地,用chrome打开index.html,在右侧文本框输入文本。

      学术家族树以文本形式输入,点击提交文本框。

    • 文本格式

      输入:

      学术家族树以文本形式输入,点击提交文本框,考虑学术家族树的文本格式是这样的:

      导师:张三

      2016级博士生:天一、王二、吴五

      2015级硕士生:李四、王五、许六

      2016级硕士生:刘一、李二、李三

      2017级本科生:刘六、琪七、司四

      导师:吴五
      2016级博士生:天一、王二、吴

      2015级硕士生:李四、王五、许六

      2016级硕士生:刘一、李二、李三

      2017级本科生:刘2、琪七、司四

      导师:刘2
      2016级博士生:天一、王二

      2015级硕士生:李四、王五、许六

      2016级硕士生:刘一、李、李三

      2017级本科生:刘、琪七、司四

      !!!文本最后不能换行

      其中,"导师:","级博士生:","级硕士生:","级本科生:"和"、"当做关键词处理;若有多组输入,中间空一行。

      输出:

      树的节点,鼠标点击后是可以缩放的。同时,支持呈现多棵树并存、两棵关联树共存等形式。

      在左侧家族树下会显示可缩放的树状结构,即生成的家族树。

    测试人员如何运行你的网页

    • 点击github上把文件Clone到本地,解压后即可使用,需保证上述所有文件在同一个文件夹下。
    • 直接用Chrome打开indext.html,输入格式按照作业要求。
    • 在右侧的文本框输入数据,点击提交文本,将会在左侧生成一棵以导师为根节点的树。支持多棵树并存以及关联树。

    单元测试

    说明你们选用的测试工具,是如何学习单元测试的,能出一份你自己的简易教程吗?

    展示出项目部分单元测试代码,并说明测试的函数

    说明构造测试数据的思路,你是如何考虑各种情况的?你如何考虑将来测试人员的刁难?

    单元测试,说实话多这个东西十分的陌生,虽然在上次的数独中有单元测试的一点点模块,助教大神不给我分啊气,这次希望助教大神。。。给点分,(憨憨只想开个玩笑,大神别搞我。这次单元测试也是相对比较简单的。

    单元测试也花了不少时间,我在查找了很多js单元测试的框架之后选定了抹茶,mocha!多好的名字,我想必打起来也会和吃抹茶一样。

    测试工具:mocha

    我首先对我的求json树长度函数进行了测试,测试了两种情况

    上图把

    1子节点

    2子节点的子节点

    可见,虽然。。。。。但是都成功单元测试出来了,说明我的json树求长度功能还是可以的。

    然后我又对子节点查找函数进行了测试

    查找 子节点的子节点 的姓名

    然后出现了我快要笑死的东西

    什么,竟然错了,在凌晨的四点的福大,仰望床底的我不禁开始了静静的思考

    思考后并且和前面的比对之后我发现少加了东西,因为我是在单元测试.js中外部请求了函数模块,所以要加上module,鸭嘞鸭嘞,然后我愉快的加上了model。。。 -------》to be comtinue

    这个这个我竟看了老半天才发现,真的是xsl

    测试成功,在所有子节点中以及子节点的子节点等等可以找到了名字为“yyy”的同学

    然后我测试一下在所有的子节点中找到 陆小爷 同学

    果然,找不到陆小爷同学,因为他打软工去了。

    测试成功。时间原因没有过多测试。

    重点来了,下面可能是最入门级的单元测试教程

    我仔细的浏览了一下博客作业中给出的mocha教程,发现很不容易上手(就是菜)

    上手的教程在这哈哈哈哈哈

    首先在电脑上安装node环境,并且配置环境变量path,(当然可以选择msi自行配制)

    配置好之后就可以愉快的用npm命令啦,npm install mocha安装抹茶

    配置抹茶.bin目录到path环境变量,然后就能愉快的运行你的test.js代码

    关于断言的单元测试代码可以参考博客作业的教程。

    //对单元测试当时爱了两个小时

    构造单元测试的思路,和应对未来的刁难

    思路清晰:

    测试json长度为例,测试完根结点的长度,是否能测出子节点的长度呢。

    查找子节点,是否能遍历所有子节点进行查找呢

    应对刁难:

    如果我们角色互换,我会让你看看什么叫残忍!

    //多学习,多做事。做到足够优秀,代码足够健壮。

    贴出Github的代码签入记录

    你以为是这样,我也想

    他其实长这样

    遇到的代码模块异常或结对困难及解决方法

    • 问题描述:树状结构难以实现。

    • 尝试:学习VUE,D3等框架,寻找类似树状可折叠结构的模板,学习API使用。

    • 是否解决:已解决。

    • 问题描述:界面设计简单简陋,不堪入目,html+css不熟练。

    • 尝试:广泛寻找优质界面,并借鉴学习,在B站和菜鸟教程寻找入门教学资源,一步步慢慢学习建立。

    • 是否解决:已解决


    • 问题描述:无法与界面树进行数据交互

    • 尝试:学习json,用json做结构

    • 是否解决:已解决


    • 问题描述:对json完全不了解

    • 尝试:打码测试,测试节点,测试遍历等等learning by doing

    • 是否解决:玩6了


    • 问题描述:太瞌睡

    • 尝试:拉着队友一起熬夜

    • 是否解决:已解决,两人均变憨憨


    评价队友

    • 值得学习的地方

      和我一样有着永不放弃的黄金精神,

    • 需要改进的地方

      不喜欢花里胡哨的东西,在基本代码还没实现之前就 不想着要搞事情。(兄嘚,Java得浪啊)

    六组测试

    数据一:

    导师:张三

    数据二:

    导师:张三
    2016级博士生:天一
    2015级硕士生:李四
    2016级硕士生:刘一
    2017级本科生:刘六

    数据三:

    导师:张三
    2016级博士生:天一、王二、吴五
    2015级硕士生:李四、王五、许六

    数据四:

    导师:张三
    2016级博士生:天一、王二、吴五
    2015级硕士生:李四、王五、许六
    2016级硕士生:刘一、李二、李三
    2017级本科生:刘六、琪七、司四

    数据五:

    导师:张三
    2016级博士生:天一、王二、吴五
    2015级硕士生:李四、王五、许六
    2016级硕士生:刘一、李二、李三
    2017级本科生:刘六、琪七、司四

    导师:吴五
    2016级博士生:天一、王二、吴
    2015级硕士生:李四、王五、许六
    2016级硕士生:刘一、李二、李三
    2017级本科生:刘2、琪七、司四

    数据六:

    导师:张三
    2016级博士生:天一、王二、吴五
    2015级硕士生:李四、王五、许六
    2016级硕士生:刘一、李二、李三
    2017级本科生:刘六、琪七、司四

    导师:吴五
    2016级博士生:天二、王四、吴六
    2015级硕士生:李一、王八、许七
    2016级硕士生:刘三、李八、李二
    2017级本科生:刘一、琪八、司四九
    导师:刘2
    2016级博士生:天四、王九
    2015级硕士生:李四
    2016级硕士生:刘一
    2017级本科生:刘一

    长路漫漫,队友作伴

  • 相关阅读:
    Splay板子
    HZOI帝国2019欢乐时刻
    数据分析体系 — 用户粘性的两个计算指标(DAU/MAU和月人均活跃天数)
    mysql—MySQL数据库中10位时间戳转换为标准时间后,如何对标准时间进行加减X天处理
    每日一题力扣575 分糖果
    每日一题力扣455 小饼干和孩子
    每日一题力扣561
    每日一题力扣121 最佳买股票
    每日一题力扣605 种花问题
    每日一题力扣605 种花问题
  • 原文地址:https://www.cnblogs.com/Martrix-revolution/p/11704673.html
Copyright © 2020-2023  润新知