0 小组成员
韩华颂 2016282110142
吴政楠 2017282110286
1 项目Github地址
https://github.com/songofjoy/softwareProject
2 预估耗时
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 10 |
· Estimate | · 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 1140 | 1360 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 80 |
· Design Spec | · 生成设计文档 | 60 | 80 |
· Design Review | · 设计复审 (和同事审核设计文档) | 30 | 40 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 40 |
· Design | · 具体设计 | 60 | 70 |
· Coding | · 具体编码 | 600 | 700 |
· Code Review | · 代码复审 | 180 | 200 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 150 |
Reporting | 报告 | 180 | 150 |
· Test Report | · 测试报告 | 150 | 120 |
· Size Measurement | · 计算工作量 | 10 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 1330 | 1520 |
3 解题思路
3.1 前期准备
在上一次作业中,我们已经生成了一个简单的算式生成器,但是其中还有括号的功能没有实现。基础代码选取了我们两人中性能较高的一个,本次项目不仅要实现GUI,还要在之前的基础上实现括号。
3.2 后端
以上次的作业为基础,继续对上次的作业进行更一步的开发——添加括号。
3.3 前端
通过利用windowbuilder插件,可以将GUI展现给用户。
3.4 分歧解决
在最开始设计时,我们对GUI的呈现方式产生了分歧:
1、以计算器的形式展现
2、以网页的方式展现
后来经过讨论,从时间角度和熟练程度考虑选取了以计算器的方式展示。
4 设计实现过程
4.1 获取题目
textField.setText(Equation.createEquation().toString());
其中Equation是一个随机生成算式的函数
4.2 保存统计数据
public static void saveScore(Score score) throws IOException, ParseException { FileWriter writer = new FileWriter(FILENAME); writer.write(score.getRightAmount() + SPLITSTRING); writer.write(score.getWrongAmount() + SPLITSTRING); writer.write(score.getRadioAmount() + SPLITSTRING); writer.close(); }
4.3 读取统计数据
public static Score readScore() throws IOException, ParseException { Score score=new Score(); BufferedReader reader = new BufferedReader(new FileReader(FILENAME)); String line = reader.readLine(); String []infos=line.split(SPLITSTRING); score.setRightAmount(Integer.valueOf(infos[0])); score.setWrongAmount(Integer.valueOf(infos[1])); score.setRadioAmount(Double.valueOf(infos[2])); return score; }
4.4 计时器
对计时器进行的初始化设置
static int timer=0; static long starttimer=0; DecimalFormat df= new DecimalFormat("######0.0");
4.5 多语言支持
static final String EN="resource_english"; static final String CH="resource_zh_CN_1"; static final String HARD="resource_hard";
5 代码说明
5.1显示当前数据
将当前的正确题目数、错误题目数以及正确率记录在dat文件中,每次答题完成后点击下一题都会读取文件显示当前的答题数据并切换到下一题。
public void actionPerformed(ActionEvent e) { String[] strings=textField.getText().split("="); DoubleStack testStack = new DoubleStack(strings[0]); testStack.analysisString(); String right=testStack.compute(); if(strings.length>1&&strings[1].equals(right)){ textField1.setText("正确!"); curScore.setRightAmount(curScore.getRightAmount()+1); System.out.println(curScore.getRightAmount()); System.out.println(curScore.getWrongAmount()); curScore.setRadioAmount((double)curScore.getRightAmount()/(double)(curScore.getRightAmount()+curScore.getWrongAmount())); System.out.println(curScore.getRadioAmount()); lblNewLabel_1.setText(String.valueOf(curScore.getRightAmount())); label_2.setText(String.valueOf(curScore.getWrongAmount())); label_3.setText(String.valueOf(df.format(curScore.getRadioAmount()*100))+"%"); try { Util.saveScore(curScore); } catch (IOException | ParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } else{ textField1.setText("错误!正确答案为"+right); curScore.setWrongAmount(curScore.getWrongAmount()+1); curScore.setRadioAmount((double)curScore.getRightAmount()/(double)(curScore.getRightAmount()+curScore.getWrongAmount())); lblNewLabel_1.setText(String.valueOf(curScore.getRightAmount())); label_2.setText(String.valueOf(curScore.getWrongAmount())); label_3.setText(String.valueOf(df.format(curScore.getRadioAmount()*100))+"%"); try { Util.saveScore(curScore); } catch (IOException | ParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } textField.setText(Equation.createEquation().toString()); } });
5.2计时器
第一次点击按钮时开始计时,第二次点击按钮停止计时,第三次点击按钮重置。时间以秒计。
public void actionPerformed(ActionEvent e) { curScore=new Score(); lblNewLabel_1.setText("0"); label_2.setText("0"); label_3.setText("0.0%"); try { Util.saveScore(curScore); } catch (IOException | ParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } });
5.3多语言支持
通过获取properties文件中的内容,将字体以对应的形式显示出来。
public static void changeCharacter(String resource){ ResourceBundle rb = ResourceBundle.getBundle(resource); lblNewLabel.setText(rb.getString("rightAmount")); label.setText(rb.getString("wrongAmount")); label_1.setText(rb.getString("radioAmount")); button_20.setText(rb.getString("reset")); button_19.setText(rb.getString("clear")); button_18.setText(rb.getString("back")); button_23.setText(rb.getString("simply")); button_21.setText(rb.getString("hard")); button_22.setText(rb.getString("english")); button_24.setText(rb.getString("timer")); button_9.setText(rb.getString("next")); }
英文 繁体中文 简体中文
6 测试运行
其中重置功能可以将答题数据(正确题目、错误题目、正确率)重置设为0,清除可将已写的答案清空,退格可删除上一个输入的数据。第二行显示的上一道题的正确与否。
在添加了括号功能后对其进行的单元测试均通过。
7 合作情况
7.1 吴政楠
这是我第一次以结对的方式完成一次编程。
在后端的实现过程中我扮演了领航员的角色。我从我的搭档那里学到了很多东西,他在Java方面有很多项目经验,很多我之前没有想明白或者解决不了的问题在我们的讨论中常常能迎刃而解。而我在之前没有实现的括号的功能也得以实现。
而在前端的设计中我扮演了驾驶员的角色。虽然之前在对GUI的呈现方式方面有所分歧,但是在确定了方案后我们便迅速投入了工作。我做事一向拖拉,但是在我搭档的带领下,我们在很短的时间内就搭建出了一个基本的框架。在之后的几次讨论中,我们调整了其中设计不合理的部分,并对一些细节问题进行了完善。
7.2 韩华颂
感觉通过结对编程的模式合作还是挺好的,遇到一些问题都会相互请教,而且可以让我们每一个人都可以从另一个视角去考虑问题。
在后端的编写过程中,我作为驾驶员与我的搭档一起编码。之前我计算表达式的的时候一直想不到特别好的算法,自从跟我的搭档交流之后才知道了通过逆波兰的方法来求解会很简单,省了我不少的时间。后来我的小伙伴还增加了测试的模块,调试的时候变的更容易了。
我在前端设计时担任了领航员,因为之前用过windowsBuilder来编写GUI界面,写起来节约了不少时间,我的搭档还把界面做了一些优化,使用户使用起来更加方便。
8 项目小结
8.1 吴政楠
在这个项目中,我充分感受到了1+1>2的编程体验。我的Java基础并不好,这次的合作给我在编程过程中提供了很多新的思路,同时也恶补了之前很多遗忘掉的基础知识。
同时,在这次合作中,我明白了编程并不是一个人埋头苦干就一定能干好的,有一个能随时提出意见并给出指导的搭档可以很大的提高编程的效率。合作中遇到的分歧我们也会理性的分析,并得出一个最优的方案。
这次的合作使我受益匪浅,不仅让我看到了自己身上很多的不足,同时也给我了一种全新的编程体验。我也很期待和我的搭档的下一次的合作。
8.2 韩华颂
这个项目提高了自己的编程能力,和与伙伴的合作协调能力。
在开发的过程中,因为windowsBuilder插件是自动生成GUI代码的,所以代码格式很不好,也没有注释,不能很容易的让人理解,以后使用一些自动生成代码的插件后一定要记住去整理代码的结构。
通过结对编程,我们优势互补,大大提高了工作效率,并且彼此相互学到了一些新知识,这门高级软件工程课还是挺有收获的,以后一定会好好去学习这门课。
9 结对照片