一、结对项目成员
本次项目成员 | 学号 | 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,内存等各个方面的性能指标。
考虑到分数的实现,因为java不存在可以处理分数运算的类,所以应将整数与分数作为一个对象来处理,即整数就是分母为1的分数。也因此做了实体类Fraction
受到Fraction启发,做了实体类OperationExpression,它的属性包含了表达式及其答案
题目生成设计思路:
于是就可以实例化一个OperationExpression对象e,运用getExpression类的getExp方法生成一个表达式设置为e的表达式,getExp()方法中调用了CalculateService的calculate()计算方法得到答案设置为e的答案。calculate()方法中产生了负数则会返回空值,可根据这个空值判断表达式是否存在负数,若存在则丢弃重新生成。其后,还会经过DuplicateCheck类的查重。通过上述步骤,即可生成一道题目。
生成题目流程图
算术表达式中序变后序流程图
实体类:分数类Fraction,算术表达式类OperationExpression
工具类:查重类DuplicateCheck
服务类:计算类CalculateService,答案判错类CheckService,表达式生成类getExpression
项目入口:OperationPro
测试代码
![](https://www.www.zyiz.net/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; } }
运行结果
在这一次的协同合作项目交流中,一开始我们就各自做自己的,没有交流,等我们汇总的时候才发现又很多问题。交流过后,我们不断磨合,不断测试代码,思考代码可行性,最后就在对方身上学到了很多东西。我们在设计过程中,取长补短,发挥各自的优势,一个人主要负责代码方面的问题,另一个负责测试相关的数据,总体合作下来感受到了团队合作的重要性,也因为后期的合作才能最终完成项目。