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

1.链接

  • github地址
  • 结对同学

2.给出具体分工

031702338郑学贵:代码编写

031702612 陈志超:需求分析,素材收集,ui设计,测试

3.PSP表格

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

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

需求分析

读完题目,经过认真的分析,NABCD模型,我们将整个需求分成三个模块

  • 处理输入数据模块
  • TreeGraph模块
  • 个人信息展示模块

算法关键

主要在于处理输入数据,首先空行分割数据,数据按组来处理,每一组在通过关键字检测提取分割,最后维护出图的邻接表。然后通过dfs递归遍历图,将数据格式修改为指定要求的构建树图数据格式,传入对应的类,渲染出关系树。

树的结构设计

因为存在多树关联的情况,那么本质上就是构造出一张DAG,但是我们经过讨论后,认为如果构造一张DAG的话,可能层级结构不是那么清晰,我们决定如果多棵树有公共节点就合并成为一颗树,每一个级别也抽象成一个点,例如"2016级博士生"也作为图上的一个点,每一人物节点的父节点先是他是什么年级的学生,再连着他的导师,公共节点拿去拆分成多个副本,这样结构关系清晰,并且也能够清楚知道他跟过哪些导师,但是每个人只保存他的最高学历。

软件工程实践2019第五次作业_第1张图片

代码片段(已加注释)

因为写的网页,唯一有逻辑性的代码则就只有处理数据这一模块,其他部分只是处理页面样式等。

handleData() {
      let text = document.getElementById("data");
      var data = text.value; //从输入框获取数据
      var lis = data.split("\n");  //先按空行分割成多组数据
      let rk = new Map();  //用于比较排名,记录某人的最高学历
      (rk["导师"] = 0),
        (rk["博士生"] = 1),
        (rk["硕士生"] = 2),
        (rk["本科生"] = 3);
      var ID = 0;
      let str = ["博士生", "硕士生", "本科生"]; //关键字检测
      var _this = this;
      for (var i = 0; i < lis.length; ) {
        var j;
        for (j = i + 1; j < lis.length; ++j) {
          if (lis[j] == "") break;
        }    
        // [i,j)为一组数据
        let th = lis[i].substring(3);

        _this.edge[th] = [];
        _this.info[th] = "导师";
        //使用map,map的第一维是字符串,对应人名,第二维对应一个数组,对应他连接的人
        for (var k = i + 1; k < j; ++k) {
          var cur, idx;
          for (var value of str) {
            idx = lis[k].indexOf(value);
            if (idx != -1) {
              cur = lis[k].substring(0, idx + 3);
              _this.edge[th].push(lis[k].substring(0, idx + 3) + th);
              _this.edge[cur + th] = [];
              _this.info[cur + th] = value;
              _this.used[cur + th] = 1;
               //used用于标记某个点是否有父节点
                //info用于处理每个人的最高学历
              break;
            }
          }
          var stu = lis[k].substring(idx + 4).split("、");
          for (var value of stu) {
              //更新最高学历
            if (_this.info[value] == null || rk[_this.info[value]] > rk[cur])
              _this.info[value] = cur;
             //通过、分割,进行连边
            _this.edge[cur + th].push(value);
            _this.used[value] = 1;
          }
        }
        i = j + 1;
      }
        
      for (var key in _this.info) {
            //可能存在多个树,我们之前将有父节点的点used都标记了,
          //因此used没被标记过的点则一定是根节点,从根节点出发,递归遍历图,处理数据格式
          if (_this.used[key] == null) {
          _this.data.push(_this.formatData(key, -1));
        }
      }
      this.$router.push({
        path: "/user/relation",
        query: {
          data: JSON.stringify(_this.data)
        }
      });
    },
    formatData(rt, fa) {
       //每个点的信息包括id,name,lv(学历),以及他的儿子节点,其他就是普通的dfs。
      let now = {};
      now.name = rt;
      now.id = this.ID;
      this.ID += 1;
      now.lv = this.info[rt];
      now.children = [];
      let arr = this.edge[rt];
      if (arr == null) return now;
      for (var i = 0; i < arr.length; ++i) {
        now.children.push(this.formatData(arr[i], rt));
      }
      if (rt.indexOf(fa) != -1) {
        let tmp = rt.substring(0, rt.indexOf(fa));
        now.name = tmp;
      }
      return now;
    }

5.附加特点设计与展示

5.1设计的创意独到之处,这个设计的意义

  • 将数据用树状图可视化,这样结构清晰,人物之间的关系一目了然
  • 增加了查看个人信息的功能,显示他的信息,以及以他为根的关系树。
  • 系统模块化开发,扩展性强,后续可以增加其他新的功能
  • 单独设置一个处理输入的页面,更加美观

5.2实现思路

在树图界面中,每个节点添加event,右键即可跳转查看对应的信息。

5.3代码片段

graph.on("node:contextmenu", ev => {
        //找到节点的信息,如果是‘xxx级博士生’等虚拟节点则不跳转,如果是真实人物则跳转到个人信息页面
        //传递对应的参数
        let name=ev.item._cfg.model.label;
        if(name.indexOf("博士生")!=-1)return;
        if(name.indexOf("硕士生")!=-1)return;
        if(name.indexOf("本科生")!=-1)return;
        this.$router.push({
          path:'info',
          query:{
            data:ev.item._cfg.model
          }
        })
      });

5.4成果展示

软件工程实践2019第五次作业_第2张图片

显示个人信息,以及以他为根的关系树。

软件工程实践2019第五次作业_第3张图片

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

6.1目录组织

s使用vue+iview+antv开发,vue脚手架大大提升生产力,src文件下,assets存放静态资源,components存放不同的模块,router配置一下路由,控制页面跳转,用到的资源全局导入即可。

软件工程实践2019第五次作业_第4张图片

dist文件夹:只包括图中两项,在本地服务器上直接运行index.html即可。

6.2如何运行

方式一:下载dist文件夹。然后再本地服务器上打开index.html(可以用vscode打开,然后装个live server,go live即可)。

Tip: built files are meant to be served over an HTTP server.
Opening index.html over file:// won't work.

方式二:下载所有文件,先装node,再安装vue,然后

cd ‘对应的文件夹’
npm install 
npm run dev

6.3运行截图及说明

在文本框内输入合法数据,按按钮即可生成

软件工程实践2019第五次作业_第5张图片

生成的图如下,关系树支持拖动,大小缩放,鼠标放在上面滚轮滑动即可缩放,鼠标选中即可拖动。多颗树的时候,下拉浏览器滚动条即可看到其他树。

软件工程实践2019第五次作业_第6张图片

点击对应的节点可展开或收缩他的儿子节点。
软件工程实践2019第五次作业_第7张图片

右键人物节点跳转到个人信息界面,显示他为根的关系树。

软件工程实践2019第五次作业_第8张图片

7.单元测试【10'】

7.1如何构造测试数据?

根据不同情况,构造出边界数据,单树的情况,多树的情况,多树关联的情况

7.2测试工具 以及学习

使用的vue-jest,有官方文档,并且讲的通俗易懂。

7.3部分代码

因为整个作业下来更多的是页面的样式,都可以直观的测试出来,有可能出错的就是在于数据的处理,自己构造了一些数据用jest测试。

软件工程实践2019第五次作业_第9张图片

顺利通过测试(inputData中处理输入数据)

软件工程实践2019第五次作业_第10张图片

8.贴出Github的代码签入记录

软件工程实践2019第五次作业_第11张图片

9.遇到的代码模块异常或结对困难及解决方法【4'】

问题描述

树图的位置和button一直不对,以及组件的样式问题。

做过哪些尝试

查找博客,去社区和qq群提问。

是否解决?

已经解决。

收获

提升了解决问题的能力,对框架的使用和一些坑点有了更深的理解。

10.评价你的队友

值得学习的地方

分析需求准确,能将需求合理的拆分成各个模块,开发能力强,效率高

需要改进的地方

需要更好的配合以及沟通交流,相信我们能更好更快的完成作业

你可能感兴趣的:(软件工程实践2019第五次作业)