一、结对项目成员
本次项目成员 | 学号 | github仓库 |
---|---|---|
邓丹丹 | 3219005354 | https://github.com/dxadd/dxadd/tree/main/ForCalculate-master |
陈静蓓 | 3219005353 | https://github.com/bubble-blase/forcalculate |
二、作业要求
作业所属课程 | 网络工程3班 |
---|---|
作业要求在哪里 | 作业要求 |
作业目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
三、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 45 |
Estimate | 估计这个任务需要多少时间 | 5 | 5 |
Development | 开发 | 200 | 380 |
Analysis | 需求分析 (包括学习新技术) | 20 | 20 |
Design Spec | 生成设计文档 | 10 | 10 |
Design Review | 设计复审 | 5 | 5 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 30 |
Design | 具体设计 | 20 | 30 |
Coding | 具体编码 | 250 | 280 |
Code Review | 代码复审 | 30 | 20 |
Reporting | 报告 | 10 | 10 |
Test Repor | 测试报告 | 20 | 30 |
Size Measurement | 计算工作量 | 20 | 25 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 15 | 20 |
Total | 合计 | 655 | 910 |
效能分析
这就是项目启动过程中cpu,内存等各个方面的性能指标。
设计过程
1、设计思路
考虑到分数的实现,因为java不存在可以处理分数运算的类,所以应将整数与分数作为一个对象来处理,即整数就是分母为1的分数。也因此做了实体类Fraction
受到Fraction启发,做了实体类OperationExpression,它的属性包含了表达式及其答案
题目生成设计思路:
于是就可以实例化一个OperationExpression对象e,运用getExpression类的getExp方法生成一个表达式设置为e的表达式,getExp()方法中调用了CalculateService的calculate()计算方法得到答案设置为e的答案。calculate()方法中产生了负数则会返回空值,可根据这个空值判断表达式是否存在负数,若存在则丢弃重新生成。其后,还会经过DuplicateCheck类的查重。通过上述步骤,即可生成一道题目。
2、设计的流程图
生成题目流程图
算术表达式中序变后序流程图
3、设计项目结构
实体类:分数类Fraction,算术表达式类OperationExpression
工具类:查重类DuplicateCheck
服务类:计算类CalculateService,答案判错类CheckService,表达式生成类getExpression
项目入口:OperationPro
关键代码说明
测试代码
点击查看代码
![](https://www.icode9.com/i/l/?n=20&i=blog/2531492/202110/2531492-20211026002042583-786735412.png)
import bean.Fraction;
import bean.OperationExpression;
import org.junit.Test;
import java.util.List;
public class test {
@Test
public void test1(){
OperationPro.mainGenerate(10,10000);
}
@Test
public void test2(){
OperationPro.mainCheck("D:\\abc\\ForCalculate\\Answer1.txt","D:\\abc\\ForCalculate\\Answer.txt");
}
@Test
public void test3(){
getExpression getExpression = new getExpression();
List exp = getExpression.getExp(new OperationExpression(null, null, null), 10);
System.out.println(exp);
}
@Test
public void test4(){
getExpression getExpression = new getExpression();
List exp = getExpression.getExp(new OperationExpression(null, null, null), 3);
System.out.println(exp);
}
@Test
public void test5(){
Fraction a = new Fraction(true,10);
Fraction b = new Fraction(true,10);
System.out.println(a.sub(b));
}
@Test
public void test6(){
Fraction a = new Fraction(false,20);
Fraction b = new Fraction(true,10);
System.out.println(a.div(b));
}
@Test
public void test7(){
Fraction a = new Fraction(false,10);
Fraction b = new Fraction(false,10);
System.out.println(a.add(b));
}
@Test
public void test8(){
Fraction a = new Fraction(false,10);
Fraction b = new Fraction(false,10);
System.out.println(a.sub(b));
}
@Test
public void test9(){
System.out.println(CalculateService.prior("+", "-"));
}
@Test
public void test10(){
getExpression getExpression = new getExpression();
List exp = getExpression.getExp(new OperationExpression(null, null, null), 3);
System.out.println(CalculateService.toPostFix(exp));
}
}
点击查看代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import bean.Fraction;
import bean.OperationExpression;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class getExpression {
private static Random r = new Random();
static List l = new ArrayList();
public getExpression() {
}
public List getExp(OperationExpression e, int limit) {
Fraction f1 = new Fraction(r.nextBoolean(), limit);
List stringList = new ArrayList();
List l = new ArrayList();
l.add(f1);
stringList.add(f1.toString());
int a = r.nextInt(3);
do {
express(e, l, stringList, limit);
--a;
} while(a >= 0);
Fraction f = CalculateService.calculate(l);
if (f == null) {
return null;
} else {
e.setRes(f);
e.setStringList(stringList);
return stringList;
}
}
static void express(OperationExpression e, List l, List stringList, int limit) {
Fraction f = new Fraction(r.nextBoolean(), limit);
int a = r.nextInt(4);
switch(a) {
case 0:
l.add("+");
l.add(f);
stringList.add("+");
stringList.add(f.toString());
break;
case 1:
l.add("-");
l.add(f);
stringList.add("-");
stringList.add(f.toString());
break;
case 2:
l.add("×");
l.add(f);
stringList.add("×");
stringList.add(f.toString());
break;
case 3:
l.add("÷");
l.add(f);
stringList.add("÷");
stringList.add(f.toString());
break;
default:
System.out.println("出错");
}
e.setList(l);
}
}
点击查看代码
import bean.Fraction;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
public class CalculateService {
public CalculateService() {
}
public static Stack toPostFix(List list) {
Stack number = new Stack();
Stack<String> action = new Stack();
int symble = false;
Iterator var4 = list.iterator();
while(true) {
String temp;
while(var4.hasNext()) {
Object o = var4.next();
int symble = flag(o, number, action);
switch(symble) {
case 1:
number.push(o);
break;
case 2:
action.push((String)o);
break;
case 3:
action.push((String)o);
break;
case 4:
while(!action.empty() && action.peek() != "(" && !prior((String)o, (String)action.peek())) {
number.push(action.pop());
}
action.push((String)o);
break;
case 5:
action.push((String)o);
break;
case 6:
while(!action.isEmpty()) {
temp = (String)action.pop();
if (temp.equals("(")) {
break;
}
number.push(temp);
}
}
}
Stack temp = new Stack();
Iterator var9 = action.iterator();
while(var9.hasNext()) {
temp = (String)var9.next();
number.push(temp);
}
var9 = number.iterator();
while(var9.hasNext()) {
Object o = var9.next();
temp.push(o);
}
return temp;
}
}
public static int flag(Object o, Stack number, Stack<String> action) {
if (o instanceof Fraction) {
return 1;
} else {
String s = (String)o;
if (s.matches("(\\+)|(\\-)|(\\×)|(\\÷)")) {
if (action.isEmpty()) {
return 2;
} else {
return prior(s, (String)action.peek()) ? 3 : 4;
}
} else if (s.matches("\\(")) {
return 5;
} else {
return s.matches("\\)") ? 6 : 0;
}
}
}
public static Boolean prior(String s1, String s2) {
if (s2.matches("\\(")) {
return true;
} else {
return s1.matches("(\\×)|(\\÷)") && s2.matches("(\\+)|(\\-)") ? true : false;
}
}
public static Fraction calculate(List list) {
Stack stack = toPostFix(list);
Stack<Fraction> newStack = new Stack();
Iterator var3 = stack.iterator();
while(true) {
if (var3.hasNext()) {
Object o = var3.next();
if (o instanceof Fraction) {
newStack.push((Fraction)o);
continue;
}
if (newStack.size() >= 2) {
Fraction a = (Fraction)newStack.pop();
Fraction b = (Fraction)newStack.pop();
String var7 = (String)o;
byte var8 = -1;
switch(var7.hashCode()) {
case 43:
if (var7.equals("+")) {
var8 = 0;
}
break;
case 45:
if (var7.equals("-")) {
var8 = 1;
}
break;
case 215:
if (var7.equals("×")) {
var8 = 2;
}
break;
case 247:
if (var7.equals("÷")) {
var8 = 3;
}
}
switch(var8) {
case 0:
newStack.push(b.add(a));
continue;
case 1:
Fraction fraction = b.sub(a);
if (fraction.getNominator() > 0 && fraction.getDenominator() > 0) {
newStack.push(fraction);
continue;
}
return null;
case 2:
newStack.push(b.muti(a));
continue;
case 3:
newStack.push(b.div(a));
default:
continue;
}
}
}
return (Fraction)newStack.pop();
}
}
}
3.查重类DuplicateCheck
点击查看代码
package utils;
import java.util.Iterator;
import java.util.List;
public class DuplicateCheck {
public DuplicateCheck() {
}
public boolean DuCheck(List l, List allList) {
Iterator it = allList.iterator();
List L;
do {
if (!it.hasNext()) {
return false;
}
L = (List)it.next();
} while(!this.CheckList(l, L));
return true;
}
boolean CheckList(List l1, List l2) {
if (l1 == l2) {
return true;
} else if (l1 == null && l2 == null) {
return true;
} else if (l1 != null && l2 != null) {
if (l1.size() != l2.size()) {
return false;
} else {
return l1.containsAll(l2) && l2.containsAll(l1);
}
} else {
return false;
}
}
}
4.答案判错类CheckService
点击查看代码
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
public class CheckService {
public CheckService() {
}
public static Map<String, String> Check(String checked, String answer) throws IOException {
Map<String, String> m = new HashMap();
String error = "";
String correct = "";
int errornum = 0;
int correctnum = 0;
String str1 = "";
String str2 = "";
File checkedfile = new File(checked);
FileInputStream input1 = new FileInputStream(checkedfile);
BufferedReader reader1 = new BufferedReader(new InputStreamReader(input1));
File answerfile = new File(answer);
FileInputStream input2 = new FileInputStream(answerfile);
BufferedReader reader2 = new BufferedReader(new InputStreamReader(input2));
while((str1 = reader1.readLine()) != null && (str2 = reader2.readLine()) != null) {
String[] str;
if (!str1.trim().equals(str2.trim())) {
str = str1.split("\\.");
error = error + str[0] + ",";
++errornum;
} else {
str = str1.split("\\.");
correct = correct + str[0] + ",";
++correctnum;
}
}
if (error.equals("")) {
error = "Wrong: " + errornum + "";
} else {
error = "Wrong: " + errornum + "(" + error.substring(0, error.length() - 1) + ")";
}
if (correct.equals("")) {
correct = "Correct: " + correctnum + "";
} else {
correct = "Correct: " + correctnum + "(" + correct.substring(0, correct.length() - 1) + ")";
}
m.put("wrong", error);
m.put("correct", correct);
return m;
}
}
运行结果
项目小结
在这一次的协同合作项目交流中,一开始我们就各自做自己的,没有交流,等我们汇总的时候才发现又很多问题。交流过后,我们不断磨合,不断测试代码,思考代码可行性,最后就在对方身上学到了很多东西。我们在设计过程中,取长补短,发挥各自的优势,一个人主要负责代码方面的问题,另一个负责测试相关的数据,总体合作下来感受到了团队合作的重要性,也因为后期的合作才能最终完成项目。