结对编程之学术家族树
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/SE2020 |
---|---|
作业博客链接 | https://edu.cnblogs.com/campus/fzu/SE2020/homework/11277 |
GitHub项目地址 | https://github.com/AJiang0704/031802309-031802320 |
- 一、结对说明
- 二、PSP表格
- 三、解题思路描述与设计实现说明
- 四、附加特点设计与展示
- 五、目录结构和使用说明
- 六、单元测试
- 七、多组数据测试
- 八、Github 的代码签入记录
- 九、遇到的代码模块异常或结对困难及解决方法
- 十、评价你的队友
一、结对说明
学号 | 姓名 | 博客链接 | 具体分工 |
---|---|---|---|
031802309 | 郭盈江 | 算法设计、UI设计、代码编写 | |
031802320 | 刘国强 | 分析归纳、收集素材、单元测试 |
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
Estimate | 估计这个任务需要多少时间 | 30 | 20 |
Development | 开发 | ||
Analysis | 需求分析 (包括学习新技术) | 60 | 120 |
Design Spec | 生成设计文档 | 20 | 30 |
Design Review | 设计复审 | 40 | 40 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 40 | 30 |
Design | 具体设计 | 40 | 40 |
Coding | 具体编码 | 360 | 520 |
Code Review | 代码复审 | 20 | 40 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 240 |
Reporting | 报告 | ||
Test Report | 测试报告 | 60 | 60 |
Size Measurement | 计算工作量 | 30 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 90 | 120 |
合计 | 910 | 1290 |
三、解题思路描述与设计实现说明
代码实现思路:
js 接收到从文本框输入的数据后,根据关键字进行解析,逐次分组切割,并依次将它们嵌入节点,以构造树型结构。
然后绘制树状图,使用 d3.js 可以得到可视化树图,显示在 web 页面。
数据流图:
核心代码:
GetData 函数用于接收并处理数据。
/**
*接收并解析数据以构造 json 树结构
*/
function GetData() {
document.getElementById('show-tree').innerHTML = '';
var text = document.getElementById("input-text").value;
if (!text) alert("输入不能为空哦");
var mul_data = text.split("\n\n");
var h = 0;
var hide = [];
var count_tree = 0;
for (var i = 0; i < mul_data.length; i++) {
count_tree++;
var pic_data = mul_data[i].split("\n");
var line = 0;
for (var j = 0; j < pic_data.length; j++) {
var per_data = pic_data[j].split(":");
var per_front = per_data[0];
var per_back = per_data[1];
if (per_front == "导师") {
var teacher = {
"name": per_back,
"parent": null,
"children": []
}
TreeData[i] = teacher;
} else if(per_front.search("博士生") >= 0 || per_front.search("硕士生") >= 0 || per_front.search("本科生") >= 0) {
var grade = {
"name": per_front,
"parent": null,
"children": []
}
TreeData[i].children[line] = grade;
var per_name = per_back.split("、");
for (var k = 0; k < per_name.length; k++) {
var name = {
"name": per_name[k],
"parent": null,
"children": []
}
TreeData[i].children[line].children[k] = name;
}
line ++;
} else {
var identity_name = {
"name": per_front,
"parent": null,
"children": []
}
TreeData[i] = identity_name;
var per_identity = per_back.split("、");
for (var k = 0; k < per_identity.length; k++) {
var identity = {
"name": per_identity[k],
"parent": null,
"children": []
}
TreeData[i].children[k] = identity;
}
}
}
/*********check*********/
for (n = 0; n < i; n++) {
check(TreeData[n], TreeData[i].name, TreeData[i]);
}
if (flag) {
TreeData[i] = [];
hide[h] = i;
h++;
}
flag = 0;
/*********check*********/
}
/*********make*********/
var flag_hide = 0;
//alert(count_tree);
for (i = 0; i < count_tree; i++) {
//alert(hide);
for(j = 0; j < h; j ++){
if(hide[j] == i) {
flag_hide = 1;
}
}
if(!flag_hide) MakeTreeGraph(i);
flag_hide = 0;
}
/*********make*********/
}
check 函数用于遍历之前所有树的子节点,与所要查找的名字比较,若相同则是关联树,该节点添加到之前的树上。
值得注意的是在 GetData 中调用 check 的位置。若有关联树被并为子树,则原来的树被赋为空数组并隐藏,最终的 web 页面不会显示。
/**
* 遍历之前所有树的子节点,与所要查找的名字比较,若相同则并为子树
* @param tree json树
* @param name 需遍历寻查找的名字
* @param node 若遍历到相同的学生名字则成为子节点
* @return 1 是关联树
* 0 不是关联树
*/
function check(tree, name, node) {
var length = 0;
for (var i in tree.children) {
length++;
}
for (var i = 0; i < length; i++) {
if (tree.children[i].name == name) {
flag = 1;
tree.children[i] = node;
return 1;
} else {
check(tree.children[i], name, node);
}
}
return 0;
}
四、附加特点设计与展示
1.可以将生成的学术家族树作为图片下载下来
核心代码:
使用 html2canvas 将 div 内容写入 Canvas 生成图片,再用 FileSaver.js 进行下载。
function convert() {
html2canvas(document.querySelector("#show"),{
scrollY: -330,
scrollX: 0,
useCORS: true
}).then(canvas => {
canvas.toBlob(function(blob) {
saveAs(blob, "Tree.png");
});
//document.body.appendChild(canvas);
});
};
效果展示:
2.输入下一次数据时无需刷新页面,直接在文本框输入即可自动清除之前的树
核心代码:
在处理新的数据前加入:
document.getElementById('show-tree').innerHTML = '';
效果展示:
五、目录结构和使用说明
├──css
│ └──style.css
├──img
│ └──bkg.jpg
├──js
│ ├──graphing.js
│ └──d3.v3.min.js
└──index.html
下载后使用 Google Chrome 运行 index.html 即可展现预期结果。
六、单元测试
测试工具: mocha
Mocha是现在最流行的 JavaScript 测试框架之一,在浏览器和 Node 环境都可以使用。
安装环境: node.js
文件配置:
安装后配置单元测试的文件。在其目录下建立 datatest 文件夹,把要测试的 GetData.js 文件放进去。
如何运行:
在测试文件同目录下新建一个 GetData.test.js 然后就可以写单元测试代码啦!使用命令行进入目录,输入mocha GetData.test.js
命令即可。
单元测试代码与运行结果:
部分代码如图,用于测试 GetData() 函数。
构造测试数据的思路:
根据测试时输入数据可能出现的各种异常情况编写代码,比如空格、空行、输入为空、输入导师时忘了写前面的部分等等。
如何考虑将来测试人员的刁难?那就……测出什么 bug 改什么 bug ……
七、多组数据测试
测试数据1:
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四
测试数据2:
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四
刘六:JAVA、数学建模
李二:字节跳动、京东云
测试数据3:
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四
导师:天一
2016级博士生:小方、小二、小吴
2015级硕士生:小李、小王、小许
2016级硕士生:小刘、小刚、小红
2017级本科生:小六、小丽、小七
测试数据4:
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四
刘六:JAVA、数学建模
李二:字节跳动、京东云
导师:天一
2018级博士生:小方、小二、小吴
2017级硕士生:小李、小王、小许
2018级硕士生:小刘、小刚、小红
2019级本科生:小六、小丽、小七
测试数据5:
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四
刘六:JAVA、数学建模
李二:字节跳动、京东云
导师:天一
2018级博士生:小方、小二、小吴
2017级硕士生:小李、小王、小许
2018级硕士生:小刘、小刚、小红
2019级本科生:小六、小丽、小七
导师:大明
2018级博士生:大方、大二、大吴
2017级硕士生:大李、大王、大许
2018级硕士生:大刘、大刚、大红
2019级本科生:大六、大丽、大七
导师:阿明
2018级博士生:阿方、阿二、阿吴
2017级硕士生:阿李、阿王、阿许
2018级硕士生:阿刘、阿刚、阿红
2019级本科生:阿六、阿丽、阿七
八、Github 的代码签入记录
九、遇到的代码模块异常或结对困难及解决方法
-
问题描述:关联树被并为子树后,怎样隐藏原来的树?
做过哪些尝试:用了一个数组,专门用来记录这些不需要显示的树
是否解决:已解决
有何收获:对树形结构以及关联树有了不一样的理解 -
问题描述:绘制图时线条不听使唤
做过哪些尝试:网上寻找了很多可视化树型结构的代码,都大同小异……
是否解决:未解决
有何收获:学习了 d3.js 这个可视化库,新技能 get,虽然线条还是丑
十、评价你的队友
郭盈江:我的队友做事条理且有责任心。我们在组队完成任务的过程中,相互鞭策、相互进步。感谢我的队友!美中不足的是我们两个都有拖延症,总是拖到最后,ε=(′ο`*)))唉。
刘国强:我的队友是一个很认真的人,我们配合还算默契、分工也较为明确,即使有一些分歧的时候她也能够很耐心地和我去磨合。通过这次作业我也学到了不少知识。希望下次可以克服拖延症。