小学四则运算web版
上次的作业是简单四则运算的java程序,这次来个惊险而又刺激的web版
项目要求
1.出题功能。每次出题时用户都可以在界面上定制如下参数:题目数量,算式数值范围(仅包括原始题目与最终结果的绝对值的数值范围),题目中最多有多少个运算符,题目中是否包含乘除法,题目中是否包含括号。在点击相应出题按钮后将生成题目文件(不包含答案)
2.做题功能。出题后,用户可以开始答题
3.判题功能。用户答题过程中或者全部完成后可以判断对错,并统计分数和时间。
目录
1.git地址
2.PSP
3.基本功能的实现
3.模块设计
4.模块对接
5.总结
git
https://github.com/tizi2756/MathProject.git
PSP
PSP | 任务内容 | 计划时间(min) | 完成时间(min) |
---|---|---|---|
planning | 计划 | 30 | 60 |
Estimate | 规划大致工作 | 30 | 60 |
Development | 开发 | 2400 | 4200 |
Design Review | 设计复审 | 120 | 180 |
Coding Standard | 代码规范 | 30 | 20 |
Coding | 编程 | 1200 | 3500 |
Code Review | 代码复审 | 120 | 720 |
Test | 测试 | 30 | 700 |
Reporting | 报告 | 60 | 360 |
基本功能
关于随机生成四则运算的功能,这次较上次有些改进,加入了括号
@Override
public List<Formula> formulas(int value1, int value2, int num, int limit, int flag1, int flag2, String Question[]){
List<Formula> formulaList=new ArrayList<Formula>();
int number[]=new int[100];
int n=0;
String question=null;
String poperator[]=new String[100];
for (int i=0;i<num;i++){
Formula formula=new Formula();
number[0]=Operation.make(value1,value2);
int count=0;
int m=Operation.make(2,limit+2);
// System.out.println(m);
for (int j=1;j<=m;j++){
count++;
if (flag1==1){
n=(int) (Math.random()*(4));
}
else if (flag1==0){
n=Math.random()>0.5?1:0;
}
switch (n){
case 0:
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
break;
case 1:
poperator[j]="-";
number[j+1]=Operation.make(value1,value2);
if(number[j]<number[j+1]){
int temp=number[j];
number[j]=number[j+1];
number[j+1]=temp;
}
break;
case 2:
if (poperator[j-1]=="*"||poperator[j-1]=="/"){
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
}
else {
poperator[j]="*";
number[j+1]=Operation.make(value1,value2);
}
break;
case 3:
if(poperator[j-1]=="*"||poperator[j-1]=="÷"){
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
}else{
poperator[j]="÷";
number[j+1]=Operation.make(value1,value2);
number[j]=number[j+1]*Operation.make(2,10);
if (number[j]>value2){
number[j]=number[j+1]*Operation.make(2,4);
}
}
break;
}
}
String question1=""+number[0];
poperator[1]="+";
for(int k=1;k<count;k++){
int rd=Math.random()>0.5?1:0;
if (flag2==0){
rd=0;
}
question1+=poperator[k]+number[k+1];
if (rd==1){
if (k<count-1)
question1="("+question1+")";
}
}
System.out.println("---"+question1);
int answer=Operation.solve(question1);
if(answer>=0){
question = question1 + "=";
}else{
String temp=Operation.makequestion(value1,value2,limit,flag1,flag2);
question=temp+"=";
answer=Operation.solve(temp);
}
System.out.println("-------"+answer);
formula.setSubject(question);
formula.setAnswer(answer);
formulaList.add(i,formula);
// formula=null;
Question[i]=question;
}
return formulaList;
}
这次并没有封装,因为要加入其他功能所以直接写到了service中
模块设计
对于后台
(1)计算模块有产生四则运算式子,计算答案,判断答案正确性等。
(2)由于使用了SpringMVC,所以只分为几个固定模块
方法类
package com.liu.entity;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Random;
import java.util.Stack;
public class Operation {
public static int make(int min,int max){
return new Random().nextInt(max-min)+min;
}
private static int first(char s){
switch (s){
case '+':
return 1;
case '-':
return 1;
case '*':
return 2;
case '÷':
return 2;
default:
return -1;
}
}
public static int solve(String question){
int ifsame = 0;
int answer = 0;
char[] q;
q=question.toCharArray();
int k=0;
//System.out.println(q);
Stack<Character> s=new Stack<Character>();
Stack<Integer> n=new Stack<Integer>();
for(int i=0;i<q.length;i++){
char temp=q[i];
if(q[i]=='0'&&!(Character.isDigit(q[i-1]))){//&&!(Character.isDigit(q[i+1]))
k = k*10 + Integer.parseInt(String.valueOf(0));
n.push(k);
}
if(Character.isDigit(q[i])||q[i]=='0'){//数字进栈
k = k*10 + Integer.parseInt(String.valueOf(q[i]));
if(i==q.length-1){
n.push(k);
//System.out.println(k+"pp");
k=0;
}
}else{
if(k!=0){
n.push(k);
//System.out.println(k+"oo");
k=0;
}
if(temp=='('){
s.push(temp);
}else if((temp == ')')){
while(s.peek()!='('){//左括号前出栈
int t=calculateSimple(String.valueOf(s.pop()), n.pop(), n.pop());
n.push(t);
}
s.pop();
}else if(temp == '+' || temp == '-' || temp == '*' || temp == 247 || temp == '(' || temp == ')' ){
if(s.isEmpty()){
s.push(temp);
//System.out.println(s.peek()+"++");
}else{
if(first(temp)<= first((s.peek()))){//优先级不大于栈顶 ,出栈后压入
//System.out.println(s.peek());
int t=calculateSimple(String.valueOf(s.pop()), n.pop(), n.pop());
//System.out.println(t+"kk");
//System.out.println(s.peek()+"dd");
n.push(t);
}
s.push(temp);
//System.out.println(s.peek()+"--");
}
}
}
}
if(k!=0){
n.push(k);
}
while(!s.empty()&&n.size()>=2){
int t=calculateSimple(String.valueOf(s.pop()), n.pop(), n.pop());
//System.out.println(t+"==");
n.push(t);
}//压入
//s.push('0');
//System.out.println(s.pop());
return n.pop();
// Stack var1 = new Stack();
// Stack var2 = new Stack();
// int var3 = (int)(Math.random() * 2.0D) + 2;
// int var4 = var0.length();
// int var5 = 0;
// int var6 = 0;
//
// for(int var7 = -1; var7 < var4 - 1; ++var7) {
// if (var0.charAt(var7 + 1) == '+' || var0.charAt(var7 + 1) == '-' || var0.charAt(var7 + 1) == '*' || var0.charAt(var7 + 1) == 247 || var0.charAt(var7 + 1) == '(' || var0.charAt(var7 + 1) == ')' || var7 == var4 - 2) {
// if (var7 == -1) {
// var2.push(var0.charAt(0));
// } else {
// if (var7 == var4 - 2) {
// var1.push(var0.substring(var5));
// break;
// }
//
// if (var5 <= var7) {
// var1.push(var0.substring(var5, var7 + 1));
// }
//
// if (!var2.empty() && var0.charAt(var7 + 1) != '(') {
// if ((Character)var2.peek() != '+' && (Character)var2.peek() != '-' || var0.charAt(var7 + 1) != '*' && var0.charAt(var7 + 1) != 247) {
// if ((Character)var2.peek() == '(') {
// var2.push(var0.charAt(var7 + 1));
// } else if (var0.charAt(var7 + 1) == ')') {
// var1.push(String.valueOf(var2.pop()));
// if (!var2.empty()) {
// var2.pop();
// }
// } else {
// if ((Character)var2.peek() == var0.charAt(var7 + 1)) {
// ++var6;
// }
//
// var1.push(String.valueOf(var2.pop()));
// var2.push(var0.charAt(var7 + 1));
// }
// } else {
// var2.push(var0.charAt(var7 + 1));
// }
// } else {
// var2.push(var0.charAt(var7 + 1));
// }
// }
//
// var5 = var7 + 2;
// }
// }
//
// if (var6 == var3 + 2) {
// ifsame = 1;
// }
//
// while(!var2.empty()) {
// var1.push(String.valueOf(var2.pop()));
// }
//
// String[] var12 = new String[20];
//
// int var8;
// for(var8 = 0; !var1.empty(); ++var8) {
// var12[var8] = (String)var1.pop();
// }
//
// --var8;
//
// for(; var8 >= 0; --var8) {
// if (!var12[var8].equals("+") && !var12[var8].equals("-") && !var12[var8].equals("*") && !var12[var8].equals("÷")) {
// var1.push(var12[var8]);
// } else {
// int var9 = 0;
// int var10 = 0;
// if (!var1.empty()) {
// var10 = Integer.parseInt((String)var1.pop());
// }
//
// if (!var1.empty()) {
// var9 = Integer.parseInt((String)var1.pop());
// }
//
// int var11 = calculateSimple(var12[var8], var9, var10);
// var1.push(String.valueOf(var11));
// }
// }
//
// if (Integer.parseInt((String)var1.peek()) < 0) {
// answer = 1;
// }
//
// if (ifsame != 1 && answer != 1) {
// return Integer.parseInt((String)var1.pop());
// } else {
// return Integer.parseInt((String)var1.pop());
// }
}
private static int calculateSimple(String operator, int a, int b) {
int result = 0;
switch (operator)
{
case "+":
result = a + b;
break;
case "-":
result = b - a;
break;
case "*":
result = a * b;
break;
case "÷":
if(a==0) break;
else{
result = b / a;
break;
}
}
return result;
}
public static void printfile(String[]QuestionSum,int Qnumber)throws IOException {
FileOutputStream fs = new FileOutputStream(new File("./results.txt"));
PrintStream p = new PrintStream(fs);
p.println("2017011838");
for(int i=0;i<Qnumber;i++){
p.println(QuestionSum[i]);
System.out.println(QuestionSum[i]);
}
p.close();
}
public static String makequestion(int value1, int value2, int limit, int flag1, int flag2){
int number[]=new int[100];
int n=0;
String poperator[]=new String[100];
number[0]=Operation.make(value1,value2);
int count=0;
int m=Operation.make(2,limit+2);
// System.out.println(m);
for (int j=1;j<=m;j++){
count++;
if (flag1==1){
n=(int) (Math.random()*(4));
}
else if (flag1==0){
n=Math.random()>0.5?1:0;
}
switch (n){
case 0:
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
break;
case 1:
poperator[j]="-";
number[j+1]=Operation.make(value1,value2);
if(number[j]<number[j+1]){
int temp=number[j];
number[j]=number[j+1];
number[j+1]=temp;
}
break;
case 2:
if (poperator[j-1]=="*"||poperator[j-1]=="/"){
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
}
else {
poperator[j]="*";
number[j+1]=Operation.make(value1,value2);
}
break;
case 3:
if(poperator[j-1]=="*"||poperator[j-1]=="÷"){
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
}else{
poperator[j]="÷";
number[j+1]=Operation.make(value1,value2);
number[j]=number[j+1]*Operation.make(2,4);
if (number[j]>value2){
number[j]=number[j+1]*Operation.make(2,4);
}
}
break;
}
}
String question1=""+number[0];
poperator[1]="+";
for(int k=1;k<count;k++){
int rd=Math.random()>0.5?1:0;
if (flag2==0){
rd=0;
}
question1+=poperator[k]+number[k+1];
if (rd==1){
if (k<count-1)
question1="("+question1+")";
}
}
return question1;
}
}
service
package com.liu.service;
import com.liu.entity.Operation;
import com.liu.mapper.projectMapper;
import com.liu.mode.Formula;
import com.liu.mode.Score;
import com.liu.mode.Student;
import com.liu.serviceI.OperationServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
@Service
public class OperationService implements OperationServiceI {
private AtomicLong generator = new AtomicLong();
@Autowired
private projectMapper projectMapper;
@Override
public List<Formula> formulas(int value1, int value2, int num, int limit, int flag1, int flag2, String Question[]){
List<Formula> formulaList=new ArrayList<Formula>();
int number[]=new int[100];
int n=0;
String question=null;
String poperator[]=new String[100];
for (int i=0;i<num;i++){
Formula formula=new Formula();
number[0]=Operation.make(value1,value2);
int count=0;
int m=Operation.make(2,limit+2);
// System.out.println(m);
for (int j=1;j<=m;j++){
count++;
if (flag1==1){
n=(int) (Math.random()*(4));
}
else if (flag1==0){
n=Math.random()>0.5?1:0;
}
switch (n){
case 0:
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
break;
case 1:
poperator[j]="-";
number[j+1]=Operation.make(value1,value2);
if(number[j]<number[j+1]){
int temp=number[j];
number[j]=number[j+1];
number[j+1]=temp;
}
break;
case 2:
if (poperator[j-1]=="*"||poperator[j-1]=="/"){
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
}
else {
poperator[j]="*";
number[j+1]=Operation.make(value1,value2);
}
break;
case 3:
if(poperator[j-1]=="*"||poperator[j-1]=="÷"){
poperator[j]="+";
number[j+1]=Operation.make(value1,value2);
}else{
poperator[j]="÷";
number[j+1]=Operation.make(value1,value2);
number[j]=number[j+1]*Operation.make(2,10);
if (number[j]>value2){
number[j]=number[j+1]*Operation.make(2,4);
}
}
break;
}
}
String question1=""+number[0];
poperator[1]="+";
for(int k=1;k<count;k++){
int rd=Math.random()>0.5?1:0;
if (flag2==0){
rd=0;
}
question1+=poperator[k]+number[k+1];
if (rd==1){
if (k<count-1)
question1="("+question1+")";
}
}
System.out.println("---"+question1);
int answer=Operation.solve(question1);
if(answer>=0){
question = question1 + "=";
}else{
String temp=Operation.makequestion(value1,value2,limit,flag1,flag2);
question=temp+"=";
answer=Operation.solve(temp);
}
System.out.println("-------"+answer);
formula.setSubject(question);
formula.setAnswer(answer);
formulaList.add(i,formula);
// formula=null;
Question[i]=question;
}
return formulaList;
}
@Transactional
@Override
public int insertStudent(Student student){
if(student.getUsername().equals("")){
throw new RuntimeException("name is null");
}
return projectMapper.insertStudent(student);
}
@Override
public boolean login(String username, String password){
System.out.println("11111");
Student student=projectMapper.nameselect(username);
// System.out.println("2222");
System.out.println(student);
if (student!=null){
if (student.getUsername().equals(username) && student.getPassword().equals(password)){
System.out.println("3333");
return true;
}
}
return false;
}
@Override
public int insertScore(Score score){
return projectMapper.insertScore(score);
}
}
controller:
package com.liu.controller;
import com.liu.entity.Operation;
import com.liu.mapper.projectMapper;
import com.liu.mode.Formula;
import com.liu.mode.Score;
import com.liu.mode.Student;
import com.liu.serviceI.OperationServiceI;
import org.apache.commons.logging.Log;
import org.apache.ibatis.annotations.Param;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;
@Controller
@RequestMapping("")
public class cController {
private static final Log logger = LogFactory.getLog(cController.class);
@Autowired
private OperationServiceI operationServiceI;
@Autowired
private projectMapper projectMapper;
/**
* @param value1s
* @param value2s
* @param amounts
* @param limits
* @param flag1s
* @param flag2s*/
@RequestMapping(value = "/operationAll")
public String All(Model model, HttpSession session, String value1s, String value2s, String amounts, String limits, String flag1s, String flag2s){
String[] var=new String[1000];
int flag1;
int flag2;
int value1= Integer.parseInt(value1s);
// System.out.println(value1);
int value2=Integer.parseInt(value2s);
if (value1>value2){
int temp=value1;
value1=value2;
value2=temp;
}
// System.out.println(value2);
int num=Integer.parseInt(amounts);
// System.out.println(num);
int limit=Integer.parseInt(limits);
// System.out.println(limit);
if (flag1s==null||flag1s.equals("")||flag1s.equals("null")){
flag1=0;
}
else
flag1=Integer.parseInt(flag1s);
// System.out.println(flag1);
if (flag2s==null||flag2s.equals("")||flag2s.equals("null")){
flag2=0;
}
else
flag2=Integer.parseInt(flag2s);
// System.out.println(flag2);
long start=System.currentTimeMillis();
List<Formula> formulas=operationServiceI.formulas(value1,value2,num,limit,flag1,flag2,var);
try {
Operation.printfile(var, num);
} catch (Exception var4) {
System.out.println("wrong");
}
session.setAttribute("for",formulas);
session.setAttribute("num",num);
session.setAttribute("start",start);
model.addAttribute("c",formulas);
return "exercise";
}
@RequestMapping(value = "/Result")
public String Result(HttpServletRequest request,HttpSession session,Model model){
int m=0;
int score=0;
long end=System.currentTimeMillis();
long start= (long) session.getAttribute("start");
long time=(end-start)/1000;
long Seconds=time%60;
long Minutes=(time/60)%60;
double num= (Integer) session.getAttribute("num") * 1.0;
int id= (int) session.getAttribute("id");
String[] result=request.getParameterValues("result");
Score score1=new Score();
List<Formula> formulas=(List)session.getAttribute("for");
for (int i=0;i<num;i++){
if (Integer.parseInt(result[i])==formulas.get(i).getAnswer()){
formulas.get(i).setJudge("正确!");
formulas.get(i).setResult(Integer.parseInt(result[i]));
m++;
}
else {
formulas.get(i).setJudge("错误!");
formulas.get(i).setResult(Integer.parseInt(result[i]));
}
}
score= (int) ((m/num)*100);
request.setAttribute("score",score);
request.setAttribute("se",Seconds);
request.setAttribute("mi",Minutes);
session.setAttribute("for",formulas);
model.addAttribute("a",formulas);
score1.setId(id);
score1.setScore(score);
score1.setNumber((int) num);
operationServiceI.insertScore(score1);
return "answerPage";
}
/**
* @param username
* @param password
* @param phone
*/
@RequestMapping(value = "/studentAdd")
public String StudentAdd(String username,String password,String phone,HttpServletRequest request){
Student student=new Student();
try{
student.setUsername(username);
student.setPassword(password);
student.setPhone(phone);
if (operationServiceI.insertStudent(student)>0){
request.setAttribute("message", "添加成功");
Student student2=projectMapper.nameselect(username);
projectMapper.insertScoreId(student2);
System.out.println("22222");
}
else {
request.setAttribute("message", "添加失败");
System.out.println("3333");
}
}catch (Exception e){
e.printStackTrace();
}
return "Addsuccess";
}
/**
* @param username
* @param password
*/
@RequestMapping(value = "/Login")
public String Login(String username,String password,HttpSession session){
System.out.println(username);
boolean bl=operationServiceI.login(username,password);
if (bl) {
Student student=projectMapper.nameselect(username);
session.setAttribute("id",student.getId());
return "userchoice";
} else {
return "Loginfalse";
}
}
}
由于加入了登录注册功能,学生成绩也可以加入数据库
所以奉上mybatis的映射文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liu.mapper.projectMapper">
<insert id="insertStudent" parameterType="com.liu.mode.Student">
insert INTO student(username,password,phone) VALUES (#{username},#{password},#{phone})
</insert>
<insert id="insertScoreId" parameterType="com.liu.mode.Student">
insert into score(id) values (#{id})
</insert>
<select id="nameselect" parameterType="String" resultType="com.liu.mode.Student">
select * from student where username=#{username}
</select>
<!--<select id="getCivilian" parameterType="int" resultType="com.liu.model.Civilian">-->
<!--select * from people where id=#{id}-->
<!--</select>-->
<!--<update id="update" parameterType="com.liu.model.Civilian">-->
<!--update people set name=#{name},password=#{password} where id=#{id}-->
<!--</update>-->
<insert id="insertScore" parameterType="com.liu.mode.Score">
insert INTO score(id,score,number) VALUES (#{id},#{score},#{number})
</insert>
</mapper>
对于前台
前台的设计主要由div+css布局实现
实现功能有登录注册,限定题目规则,答题等功能
注意!这里实现了计时器的功能,只有点击开始做题,开始计时后才可做题
来看看js代码
同时还有判空功能
模块对接
另一名成员规划出页面的模块布局之后,添加jsp代码,将需要的数据传到页面中
需要的数据主要为:
1.题目 为一个list集合
2.题目的数量 为list对象的size
3.正确答案被set到了实体类的answer中
实现为:
使用了循环输出,jstl标签,以及基本的jsp代码
总结
一开始觉得这个项目还是蛮简单的,但是架不住时间不够,本身能想到很多附加功能,但是越往后就越觉得时间不够。而且,大致完成后总会发现一些意想不到的bug。有些功能我想了很久,比如计算做题时间,总想着获取前台的计时器,但其实可以通过后台获取当前时间来计算。再有就是我对于项目的整体规划不到位,总是在不断地添加实体类。