软件工程实践2019第五次作业

项目 地址
本作业博客链接 https://edu.cnblogs.com/campus/fzu/2019FZUSEZ/homework/8736
Github项目地址 https://github.com/nevermoress/031702130-031702131.git

一、结对信息和具体分工

姓名 学号 分工 地址
张成德 031702130 编写前端页面,编写博客,测试 https://www.cnblogs.com/zcd031702130/
蔡劭凡 031702131 编写前端页面,编写输入模块,总结 https://www.cnblogs.com/cai1999/

二、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟 实际耗时(分钟)
Planning 计划 30 45
-Estimate -估计这个任务需要多少时间 30 45
Development 开发 1740 2400
-Analysis -需求分析(包括学习新技术) 360 480
-Design Spec -生成设计文档 30 30
-Design Review -设计复审 10 10
-Coding Standard -代码规范(为目前的开发制定合适的规范) 20 20
-Design -具体设计 30 40
-Coding -具体编码 960 1200
-Code Review -代码复审 30 20
-Test -测试 300 600
Reporting 报告 50 75
-Test Repor -测试报告 20 30
-Size Measurement -计算工作 20 30
-Postmortem & Process Improvement Plan -事后总结, 并提出过程改进计划 10 15
合计 1820 2520

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

1.代码组织与内部实现设计

    以html为主体,在body中主要分为两个模块:1.数据处理模块、2.树型结构的渲染模块。第一部分将在下面说明,第二部分调用了bootstrap、jQuery、d3三种JavaScript框架。

2.算法的关键与关键实现部分流程图

    算法的关键:我们认为算法的关键是输入信息的提取部分,实现方法:在页面中创建文本框,将文本内容全部保存在一个变量中,对变量进行信息提取,采用循环和sprit()语句进行拆分,以及indexOf()语句进行判断,对文本内容先后根据“\n”,“:”,“级”以及“、”等关键字进行拆分存取。

3.重要的代码片段

  • 数据处理模块
for(l=0;l<line.length;l++)
        {
          //判断导师还是学生信息
            if(line[l].indexOf("导师")!=-1)
            {
            tline=line[l].split(":");
            tname=tline[1];
            }
            else
            {
              //用split对变量进行拆分,重新储存
                sline=line[l].split(":");
                sline1=sline[0].split("级");
                if(sline1[1].indexOf("博士")!=-1)
                {
                    if(student[0]==1){
                        k++;}
                    else {
                        k=0;}
                    student[0]=1;
                    grade0[k]=sline1[0];
                    sname0[k]=sline[1].split("、");
                }
                else if(sline1[1].indexOf("硕士")!=-1)
                {
                    if(student[1]==1){
                        k++;}
                    else {
                        k=0;}
                    student[1]=1;
                    grade1[k]=sline1[0];
                    sname1[k]=sline[1].split("、");
                }
                else
                {
                    if(student[2]==1){
                        k++;}
                    else {
                        k=0;}
                    student[2]=1;
                    grade2[k]=sline1[0];
                    sname2[k]=sline[1].split("、");
                }
            }
        }
  • 树型结构的渲染模块
<script>
        $("#begin").click(function(){
        var content = document.getElementById("txt").value;
            var line = content.split("\n");
            var tline,j=0,sline1=0,k=0,l=0,tname=0;
            var sline,student=[0,0,0],sname0=[],sname1=[],sname2=[],grade0=[],grade1=[],grade2=[];
        for(l=0;l<line.length;l++)
        {
          //判断导师还是学生信息
            if(line[l].indexOf("导师")!=-1)
            {
            tline=line[l].split(":");
            tname=tline[1];
            }
            else
            {
              //用split对变量进行拆分,重新储存
                sline=line[l].split(":");
                sline1=sline[0].split("级");
                if(sline1[1].indexOf("博士")!=-1)
                {
                    if(student[0]==1){
                        k++;}
                    else {
                        k=0;}
                    student[0]=1;
                    grade0[k]=sline1[0];
                    sname0[k]=sline[1].split("、");
                }
                else if(sline1[1].indexOf("硕士")!=-1)
                {
                    if(student[1]==1){
                        k++;}
                    else {
                        k=0;}
                    student[1]=1;
                    grade1[k]=sline1[0];
                    sname1[k]=sline[1].split("、");
                }
                else
                {
                    if(student[2]==1){
                        k++;}
                    else {
                        k=0;}
                    student[2]=1;
                    grade2[k]=sline1[0];
                    sname2[k]=sline[1].split("、");
                }
            }
        }
        var treeData = [
            {
                "name": tname,
                "parent": "null",
                "children": [
                    {
                        "name": "博士生",
                        "parent": tname,
                        "children": [
                            {
                                "name": grade0[0],
                                "parent": "博士生",
                                "children": [
                                    {
                                        "name": sname0[0][0],
                                        "parent": "2015"
                                    },
                                    {
                                        "name": sname0[0][1],
                                        "parent": "2015"
                                    },
                                    {
                                        "name": sname0[0][2],
                                        "parent": "2015"
                                    },
                                ]
                            },
                        ]
                    },
                    {
                        "name": "硕士生",
                        "parent": tname,
                        "children": [
                            {
                                "name": grade1[0],
                                "parent": "硕士生",
                                "children": [
                                    {
                                        "name": sname1[0][0],
                                        "parent": "2015"
                                    },
                                    {
                                        "name": sname1[0][1],
                                        "parent": "2015"
                                    },
                                    {
                                        "name": sname1[0][2],
                                        "parent": "2015"
                                    },
                                 ]
                            },
                            {
                                "name": grade1[1],
                                "parent": "硕士生",
                                "children": [
                                    {
                                        "name": sname1[1][0],
                                        "parent": "2015"
                                    },
                                    {
                                        "name": sname1[1][1],
                                        "parent": "2015"
                                    },
                                    {
                                        "name": sname1[1][2],
                                        "parent": "2015"
                                    },
                                ]
                            }
                        ]
                    },
                    {
                        "name": "本科生",
                        "parent": tname,
                        "children": [
                            {
                                "name": grade2[0],
                                "parent": "本科生",
                                "children": [
                                    {
                                        "name": sname2[0][0],
                                        "parent": "2017"
                                    },
                                    {
                                        "name": sname2[0][1],
                                        "parent": "2017"
                                    },
                                    {
                                        "name": sname2[0][2],
                                        "parent": "2017"
                                    },
                                ]
                            },
                        ]
                    },
                ]
            }
        ];
//定义树图的全局属性(宽高)
        var margin = {top: 20, right: 120, bottom: 20, left: 120},
            width = 1280 - margin.right - margin.left,
            height = 980 - margin.top - margin.bottom;
        var i = 0,
            duration = 750,//过渡延迟时间
            root;
        var tree = d3.layout.tree()//创建一个树布局
            .size([height, width]);
        var diagonal = d3.svg.diagonal()
            .projection(function (d) {
                return [d.y, d.x];
            });//创建新的斜线生成器
//声明与定义画布属性
        var svg = d3.select("body").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
        root = treeData[0];//treeData为上边定义的节点属性
        root.x0 = height / 2;
        root.y0 = 0;
        update(root);
        d3.select(self.frameElement).style("height", "500px");
        function update(source) {
            // Compute the new tree layout.计算新树图的布局
            var nodes = tree.nodes(root).reverse(),
                links = tree.links(nodes);
            // Normalize for fixed-depth.设置y坐标点,每层占180px
            nodes.forEach(function (d) {
                d.y = d.depth * 180;
            });
            // Update the nodes…每个node对应一个group
            var node = svg.selectAll("g.node")
                .data(nodes, function (d) {
                    return d.id || (d.id = ++i);
                });//data():绑定一个数组到选择集上,数组的各项值分别与选择集的各元素绑定
            // Enter any new nodes at the parent's previous position.新增节点数据集,设置位置
            var nodeEnter = node.enter().append("g")  //在 svg 中添加一个g,g是 svg 中的一个属性,是 group 的意思,它表示一组什么东西,如一组 lines , rects ,circles 其实坐标轴就是由这些东西构成的。
                .attr("class", "node") //attr设置html属性,style设置css属性
                .attr("transform", function (d) {
                    return "translate(" + source.y0 + "," + source.x0 + ")";
                })
                .on("click", click);
            /*//添加连接点---此处设置的是圆圈过渡时候的效果(颜色)
   nodeEnter.append("circle")
       .attr("r", 1e-6)
       .style("fill", function(d) { return d._children ? "lightsteelblue" : "#357CAE"; });//d 代表数据,也就是与某元素绑定的数据。*/
            nodeEnter.append("rect")
                .attr("x", -23)
                .attr("y", -10)
                .attr("width", 150)
                .attr("height", 50)
                .attr("rx", 10)
                .style("fill", "#357CAE");//d 代表数据,也就是与某元素绑定的数据。
            nodeEnter.append("text")
            //.attr("x", function(d) { return d.children || d._children ? 13 : 13; })
                .attr("x", "50")
                .attr("dy", "20")
                .attr("text-anchor", "middle")
                .text(function (d) {
                    return d.name;
                })
                .style("fill", "white")
                .style("fill-opacity", 1);
            //将节点过渡到一个新的位置-----主要是针对节点过渡过程中的过渡效果
            //node就是保留的数据集,为原来数据的图形添加过渡动画。首先是整个组的位置
            var nodeUpdate = node.transition()  //开始一个动画过渡
                .duration(duration)  //过渡延迟时间,此处主要设置的是圆圈节点随斜线的过渡延迟
                .attr("transform", function (d) {
                    return "translate(" + d.y + "," + d.x + ")";
                });
            nodeUpdate.select("rect")
                .attr("x", -23)
                .attr("y", -10)
                .attr("width", 150)
                .attr("height", 50)
                .attr("rx", 10)
                .style("fill", "#357CAE");
            nodeUpdate.select("text")
                .attr("text-anchor", "middle")
                .style("fill-opacity", 1);
            //过渡现有的节点到父母的新位置。
            //最后处理消失的数据,添加消失动画
            var nodeExit = node.exit().transition()
                .duration(duration)
                .attr("transform", function (d) {
                    return "translate(" + source.y + "," + source.x + ")";
                })
                .remove();
            nodeExit.select("rect")
                .attr("x", -23)
                .attr("y", -10)
                .attr("width", 150)
                .attr("height", 50)
                .attr("rx", 10)
                .style("fill", "#357CAE");
            nodeExit.select("text")
                .attr("text-anchor", "middle")
                .style("fill-opacity", 1e-6);
            // Update the links…线操作相关
            //再处理连线集合
            var link = svg.selectAll("path.link")
                .data(links, function (d) {
                    return d.target.id;
                });
            //添加新的连线
            link.enter().insert("path", "g")
                .attr("class", "link")
                .attr("d", function (d) {
                    var o = {x: source.x0, y: source.y0};
                    return diagonal({source: o, target: o});  //diagonal - 生成一个二维贝塞尔连接器, 用于节点连接图.
                })
                .attr('marker-end', 'url(#arrow)');
            //将斜线过渡到新的位置
            //保留的连线添加过渡动画
            link.transition()
                .duration(duration)
                .attr("d", diagonal);
            //过渡现有的斜线到父母的新位置。
            //消失的连线添加过渡动画
            link.exit().transition()
                .duration(duration)
                .attr("d", function (d) {
                    var o = {x: source.x, y: source.y};
                    return diagonal({source: o, target: o});
                })
                .remove();
            //将旧的斜线过渡效果隐藏
            nodes.forEach(function (d) {
                d.x0 = d.x;
                d.y0 = d.y;
            });
        }
//定义一个将某节点折叠的函数
//切换子节点事件
        function click(d) {
            if (d.children) {
                d._children = d.children;
                d.children = null;
            } else {
                d.children = d._children;
                d._children = null;
            }
            update(d);
        }
    // }
    });
</script>

四、附加特点设计与展示

1.设计的创意独到之处

    设计了文本框填写信息界面的文字引导

2.实现思路

    在信息输入部分代码加入文字引导

3.重要的代码片段

<textarea id="txt" placeholder=
  "请输入家族树信息:
  例如:
  导师:张三
  2016级博士生:天一、王二、吴五
  2015级硕士生:李四、王五、许六
  2016级硕士生:刘一、李二、李三
  2017级本科生:刘六、琪七、司四"
  rows="20" cols="35">
  </textarea>

4.实现成果展示


五、目录说明和使用说明

1.目录说明

    在github里面存放了tree.html和js文件夹,文件夹里是代码引用的框架

2.使用说明

     下载js文件夹以及html文件的压缩包,下载完解压,用谷歌浏览器打开tree.html就能运行。


六、单元测试

1.测试工具

    Chrome的F12里的Console,因为在网易云课堂上看叶建华老师的JS教程时,他在很多时候都运用了Chrome的F12里的Console来进行单元测试,我觉得这是一个既简单又快捷的单元测试办法。

2.测试的函数

    console.log()函数

3.说明构造测试数据的思路

    构造测试数据的思路当然是不停的改变数据,并尽可能考虑各种数据出现的情况,比如说输入的行数,每一行的名字数,每个名字的字数等等等等。


七、Github的代码签入记录


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

1.问题描述

一开始不会处理输入的数据,最后不能实现多棵树并联

2.做过哪些尝试:

在搜索引擎上查阅相关资料

3.是否解决:

部分解决

4.收获:

学会了对输入数据的分割,关键字提取,JS正则等内容,能够将输入数据转化为树形结构,遗憾的是还未实现树的动态并联。


九、评价你的队友

评价我的队友蔡邵凡:

1.值得学习的地方:谦虚好学,学习效率高,关键人还长得帅。
2.需要改进的地方:需要更好的配合以及沟通交流。


posted @ 2019-10-19 16:01  nevermores  阅读(304)  评论(1编辑  收藏  举报