结对项目-四则运算 “软件”之升级版
一.前提
(1)作业来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2213
(2)GitHub地址:https://github.com/GVictory/MakeOutQuestionsWithInterface
(3)调试环境:IntelliJ IDEA ,CHORME浏览器
二.作业要求
(1)基本要求
- 自动生成题目,单个题目最多不能超过4个运算符,操作数小于100。
- 用户可以输入答案
- 若用户输入答案正确,则提示正确;若答案错误,则提示错误,并要提示正确答案是多少。
(2)扩展要求
- 用户答题结束以后,程序可以显示用户答题所用的时间
- 用户可以选择出题的个数(最多不能超过5个题目),答题结束可以显示用户答错的题目个数和答对的题目个数
- 用户在第一次答题时,需要用户输入用户名,用户下次启动后,程序需要记住用户前一次输入的用户名
- 程序可以设置答题时间,时间设置为整数,单位为秒,最大不能超过120秒,若超过了答题时间未答题,则提示:时间已到,不能答题。
(3)结对成员
姓名:李志成 学号:201606110064 博客园地址:https://www.cnblogs.com/97lzc/
姓名:郭木凯 学号:201606110066 博客园地址:https://www.cnblogs.com/GMUK/
三.时间估算
结对项目软件过程耗时估计表与统计表
(时间单位:小时)
PSP2.1
|
个人软件实现阶段 |
预计时间 |
实际时间 |
||||||||||||||||||||||||||||||||||||||||||||||||
Planning |
计划 |
1 |
2 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Estimate |
估计这个任务需要多少时间 |
10 |
15 |
||||||||||||||||||||||||||||||||||||||||||||||||
Development |
开发 |
10 |
10 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Analysis |
需求分析 (包括学习新技术) |
1 |
1 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Design Spec |
生成设计文档 |
1 |
1 | ||||||||||||||||||||||||||||||||||||||||||||||||
· Design Review |
设计复审 |
0.5 |
0.5 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Coding Standard |
代码规范 |
1 |
1 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Design |
具体设计 |
1 |
1 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Coding |
具体编码 |
1 |
1 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Code Review |
代码复审 |
0.5 |
0.5 |
||||||||||||||||||||||||||||||||||||||||||||||||
· Test |
测试(自我测试,修改代码,提交修改) |
1 |
1 |
||||||||||||||||||||||||||||||||||||||||||||||||
Reporting |
报告 |
1 |
1 |
||||||||||||||||||||||||||||||||||||||||||||||||
· |
测试报告 |
1 |
1 |
||||||||||||||||||||||||||||||||||||||||||||||||
· |
计算工作量 |
2 |
2 |
||||||||||||||||||||||||||||||||||||||||||||||||
· |
并提出过程改进计划 |
2 |
2 |
四:工作详情
(一)工作:
李志成: 题目和答案生成,前台题目和答案的渲染。
郭木凯: 前台设计,换肤,计时。
(二) 部分功能代码介绍:
首先是前端页面的实现,通过html,css,JavaScript,jQuery,vue.js编写
1 <!DOCTYPE html> 2 <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>志成出题</title> 6 <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> 7 <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> 8 </head> 9 <body style="height: 100%;"> 10 <div style="display: flex;justify-content: center;align-content: center"> 11 <div id="boss" style="display:flex;width: 600px;height: 450px;border: 1px dashed gray; padding: 0px; color: rgb(0, 0, 255); line-height: 1.5 !important;">> 12 <div style="width: 100px;border-right: 1px solid #bbbbbb;height: 100%;display:flex;align-content: center;justify-content: center"> 13 <div style="font-size: 30px;width: 30px;margin-top: 20px">志成出题</div> 14 </div> 15 <div style="width: 100%;height: 100%;display: flex;flex-direction: column"> 16 <div style="width: 100%;height: 90px;display: flex;align-items: flex-end;flex-direction: row;align-items:center;justify-content: space-between"> 17 <div> 18 <div id="selectCount" 19 style="display: flex;flex-direction: column;align-items: center;margin-left: 20px"> 20 <select id="select" 21 style="height:28px; width:90px; line-height:28px; border:1px solid #9bc0dd; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; "> 22 <option value="1">1</option> 23 <option value="2">2</option> 24 <option value="3">3</option> 25 <option value="4">4</option> 26 <option value="5" selected>5</option> 27 </select> 28 <button id="countButton" onclick="getArithmetic()" 29 style="margin-top:10px;border:none;height: 30px;width:60px;color: white;border-radius: 15%;font-size: 9px"> 30 确定 31 </button> 32 </div> 33 </div> 34 <div> 35 <div style="display: flex;align-items: flex-start;width: 150px;margin-bottom: 5px"> 36 <span>所用时间:</span><span id="useTime">0</span><span>秒</span> 37 </div> 38 <div style="display: flex;align-items: flex-start;width: 150px;margin-top: 5px"> 39 <span>答题时间:</span><span>120秒</span> 40 </div> 41 </div> 42 43 </div> 44 <div id="test" 45 style="width: 100%;height: 270px;border-top: 1px solid #bbbbbb;border-bottom:1px solid #bbbbbb;display: flex;flex-direction: column;padding: 30px;box-sizing:border-box"> 46 <div id="body"> 47 <div style="margin-bottom: 10px;display: flex;" v-for="(ari,index) in arithmetic"> 48 <div style="width: 90px">{{ari.question}}</div> 49 <span> = </span> 50 <input v-bind:id="index" style="border:none;border-bottom: 1px solid #bbbbbb;width: 70px"/> 51 <i name="answers" style="margin-right: 25px;margin-left: 25px" v-bind:id="index+10">X</i> 52 <div name="answers"> 53 <span>正确答案:</span> 54 <span>{{ari.answer}}</span> 55 </div> 56 </div> 57 </div> 58 </div> 59 <div id="result" 60 style="width: 100%;height:85px;display: flex;flex-direction: row;justify-content: space-between;align-items: center;padding: 20px;box-sizing: border-box"> 61 <div> 62 <div id="text"> 63 <span>您答对了<span id="right">3</span>道题,答错了<span id="error">2</span>道题</span><br/> 64 <span>答题正确率为<span id="rate">60%</span></span> 65 </div> 66 </div> 67 <div style="display: flex;align-items: flex-end" id="commit"> 68 <button onclick="commitAnswer()" 69 style="border:none;height: 45px;width:100px;color: white;border-radius: 12px;font-size: 17px;margin-right: 5px"> 70 提交 71 </button> 72 <button id="skin" onclick="changeSkin()" 73 style="border:none;height: 30px;width:40px;color: white;border-radius: 15%;font-size: 9px"> 74 换肤 75 </button> 76 </div> 77 </div> 78 </div> 79 </div> 80 </div> 81 </body> 82 <script> 83 var questions = new Array(); 84 var vue; 85 var t; 86 87 function getArithmetic() { 88 var option = $("#select option:selected").text(); 89 $.ajax({ 90 type: 'GET', 91 url: "/hello?count=" + option, 92 success: function (data) { 93 var jsonData = JSON.stringify(data); 94 var obj = JSON.parse(jsonData); 95 array = obj; 96 for (var p in obj) {//遍历json对象的每个key/value对,p为key 97 var ob = {"question": p.toString(), "answer": obj[p]} 98 questions.push(ob); 99 } 100 vue = new Vue({ 101 el: '#test', 102 data: { 103 arithmetic: questions 104 } 105 }) 106 $("#body").show() 107 $("#selectCount").hide(); 108 $("#commit").show(); 109 $("#text").hide(); 110 $("[name='answers']").hide(); 111 var num = 0; 112 t = setInterval(function () { 113 num++; 114 $("#useTime").text(num) 115 if (num == 120) { 116 clearInterval(t); 117 alert("时间已到,答题结束") 118 commitAnswer(); 119 } 120 }, 1000); 121 122 } 123 }); 124 } 125 126 $(function () { 127 $("#body").hide(); 128 $("#commit").hide(); 129 $("#text").hide() 130 }) 131 132 function changeSkin() { 133 $("#boss").css("background-color", "#2b2b2b"); 134 $("#boss").addClass("changeSkin"); 135 } 136 137 function commitAnswer() { 138 var rightCount = 0; 139 var errorCount = 0; 140 for (var i in questions) { 141 $("#" + i).attr("disabled", "disabled"); 142 if (questions[i].answer == $("#" + i).val()) { 143 var num = parseInt(i) + 10; 144 $("#" + num.toString()).text("√"); 145 rightCount++; 146 } else { 147 errorCount++; 148 } 149 } 150 clearInterval(t); 151 $("[name='answers']").show(); 152 $("#commit").hide(); 153 $("#text").show(); 154 $("#right").text(rightCount); 155 $("#error").text(errorCount); 156 $("#rate").text((rightCount / (rightCount + errorCount) * 100) + "%") 157 } 158 </script> 159 <style> 160 .changeSkin { 161 color: #f5a528; 162 } 163 </style> 164 </html>
其次是后端控制器代码,如下:
1 public class testContraller { 2 @GetMapping("/getArithmetic")
3 public HashMap<String, Integer> getArithmetic(@RequestParam Integer count) throws JSONException {
4 return new Arithmetic().getArithmetic(count);
5 }
6 }
最后是解题函数(此处展示重要部分):
1 private static String getQuestion(Integer operatorNumber,Integer numberRange){
2 char[] operator = new char[]{'+', '-', '*', '/'}; 3 Random random = new Random(); 4 StringBuilder stringBuilder = new StringBuilder(); 5 for (int operatorIndex = 0; operatorIndex < operatorNumber; operatorIndex++) { 6 stringBuilder.append(random.nextInt(numberRange+1)); 7 stringBuilder.append(operator[random.nextInt(4)]); 8 } 9 stringBuilder.append(random.nextInt(numberRange+1)); 10 return stringBuilder.toString(); 11 } 12 13 private static Float getAnswer(String question){ 14 Stack<Character> operatorStack=new Stack<Character>(); 15 Stack<Float> numberStack=new Stack<Float>(); 16 char operatorTemp; 17 StringBuilder numberTemp=new StringBuilder(); 18 for (int questionIndex=0;questionIndex<question.length();questionIndex++){ 19 char singleChar=question.charAt(questionIndex); 20 if (Character.isDigit(singleChar)){ 21 numberTemp.append(singleChar); 22 }else { 23 if (!operatorStack.isEmpty()&&operatorStack.getTop()=='*'){ 24 operatorStack.pop(); 25 numberStack.push(numberStack.pop()*Float.valueOf(numberTemp.toString())); 26 }else if (!operatorStack.isEmpty()&&operatorStack.getTop()=='/'){ 27 operatorStack.pop(); 28 numberStack.push(numberStack.pop()/Float.valueOf(numberTemp.toString())); 29 }else if(!operatorStack.isEmpty()&&operatorStack.getTop()=='-'){ 30 numberStack.push(-Float.valueOf(numberTemp.toString())); 31 }else { 32 numberStack.push(Float.valueOf(numberTemp.toString())); 33 } 34 operatorStack.push(singleChar); 35 numberTemp.delete(0,numberTemp.length()); 36 } 37 } 38 if (!operatorStack.isEmpty()&&operatorStack.getTop()=='*'){ 39 numberStack.push(numberStack.pop()*Float.valueOf(numberTemp.toString())); 40 operatorStack.pop(); 41 }else if (!operatorStack.isEmpty()&&operatorStack.getTop()=='/'){ 42 numberStack.push(numberStack.pop()/Float.valueOf(numberTemp.toString())); 43 operatorStack.pop(); 44 }else if(!operatorStack.isEmpty()&&operatorStack.getTop()=='-'){ 45 numberStack.push(-Float.valueOf(numberTemp.toString())); 46 }else { 47 numberStack.push(Float.valueOf(numberTemp.toString())); 48 } 49 while (!operatorStack.isEmpty()){ 50 operatorStack.pop(); 51 numberStack.push(numberStack.pop()+numberStack.pop()); 52 } 53 return numberStack.pop(); 54 }
五.软件演示
一进来网页时,网页的模样如下图,主要由五大部分组成,分别是选题数,时间计时,题目,换肤,答题情况,一开始进来时由于题目数未选择,所以时间计时是静止的,题目部分不存在。
PS:题数只能选择1-5。
当选好题数并单击按钮时,选题数部分消失,时间开始计时,题目出现,并且用户可以输入题目的答案并提交。
其次网页还具有换肤功能,当点击换肤时,会改变文字和背景色。
当点击提交时,答题情况部分出现,时间静止,考试结束。
当超过时间时,弹出提醒,并且输入框此时无法输入,进行与提交一样的操作。
六:结对照片
七:收获与感悟
由于此前已有计算类的实现,所以该作业的难度在于页面的交互以及逻辑的处理,与队友一路做下来,发现所花的时间甚多,特别是调试和测试上,一改再改,与计划的时间相差甚远,至此有感,技术决定效率,效率决定未来。