合作成员:
郭文茜(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) + '. <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 |