合作成员:
郭文茜(201421122005)代码仓库点击此处
兰天宇(201421122091)代码仓库点击此处

需求分析

  • 选择语言功能
  • 在生成题目后开始计时,并在提交题目后停止计时并统计正误数量

程序设计

选择语言

计时器


代码说明

HTML代码

<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<title>Mathematics</title>
<style type="text/css">
#sub {
display: block;
}
</style>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>

<body>
<div class="container">
<div class="form-group">
<label for="">Number of question</label>
<input class="form-control" type="number" id="ex_n" name="ex_n" />
</div>
<div class="form-group">
<label for="">Range of value</label>
<input class="form-control" type="number" id="ex_r" name="ex_r" />
</div>
<button id="confirm" class="btn btn-primary" type="button" onclick="subHandle()">Confirm</button>
<div id="right_num">Correct number:<span>0</span></div>
<div id="wrong_num">Wrong number:<span>0</span></div>
<div id="timer">Time:00:00:00</div>
<table id="exer" class="table table-striped">
<tr>
<th>Question</th>
<th>Answer</th>
<th>Correct/Wrong</th>
</tr>
</table>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
//js代码详见下方
</script>
</body>

</html>

JS代码

  • 计时器对象
var timer = {
//时分秒属性
sec: '0' + 0,
min: '0' + 0,
hou: '0' + 0,
//开始计时方法
startTimer: function() {
var timeShow = document.getElementById('timer');
this.sec = '0' + 0, this.min = '0' + 0, this.hou = '0' + 0;
this.sec = '0' + 1;
//定义全局定时触发器
setTimer = setInterval(function() {
timeShow.innerText = 'Time:' + this.hou + ':' + this.min + ':' + this.sec;

this.sec++;
//时分秒换算
if(this.sec == 60) {
this.sec = '0' + 0;
this.min++;
}
if(this.min == 60) {
this.min = '0' + 0;
this.hou++;
}
this.hou < 10 && this.hou.toString().length < 2 ? this.hou = '0' + this.hou : this.hou = this.hou;
this.min < 10 && this.min.toString().length < 2 ? this.min = '0' + this.min : this.min = this.min;
this.sec < 10 && this.sec.toString().length < 2 ? this.sec = '0' + this.sec : this.sec = this.sec;
}.bind(this), 1000);
},
//停止计时方法
stopTimer: function() {
clearInterval(setTimer);
}

}
  • 生成题目方法
function subHandle() {

document.querySelector('#exer').innerHTML = '<tr><th>Question</th><th>Answer</th><th>Correct/Wrong</th></tr>';
//保存题目数
var n = document.querySelector('#ex_n').value;
//保存范围数
var r = document.querySelector('#ex_r').value;
//存放四则运算符
var ope = ['+', '-', '/', '*'];
//判断用户输入信息是否符合要求
if(parseInt(n) == n && parseInt(r) == r && n <= 10000 && r > 0 && n > 0) {
document.getElementById('confirm').style.display = 'none';
var current_n = 0;
while(current_n < n) {
//随机生成运算符数量1~3
var ope_count = Math.round(Math.random() * 2) + 1;
//根据运算符数量随机某生成括号的位置
var bra_position = Math.round(Math.random() * ope_count);
//存放算式的数
var number = [];
//根据运算符数量生成相应数量的数字并存入数组中
for(var i = 0; i < ope_count + 1; i++) {
number.push(Math.ceil(Math.random() * r))
}
//根据运算符数量不同,生成算式,或者带括号的算式
if(ope_count == 1) {
var equ = number.shift() + ope[Math.round(Math.random() * 3)] + number.shift();
} else if(ope_count == 2) {
switch(bra_position) {
case 0:
var equ = number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift();
break;
case 1:
var equ = '(' + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ')' + ope[Math.round(Math.random() * 3)] + number.shift();
break;
case 2:
var equ = number.shift() + ope[Math.round(Math.random() * 3)] + '(' + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ')';
break
}

} else if(ope_count == 3) {
switch(bra_position) {
case 0:
var equ = number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift();
break;
case 1:
var equ = '(' + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ')' + ope[Math.round(Math.random() * 3)] + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift();
break;
case 2:
var equ = number.shift() + ope[Math.round(Math.random() * 3)] + '(' + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ')' + ope[Math.round(Math.random() * 3)] + number.shift();
break;
case 3:
var equ = number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ope[Math.round(Math.random() * 3)] + '(' + number.shift() + ope[Math.round(Math.random() * 3)] + number.shift() + ')';
break;
}

}
//将算式以及输入框等拼接插入标签中
var strHtml = '<tr class="exercise"><td>Question-' + (current_n + 1) + '.&nbsp;<label>' + equ + '</label>=</td><td><input class="form-control" style="width:100px" type="text"/></td><td><span class="res right" style="color:green; display:none;">Correct</span><span class="res wrong" style="color:red; display:none;">Wrong</span></td></tr>'
document.querySelector('#exer').innerHTML += strHtml;
current_n++;
}
document.querySelector('#exer').innerHTML += '<button id="sub" class="btn btn-success" type="button" onclick="checkHandle()">Submit</button>';
timer.startTimer();
} else {
alert('Please enter the question number and range of value correctly, the number of questions must be less than 10000, the range of value must be a natural number');
}
}
  • 提交答案函数
function checkHandle() {
document.getElementById('confirm').style.display = 'inline-block';
timer.stopTimer();
var exer = document.getElementsByClassName('exercise');
for(i in exer) {
if((typeof exer[i]) == 'object') {
//获取答题框内容
var ans = exer[i].getElementsByTagName('input')[0].value;
if(ans.indexOf('\'') != -1 && ans.indexOf('/') != -1) {
var arr = ans.split('\'');
var result = parseInt(arr[0]) + eval(arr[1]);
if(result == eval(exer[i].getElementsByTagName('label')[0].innerText)) {
rightFun(exer[i]);
} else {
wrongFun(exer[i]);
}

} else if(ans.indexOf('/') != -1) {
if(eval(ans) == eval(exer[i].getElementsByTagName('label')[0].innerText)) {
rightFun(exer[i]);
} else {
wrongFun(exer[i]);
}
} else {
if(ans == eval(exer[i].getElementsByTagName('label')[0].innerText)) {
rightFun(exer[i]);
} else {
wrongFun(exer[i]);
}
}
}
}
$('#right_num span').text($('span.right:visible').length);
$('#wrong_num span').text($('span.wrong:visible').length);
}
  • 正误行为函数
//正确行为函数
function rightFun(ele) {
ele.getElementsByClassName('right')[0].style.display = 'inline';
ele.getElementsByClassName('wrong')[0].style.display = 'none';
ele.style.borderColor = 'green';
}
//错误行为函数
function wrongFun(ele) {
ele.getElementsByClassName('right')[0].style.display = 'none';
ele.getElementsByClassName('wrong')[0].style.display = 'inline';
ele.style.borderColor = 'red';
}

运行测试

  • 选择语言

  • 生成题目

  • 提交答案


小结感受

两个人合作的效果从时间和质量上来说都远远超过一个人单独工作。并行工作使得任务完成时间缩短,分析和实现过程中,不断交换思路和想法可以有效的推进任务的进程,而且合作过程中可以互相取长补短,学习到很多自己没有掌握的东西,遇到困难也可以一起解决,让任务完成的过程变得更加顺利。


伙伴评价

兰天宇同学在这次编程作业完成过程中起到了团队领导的作用,提出实现思路和框架,并承担起了主要的编程任务,在完成过程中,对于我提出的问题和质疑也认真地进行了思考和回答,对于我在编程中出现的困难,也给予了足够的指导和帮助,是个不可多得的合作伙伴。


PSP

PSP2.1 Personal Software Process Stages Time Senior Student(min) Time(min)
Planning 计划 5 5
Estimate 估计这个任务需要多少时间 1 1
Development 开发 180 240
Analysis 需求分析 (包括学习新技术) 1 1
Design Spec 生成设计文档 2 1
Design Review 设计复审 5 2
Coding Standard 代码规范 1 1
Design 具体设计 10 15
Coding 具体编码 120 150
Code Review 代码复审 5 3
Test 测试(自我测试,修改代码,提交修改) 30 60
Reporting 报告 30 35
测试报告 20 25
计算工作量 5 5
并提出过程改进计划 5 5