结对项目

软件工程 网工1934班级链接
作业要求 作业要求链接
作业目标 体验结对编程

欧柱轩 3119005391
黄俊鸿 3119005373
项目 GitHub 链接

一、PSP 表格

PSP 2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 60 85
Development 开发
· Analysis · 需求分析 (包括学习新技术) 240 320
· Design Spec · 生成设计文档 30 25
· Design Review · 设计复审 10 3
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 15
· Design · 具体设计 120 200
· Coding · 具体编码 150 285
· Code Review · 代码复审 60 80
· Test · 测试(自我测试,修改代码,提交修改) 30 95
Reporting 报告
· Test Report · 测试报告 15 25
· Size Measurement · 计算工作量 5 15
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 10 12
· 合计 750 1160

二、设计实现过程

模块设计

  • Expression 类:使用二叉树封装表达式的类,包含了一个生成表达式二叉树的方法。
  • Ran 类:包括随机生成运算符、整数、分数和子节点位置的方法。
  • TreeNode 类:getResult(),获取每个结点的运算结果并检验是否出现负数、除数为0的情况;toString(),按照优先级添加及去除括号,形成表达式串。
  • Generator 类:generate(),根据要求数量及最大值生成题目和答案并写入 txt 文件。
  • Calculator 类:实现真分数的加减乘除运算。
  • Check 类:实现对练习答案中对错的判定及数量统计。
  • FileUtil 类:txt 写入工具类。
  • CommandResolver 类:解析命令参数,包括 -n、-r、-e、-a。

项目结构

结对项目 ## 关键函数 getResult(): 结对项目

三、代码说明

生成二叉树

public void createBTree(){
    TreeNode lchild, rchild, lnode, rnode;

    if(num == 1){ //一个运算符的情况
        lchild = new TreeNode(String.valueOf(Ran.getNumber(max)), null, null); //生成随机数并赋值给叶节点
        rchild = new TreeNode(String.valueOf(Ran.getNumber(max)), null, null);
        root = new TreeNode(String.valueOf(Ran.getOperator()), lchild, rchild); //随机运算符根节点
    }
    else{
        int num1 = 0;
        boolean[] place = Ran.getChildPlace(num);
        root = new TreeNode(String.valueOf(Ran.getOperator()), null, null);
        opeList.add(root);

        for(int i = 0; i < place.length; i++){
            if(place[i]){ //生成一个运算符节点
                lnode  = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null);
                rnode  = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null);
                if(i%2 == 0){
                    lchild = new TreeNode(String.valueOf(Ran.getOperator()), lnode, rnode);
                    opeList.add(lchild);
                    opeList.get(num1).setLchild(lchild);
                }
                else{
                    rchild = new TreeNode(String.valueOf(Ran.getOperator()), lnode, rnode);
                    opeList.add(rchild);
                    opeList.get(num1).setRchild(rchild);
                }
            }
            else{ //生成一个左/右孩子
                if(i%2 == 0){
                    lchild = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null);
                    opeList.get(num1).setLchild(lchild);
                }
                else{

                    rchild = new TreeNode(String.valueOf(Ran.getNumber(10)), null, null);
                    opeList.get(num1).setRchild(rchild);
                }
            }
            num1 = num1 + i%2; //num1为偶说明孩子未生成
        }
    }
}

校验统计练习答案对错

public void grade(String Exercisefile,String AnswerFile) throws IOException {
    file1 = Exercisefile;
    file2 = AnswerFile;

    try {
        br1 = new BufferedReader(new FileReader(file1));
        br2 = new BufferedReader(new FileReader(file2));
        bw = new BufferedWriter(new FileWriter(file3));
    } catch (IOException e) {
        e.printStackTrace();
    }

    result1 = "correct:";
    result2 = "wrong:";
    sb1.append("(");
    sb2.append("(");
    String str = null, str1 = null;
    String[] strings = null, strings1 = null;
    while ((str = br1.readLine()) != null && (str1 = br2.readLine()) != null) {
        strings = str.split("="); //分割练习字符串,=后为答案
        strings1 = str1.split("\\."); //分割答案字符串,.后为答案
        if (strings[1].equals(strings1[1])) {
            rightCount++;
            sb1.append(strings1[0] + ",");
        }else {
            wrongCount++;
            sb2.append(strings1[0] + ",");
        }
    }
    //去掉尾部多余的,
    if(rightCount != 0)
        sb1.deleteCharAt(sb1.length() - 1);
    if(wrongCount != 0)
        sb2.deleteCharAt(sb2.length() - 1);
    sb1.append(")");
    sb2.append(")");
    result1 += rightCount + sb1.toString();
    result2 += wrongCount + sb2.toString();
    bw.write(result1);
    bw.newLine();
    bw.write(result2);
    br1.close();
    br2.close();
    bw.close();
}

四、性能分析

结对项目结对项目

五、测试分析

public class TestGenerator {
    /**
     * 测试无 -r 参数情况
     */
    @Test
    public void testCommandNotParamR() throws IOException {
        Main.main(new String[]{"-n", "5"});
    }

    /**
     * 测试 -r 参数后无输入整数情况
     */
    @Test
    public void testCommandFormatError() throws IOException {
        Main.main(new String[]{"-r", "五"});
    }

    /**
     * 测试无 -n 参数情况(默认为5,即生成5道题)
     */
    @Test
    public void testCommandNotParamN() throws IOException {
        //无指定-n时默认为5
        Main.main(new String[]{"-r", "10"});
    }

    /**
     * 测试参数输入错误情况
     */
    @Test
    public void testCommandParamError() throws IOException {
        Main.main(new String[]{"-nsfd", "5", "-r", "6"});
    }

    /**
     * 测试参数个数错误的情况(非2非4)
     */
    @Test
    public void testCommandParamNumError() throws IOException {
        Main.main(new String[]{"-r", "5", "-n"});
    }

    /**
     * 生成6道题,最大值为10的情况(-n参数在前)
     */
    @Test
    public void testCommandFirstNThenR() throws IOException {
        Main.main(new String[]{"-n", "6", "-r", "10"});
    }

    /**
     * 生成10道题,最大值为10的情况(-n参数在后)
     */
    @Test
    public void testCommandFirstRThenN() throws IOException {
        Main.main(new String[]{"-r", "10", "-n", "20"});
    }

    /**
     * 生成10000道题,最大值为10的情况
     */
    @Test
    public void testCommandNice2() throws IOException {
        Main.main(new String[]{"-n", "1000", "-r", "10"});
    }

    /**
     * 测试判断答案对错并统计
     */
    @Test
    public void testGrade() throws IOException {
        Main.main(new String[]{"-e", "F:\\Unicourses\\SE\\arithmetic-generator\\Exercise.txt", "-a", "F:\\Unicourses\\SE\\arithmetic-generator\\Answers.txt"});
    }
}

测试截图:
结对项目
结对项目
结对项目
结对项目
结对项目
结对项目
结对项目
结对项目
结对项目
结对项目

六、项目小结

欧柱轩:

刚看到题目时以为比较简单,但到了真正动手做的时候,发现要考虑的事情还挺多。在和俊鸿互相探讨交流的过程里,逐渐明确了目标以及分工,最后终于是完成了课题。这是我第一次与他人合作完成任务,让我深刻意识到交流是多么的重要。俊鸿对代码的严谨和一丝不苟十分值得我学习。

黄俊鸿:

两个人的思想碰撞是一件很有趣的事儿,虽然可能没有完全按照结对编程的分工流程,但还是挺享受其中的过程的。柱轩对项目全局的把控很到位,十分值得我学习。

上一篇:[LeetCode 278,283][简单]第一个错误的版本/移动零


下一篇:力扣283.移动0