2019软工作业五-实现师门树
结对编程成员
031702101 王茜葶:https://www.cnblogs.com/lingluoyu/
031702113 陶俊宇:https://www.cnblogs.com/M031702113/
作业链接
031702101 王茜葶:https://www.cnblogs.com/lingluoyu/p/11704901.html
031702113 陶俊宇:https://www.cnblogs.com/M031702113/p/11704841.html
GitHub项目地址
https://github.com/DreamFeather/031702101-031702113
博客内容最新修改记录
201910/20 :完善博客内容,增加新段落“say something?”
结对分工
陶俊宇:主要是js偏后端方面,树的框架构建,树的输出显示,树的点击操作,树节点增加
王茜葶:负责界面方面,网页元素设计,css style,以及素材搜索与整理
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 5 | 5 |
Estimate | 估计这个任务需要多少时间 | 5 | 5 |
Development | 开发 | 538 | 520 |
Analysis | 需求分析 (包括学习新技术) | 240 | 200 |
Design Spec | 生成设计文档 | 0 | 0 |
Design Review | 设计复审 | 30 | 0 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 3 | 5 |
Design | 具体设计 | 20 | 10 |
Coding | 具体编码 | 120 | 55 |
Code Review | 代码复审 | 5 | 10 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 240 |
**Reporting ** | 报告 | 60 | 35 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 10 | 5 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 10 |
合计 | 603 | 560 |
解题思路
对于师门树这一概念我是不太陌生的,早在软工作业四中我们就已经讨论过了如何以师生关系建立关系网,也就是所谓的师门树。这次作业最大的挑战还是来源于对前端语言的首次接触,从作业发布到提交,仅有10天左右的时间,要入门html+css+js三门语言(没入门的时候觉得是三门,现在觉得是一门)并完成相关作业对我们这些小白来说无疑是千斤重担。而我们并未从框架入手,其实本来想的,但是想看懂框架就得先学习语言,结果语言学会了有思路,就没心思去搞框架了。所以本次作业我们并未使用任何框架,所有代码纯手打。
function Student(name="student") { //Student构建函数-学生
this.name = name;
}
function Tag(name="tag") { //Tag构建函数-标签
this.name = name;
this.list = new Array(); //该数组存放学生对象
this.show = false; //默认不展开
}
function Teacher(name="teacher") { //Teacher构建函数-导师
this.name = name;
this.studentTag = new Array(); //该数组存放学生标签
this.show = false; //默认不展开
}
类图:
算法解释:
之前我并未想到合适的算法来解决树的输出的问题,我一直认为树应该是动态的,能够随时添加删除节点,这样一来如果用html写的输出就把内容格式限死了,表的增改不灵活。也许html可以动态管理输出,但是我不会用。所以我当即确定了,输出应交给偏后端的js来处理,同时js输出的文字需要有带有css动态效果,要能接受鼠标点击触发属性值变化。
输出显示方案及原理:在js控制输出但是本质还是html在输出,所以js需要获取html的标签的id。只要通过document.getElementById('html').innerHTML
修改标签内的值就可以了。另外一个,在html内将文字绑定onclick函数非常的简单<a onclick="function()"></a>
即可,但是用document.getElementById('html').innerHTML=str;
的形式输出没问题,可是onclick我就怎么试都没反应,不能唤起相关的函数,最后查了very very very long 的time才找到解决方案,使用JSON.stringify()将对象转换成字符串的形式插入到.innerHTML中,使之成为某个函数值的参数。
function DisplayTable(arr) { //输出导师表 即树
var i = 0;
ptr_obj = arr; //ptr_obj是全局变量,指向当前状态的root
var StdOut_Front = "<a class ='normal' onclick='Click_teacher("; //特效在class里改,这里只会改到导师
var StdOut_Mid=") '>";
var StdOut_Back = "</a>";
var str="";
while (i < arr.length) {
//document.write(arr.name);
str += StdOut_Front + JSON.stringify(arr) + "," + i + StdOut_Mid + arr[i].name + StdOut_Back; //这样一来onclick里的函数就可以把arr当作参数
str += "<br>"; //输出换行 导师名独占一行
if (arr[i].show == true) {
str += DisplayTag(arr, i);
}
i++;
}
document.getElementById('html').innerHTML = str; //将html里内容改为str。或者说将str输出到html网页
本来我是想用root一个全局变量,所有函数对其进行增删改查,输出只用DisplayTable(root)就行,但是实际在调试的过程中发现,改操作死活都不能更改传进去对象的属性,然后点击操作改的只是形参里的值,原对象任凭风吹雨打,沉着安稳如山。网上求解,我想传对象引用改变原对象的值,结果网上都是一堆关于“如何让函数不改变对象里的值,传个对象进去结果发现数据被改了……”等等话题。我觉得是我对js语法掌握得不够彻底。但是急需一个解决方案,所以我就想,干脆用传进来的对象做输出算了。
function Click_teacher(a, i) { //鼠标点到了导师姓名就修改标签展开状态
a[i].show = !a[i].show;
ptr_obj = a; //全局变量指向root当前状态,需要实时更新
DisplayTable(a);
}
倒还真可以了,但是缺陷是非常的明显的,由于是递归式调用,参数为形参,每调用一次复制一份,永不返回,这样操作极耗内存,不推荐采用。其中ptr_obj的作用是,当前显示的root不再是全局的root,用全局的ptr_obj指向当前作为参数的root,即代码中的a,在进行插入操作时,需要将数据插入到显示的root这一层数据上。否则,插入的数据不可见。
递归式显示:改了之后输出改了的,输出后再等待被改
整体流程图:
重要代码:
在建树的时候,我觉得树的结构搭建是非常关键的,最为重要。可是当我做到输出的时候,才发现,用js来控制输出时html标签的插入处理难度高出天际,因为我实在不懂格式。可是最后,到了做输入处理的时候,这个处理量真是看了脑壳昏,写出来我也并不知道它为什么能正常运行,代码如下
function check_tch(str, i) { //在str【i】这里检查后面字符串内容是否为“导师:”
var j = 0;
var daoshi = "导师";
var sign1 = ":", sign2 = ":"; //圆角半角符号通吃
while (j < 2) {
if (str[i + j] != daoshi[j]) return false;
j++;
}
if (str[i + j] != sign1 && str[i + j] != sign2) return false;
return true;
}
function check_tag(str, i) { //在str【i】这里提取输入的字符串作为学生标签
if (str[i] == '\n')++i;
if (str[i] == undefined) return false;
var tagname = "";
while (str[i] != ":" && str[i] != ":" && str[i] != "," && str[i] != "," && str[i] != "、" && str[i] != "\n" && str[i] != undefined) { //中英文逗号、冒号,顿号,换行符,末尾,都是截断符
tagname += str[i++];
}
var tg = new Tag(tagname); //从输入中提取出的tagname,用来新建标签
if (str[i] == "\n" || str[i] == undefined) return tg;
++i;
var stname = "";
while (1) {
if (str[i] != ":" && str[i] != ":" && str[i] != "," && str[i] != "," && str[i] != "、" && str[i] != "\n" && str[i] != undefined) {
stname += str[i];
}
else {
var std = new Student(stname);
tg.list.push(std); //将学生名放入标签表中
stname = "";
}
if (str[i] == "\n"|| str[i] == undefined) break;
i++;
}
return tg; //返回建好的标签
}
function Get_input(a) { //鼠标点击确认后,将框内的文本读入到树中
var str = document.getElementById("inputbox").value;
document.getElementById("inputbox").value = ""; //获取文本框内容后清空
var i = 0;
var teachername="";
var line_break = '\n';
while (str[i] != undefined) {
if (check_tch(str, i)) { //找“导师:”
i += 3;
while (str[i] != line_break && str[i] != undefined) {
teachername += str[i];
i++;
}
var t = new Teacher(teachername);
teachername = ""; //找到导师名后新建导师对象
a.push(t); //放入树中
while (str[i] != undefined) {
var tg = check_tag(str, i);
if (tg != false) {
t.studentTag.push(tg); //再将导师后面的标签也放入该导师的student.Tag中
if (str[i] == line_break) i++;
while (str[i] != line_break && str[i] != undefined)++i;
}
i++;
}
}
i++;
}
DisplayTable(a);
}
首先从字符串里找到“导师:”这三个符号,那么后面就是导师姓名,再往下就是学生的标签,标签后面是学生名。整个字符串处理过程相当繁琐。
目录及使用说明
简单的目录
一张背景图 123.png
少许css式样 styleshee.css
以及页面主体 Tch-Stu_tree.html
操作说明
在网页的输入框内输入导师信息,标签信息,学生信息
点击左下角的完成即可生成相应的师门树
输入格式:
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四
导师姓名与学生标签可点击,点击效果为展开/收缩
鼠标在导师姓名,学生标签或者学生姓名上悬停,会触发css hover效果
举个例子
.stu {
font-size: 22px;
color:cyan;
}
.stu:hover {
font-size: 27px;
color:gold;
transition-duration: 600ms; //转换时间:600ms
}
这是学生姓名的显示效果,上面的.stu是正常状态下的字体像素为22px,颜色cyan偏青色。而.stu:hover则是鼠标在学生姓名上悬停的效果,字体变大为27px,颜色gold金黄色,变化时间600ms。
或者直接试试这段文字
签入记录
可能还会有更新
遇到的问题
遇到的问题不仅有,而且还挺多的。由于语言的不熟悉产生的问题,例如之前提到过的输出问题,怎样不让html把输出定死,用js,用了js又如何实现css效果,这些问题我们都是不了解的,只能从网上查找方案,还不一定能看懂。看不懂的代码就先拿去跑下试试结果!也是由于js语言的特性,动态编译运行,使得我们很快就能看到运行结果,大大减少了学习耗时。结对编程对于我们来说,确实也很大的不便,由于两个人很少聚到一起,少有机会讨论,要合作分工的话,也基本上以文件来分比较合适,分工不均是时有的事,我们处于结对初期,还需要时间去磨合。
评价你的队友
我觉得我的队友是一个性格强悍的女汉子,而实际上内心又很柔弱,但是表现得还真的挺强悍,额,咳咳……
值得学习的地方嘛,idea挺多的,开发经验比我多,善于代码重用,懂得使用框架,利用外部资源,善用工具作图等等等等。
需要改进的地方,唉,人的评价都是感性的,她对我的评价是我学习能力很强,我可能会觉得她的学习能力稍弱等等,一个人的能力是有限的,这些并不是需要改进的地方,也不是说想改进就能的,更多的,我觉得她有时候太专注于手中的事,而容易忽略身边更有意思的东西。所以我觉得她应该要学会观察,观察生活中的事务,抓住事物的核心点下手去做事,效率会更高。即使你懂得多,但是在找到完整思路之前,可以妄下结论,但不要轻易动手。唉,这些都是次要的,她要是能学会一点撒娇卖萌,就……
say something?
这次结对编程作业我收获还是蛮多的,从对前端有着错误的理解到不了解前端,再到前端入门,实际上只用了5天,这5天里,我和我的小伙伴都很忙,都没有什么时间来做这个作业,即便是今晚,我也要在团队编程作业上分出一点心思。每天睡得晚起得早,就像战争一样,精神高度紧张,我感觉到了时间的重要性,一天其实很短,5天也是,作业都是逼着自己赶出来的。这是一段痛苦而值得留恋的回忆,我大部分时间都在盯着网页刷资料,大脑飞速运转,只为解决这个难点,满足那个需求。但即使晚上想着问题难以入眠,脑细胞活跃的兴奋却在告诉我,我在成长,“加油,孩子”。面对困难,根本就没有什么“无法解决”,只是看你有没有这个精力,愿不愿意花精力而已。
博客从始至终,你都可以看到我说得眉色飞舞,但是我却没有贴出一张我做的页面是怎么样的图,我直白的说,成品没有我们想象的那么美好,简陋了点,如果要与同学们对比那我们更觉得自己做的不堪入目,可这同样是我们花了大量时间和精力去完成的一项作业。你要是问我,我觉得满意吗?我会说结果不太满意,因为我们还能做得更好,毕竟我们当时只有那么点精力,不过中间付出的辛勤劳动我是一定满意的。看了此次的评分标准,对美观度还是有较大的要求,那我觉得,我们分数又要往下压一压了,但正如某位伟人所说过的:“分数不是衡量收获的唯一标准”。我们没有用任何的框架,真正从零起步,我们收获了多少我们心里清楚,我对此感到满意。
逐字编写简陋的曲谱,也能唱响打动心灵的旋律。
想看看到底长啥样么?就酱