这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/SE2020 |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/SE2020/homework/11277 |
这个作业的目标 | 根据输入的文本内容在网页页面上呈现树形结构形式的师门树 |
学号 | 031802507 031802509 |
具体分工
031802507 邓家俊 : HTNML 文件、 CSS 文件
031802509 胡启华 : Javascript 文件 、单元测试 、HTML 文件 、CSS 文件
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 20 |
Estimate | 估计这个任务需要多少时间 | 15 | 15 |
Development | 开发 | 180 | 240 |
Analysis | 需求分析 (包括学习新技术) | 180 | 300 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
Design | 具体设计 | 30 | 60 |
Coding | 具体编码 | 120 | 150 |
Code Review | 代码复审 | 30 | 60 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 120 |
Reporting | 报告 | 60 | 90 |
Test Report | 测试报告 | 30 | 30 |
Size Measurement | 计算工作量 | 30 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 865 | 1225 |
一、解题思路描述和设计实现说明
解题思路描述
解题之前需要学习知识
流程图
设计实现说明
1、HTML 页面
把 CSS 和 JS 代码存都放到外部文件中,便于维护。
通过 div 块级元素,用于对内容块设置样式属性,以及文档布局。
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./index.js"></script>
<link rel="stylesheet" type="text/css" href="./bootstrap.css">
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container" id="main">
<div class="row">
<div class="col-sm-4" id="input_area">
<div id="input_head" class="col-sm-12">输入数据</div>
<textarea id="text" class="col-sm-12">请输入数据</textarea>
<div class="col-sm-12" id="space"></div>
<button id="button" class="col-sm-12" onclick="submit()">提交</button>
</div>
<div class="col-sm-2" id="menu_area">
<div id="menu_head">导师列表</div>
<div id="menu" ></div>
</div>
<div class="col-sm-4" id="tree_area">
<div id="tree_head" class="col-sm-12">树形图</div>
<div id="tree" class="col-sm-12"></div>
</div>
</div>
</div>
</body>
</html>
2. CSS 代码
#main{
position: absolute;
//border: aqua 5px solid;
100%;
top: 10%;
}
#space{
height: 29px;
}
#text{
100%;
height: 290px;
}
#input_head{
text-align: center;
//border-top: gold 5px solid;
background-color: lightgoldenrodyellow;
}
#input_area{
background-color: lightgoldenrodyellow;
border-top: gold 5px solid;
margin: 2.6%;
}
#button{
100%;
}
#menu_head{
text-align: center;
}
#menu_area{
border-top: gold 5px solid;
background-color: lightgoldenrodyellow;
margin: 2.6%;
}
#menu{
background-color: lightgoldenrodyellow;
}
#menu_name{
margin-bottom: 5px;
}
#tree_area{
background-color: lightgoldenrodyellow;
border-top: gold 5px solid;
margin: 2.6%;
}
#tree_head{
text-align: center;
background-color: lightgoldenrodyellow;
}
#teacher_name{
position: relative;
left: -15px;
}
#type{
margin: 5px;
position: relative;
left: 29px;
}
#student{
margin: 5px;
position: relative;
left: 29px;
}
#skill{
margin: 5px;
position: relative;
left: 29px;
}
二、附加特点设计与展示
附加特点设计
- 可以多次提交文本并新增树和节点,但不会创建重复的树和节点
- 意义:可以不断添加新的导师和新的师门树信息,导师列表和每个导师对应的师门树也会随之增添新的树和节点。
- 实现思路:
- 将从文本中读取到的信息都存储在 teacher 和 student 对象中,导师列表和师门树的数据都从 teacher 和 student 中获取。
- 在将读取到的文本信息存入对象中之前先检查这个信息是否已经存在于对象中,如果不存在则插入新的信息,如果存在则跳过该信息。
- 可以检测到文本输入格式错误,并提示用户
- 意义:防止格式错误导致存入不符合要求的信息
- 实现思路:
- 在读取每一条文本信息的时候都先检查格式是否符合要求,如果不符合要求便中止读取,并弹出窗口提示用户格式错误的种类。
- 在错误格式出现之前的数据能够正常存入对象中。
实现成果展示
正常输入
错误输入
三、目录说明和使用说明
目录说明
031802507-031802509
index.html
index.js
index.css
fun.js
fun.test.js
使用说明
- 从仓库中下载文件
git clone https://github.com/Victorique0/031802507-031802509.git
-
解压后选择用谷歌浏览器打开文件中的 index.html 文件即可打开页面
-
在文本框输入文本信息后点击提交按钮即可提交数据
-
提交的文本会被处理成有效的数据并存储在对象中,导师列表会显示对象中所有导师的名字
-
点击导师的名字即可显示这个导师的师门树
-
点击师门树的各个节点便可以进行缩放
-
有需要的话可以继续输入文本添加更多的信息,页面会读取文本并忽略重复的数据,将新的数据存入对象中,导师列表和各个导师的师门树也会相应更新
四、单元测试
单元测试工具
使用 Mocha 进行单元测试
单元测试代码
进行单元测试的函数是对文本输入进行处理并将数据存入对象中的函数,单元测试代码检测函数产生的对象是否和应该得出的正确的对象相同
fun.js
function submit(msg,input_teacher,input_student) {
var teacher = {};
var student = {};
var list = msg.split("
");
var error_type = 0;
//这部分的内容与 index.js 中的 submit 函数的主体几乎完全一致,只进行了极少量的修改,因为篇幅过长就省略了
//详细内容可以在 https://github.com/Victorique0/031802507-031802509/blob/main/fun.js 中查看
// 验证 teacher
if(teacher.length!==input_teacher.length||student.length!==input_student.length)
return 0;
for(var teacher_name in teacher)
{
if(!input_teacher.hasOwnProperty(teacher_name))
{
console.log("teacher name error
");
return 0;
}
var type = teacher[teacher_name];
var input_type = input_teacher[teacher_name];
//console.log(type);
//console.log(input_type);
if(type.length!==input_type.length)
{
console.log("type length error
");
return 0;
}
for(var type_name in type)
{
if(input_teacher.hasOwnProperty(type_name))
{
//console.log(type_name);
console.log("type name error
");
return 0;
}
var stu_list = type[type_name];
var input_stu_list = input_type[type_name];
if(stu_list.length!==input_stu_list.length)
{
console.log("stu_list length error");
return 0;
}
for(var item = 0;item<stu_list.length;item++)
{
var now_stu = stu_list[item];
for(var input_item = 0;input_item<input_stu_list.length;input_item++)
{
var flag = 0;
var now_input_stu = input_stu_list[input_item];
if(now_stu!==now_input_stu)
continue;
if(now_stu===now_input_stu)
{
flag = 1;
break;
}
}
if(flag===0)
{
console.log("student name error in teacher list
");
return 0;
}
}
}
}
//验证 student
if(student.length!==input_student.length)
{
console.log("student skill length error
");
return 0;
}
if(student.length===0)
return 1;
for(var stu_name in student) {
if (!input_student.hasOwnProperty(stu_name))
{
console.log("student name error in student list
");
return 0;
}
if(student[stu_name].length!==input_student[stu_name].length)
{
console.log("skill length error
");
return 0;
}
for(var skill_name_item = 0;skill_name_item<student[stu_name].length;skill_name_item++)
{
var now_skill = student[stu_name][skill_name_item];
for(var input_skill_name_item = 0;input_skill_name_item<input_student[stu_name].length;input_skill_name_item++)
{
var flag = 0;
if(input_student[stu_name][input_skill_name_item]!==now_skill)
continue;
if(input_student[stu_name][input_skill_name_item]===now_skill)
{
flag = 1;
break;
}
}
if(flag===0)
{
console.log("skill name error
");
return 0;
}
}
}
return 1;
}
module.exports = submit;
fun.test.js
var submit = require('./fun.js');
var expect = require('chai').expect;
//这部分的内容的是六次测试中的输入文本和函数处理后对应的正确结果,篇幅过长便省略了,可以在 https://github.com/Victorique0/031802507-031802509/blob/main/fun.test.js 中查看
describe('文本处理函数测试1(标准输入)', function() {
it('函数处理文本后得到的结果和正确结果相一致', function() {
expect(submit(input1,result_teacher1,result_student1)).to.be.equal(1);
});
});
describe('文本处理函数测试2(标准输入)', function() {
it('函数处理文本后得到的结果和正确结果相一致', function() {
expect(submit(input2,result_teacher2,result_student2)).to.be.equal(1);
});
});
describe('文本处理函数测试3(多组标准输入,每组的导师不同)', function() {
it('函数处理文本后得到的结果和正确结果相一致', function() {
expect(submit(input3,result_teacher3,result_student3)).to.be.equal(1);
});
});
describe('文本处理函数测试4(多组标准输入,每组的导师相同)', function() {
it('函数处理文本后得到的结果和正确结果相一致', function() {
expect(submit(input4,result_teacher4,result_student4)).to.be.equal(1);
});
});
describe('文本处理函数测试5(输入错误格式的文本:人员信息和技能树之间没有空行)', function() {
it('函数处理文本后得到的结果和正确结果相一致', function() {
expect(submit(input5,result_teacher5,result_student5)).to.be.equal(1);
});
});
describe('文本处理函数测试6(输入错误格式的文本:导师信息和各级学生信息之间多了空行)', function() {
it('函数处理文本后得到的结果和正确结果相一致', function() {
expect(submit(input6,result_teacher6,result_student6)).to.be.equal(1);
});
});
构造测试数据的思路
测试数据的类型
-
正常单次输入
-
正常多次输入,不输入重复的数据
-
正常多次输入,但存在重复的数据
-
异常输入,人员信息和技能树之间没有空行
-
异常输入,导师信息和各级学生信息之间多了空行
五、Github 代码签入记录
六、遇到的代码模块异常或结对困难及解决方法
遇到的问题
- HTML 界面的的合理性,做的感觉太 low 了。通过菜鸟教程和 CSDN 的例子,最后用
<div>
块级元素来实现。参考大佬的代码,一步步调整 CSS 参数。
收获
- 进一步熟悉了 Github 的使用。
- 了解和学习了 HTML CSS JS 相关的基础知识。
七、评价队友
- 值得学习的地方:学习能力强,极限编程贯彻者,做事态度认真负责。
- 需要改进的地方:无