2023软件工程导论个人项目互评

发布时间 2023-09-20 20:58:07作者: 逾昔

【HNU2023软件工程导论个人项目互评】

【目录】

一、项目要求

二、功能测试

三、代码分析

四、总结体会

【正文】

一、项目要求

1.1用户目标

小学、初中和高中数学老师。

1.2功能实现

1、命令行输入用户名和密码,两者之间用空格隔开(程序预设小学、初中和高中各三个账号,具体见附表),如果用户名和密码都正确,将根据账户类型显示“当前选择为XX出题”,XX为小学、初中和高中三个选项中的一个。否则提示“请输入正确的用户名、密码”,重新输入用户名、密码;

2、登录后,系统提示“准备生成XX数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):”,XX为小学、初中和高中三个选项中的一个,用户输入所需出的卷子的题目数量,系统默认将根据账号类型进行出题。每道题目的操作数在1-5个之间,操作数取值范围为1-100;

3、题目数量的有效输入范围是“10-30”(含10,30,或-1退出登录),程序根据输入的题目数量生成符合小学、初中和高中难度的题目的卷子(具体要求见附表)。同一个老师的卷子中的题目不能与以前的已生成的卷子中的题目重复(以指定文件夹下存在的文件为准,见5);

4、在登录状态下,如果用户需要切换类型选项,命令行输入“切换为XX”,XX为小学、初中和高中三个选项中的一个,输入项不符合要求时,程序控制台提示“请输入小学、初中和高中三个选项中的一个”;输入正确后,显示“”系统提示“准备生成XX数学题目,请输入生成题目数量”,用户输入所需出的卷子的题目数量,系统新设置的类型进行出题;

5、生成的题目将以“年-月-日-时-分-秒.txt”的形式保存,每个账号一个文件夹。每道题目有题号,每题之间空一行;

                  

二、功能测试

2.1 

 分析: 1、登录界面稍显简单 2、当输入错误的用户名和密码时,未设置校验和给用户重新输入的机会,导致出现乱码

 2.2

 分析:在登录状态下输入“切换为xx”能够对应的切换为相应的年级能够产生相对应的题目,且题目名称也按照要求完成,但高中题目全是三角函数,平方和根号的加减

2.3

 分析:当输入题目不在范围内的时候能够做出提醒并让用户有机会重新输入,但当输入数字较大时,会分成两页。

 

三、代码分析

User类

public class User {
  private String username;
  private String password;
  private String teacherType;

  public User(String name, String password, String teacherType) {
    this.username = name;
    this.password = password;
    this.teacherType = teacherType;
  }

  public String getUsername() {
    return this.username;
  }

  public String getPassword() {
    return this.password;
  }

  public String getType() {
    return this.teacherType;
  }

  public void setType(String teacherType) {
    this.teacherType = teacherType;
  }

  public void createTest(User user, int num) {
    GeneTest testCreation = new GeneTest();
    switch (this.teacherType) {
      case "小学":
        testCreation.makePrimary(user, num);
        break;
      case "初中":
        testCreation.makeJunior(user, num);
        break;
      case "高中":
        testCreation.makeSenior(user, num);
        break;
      default:
        throw new IllegalStateException("Unexpected value: " + this.teacherType);
    }

  }
}
点击查看代码

分析:对用户类的三个属性都进行了封装,且都定义了方法

GeneTest类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.test.program01;

import java.io.File;
import java.util.LinkedList;
import java.util.Random;

public class GeneTest {
  private final LinkedList<String> primary = new LinkedList();
  private final LinkedList<String> junior = new LinkedList();
  private final LinkedList<String> senior = new LinkedList();

  public GeneTest() {
    this.primary.add("+");
    this.primary.add("-");
    this.primary.add("×");
    this.primary.add("÷");
    this.junior.add("²");
    this.junior.add("√");
    this.senior.add("");
    this.senior.add("sin");
    this.senior.add("cos");
    this.senior.add("tan");
  }

  public void makePrimary(User user, int number) {
    for(int i = 0; i < number; ++i) {
      Random random = new Random();
      StringBuilder stringBuilder = new StringBuilder();
      int brackets = 0;
      int breakOrNot = false;
      int cnt = 5;

      int bracketOrNot;
      while(cnt-- > 0) {
        int breakOrNot = random.nextInt(2);
        bracketOrNot = random.nextInt(3);
        if (bracketOrNot == 1 && breakOrNot != 1 && cnt != 0) {
          ++brackets;
          stringBuilder.append("(");
        }

        int ran = random.nextInt(100) + 1;
        stringBuilder.append(ran);
        int rightBracket = random.nextInt(2);
        if (bracketOrNot != 1 && brackets > 0 && rightBracket == 1) {
          stringBuilder.append(")");
          --brackets;
        }

        if (cnt != 4 && (breakOrNot == 1 || cnt == 0)) {
          break;
        }

        int symbolSelect = random.nextInt(4);
        String symbol = (String)this.primary.get(symbolSelect);
        stringBuilder.append(symbol);
      }

      for(bracketOrNot = 0; bracketOrNot < brackets; ++bracketOrNot) {
        stringBuilder.append(")");
      }

      stringBuilder.append("=");
      IOCtrller ioCtrller = new IOCtrller();
      File newFile = ioCtrller.makeFile(user);
      String title = stringBuilder.toString();
      if (ioCtrller.check(newFile, title)) {
        --i;
      } else {
        ioCtrller.writeIn(newFile, i + 1, title);
      }
    }

  }

  public void makeJunior(User user, int number) {
    for(int i = 0; i < number; ++i) {
      Random random = new Random();
      StringBuilder stringBuilder = new StringBuilder();
      int brackets = 0;
      int breakOrNot = false;
      int cnt = 5;
      int squareOrNot = true;

      int bracketOrNot;
      while(cnt-- > 0) {
        int breakOrNot = random.nextInt(2);
        bracketOrNot = random.nextInt(3);
        if (bracketOrNot == 1 && breakOrNot != 1 && cnt != 0) {
          ++brackets;
          stringBuilder.append("(");
        }

        int evolutionOrNot = random.nextInt(2);
        if (evolutionOrNot == 1) {
          stringBuilder.append((String)this.junior.get(1));
        }

        int ran = random.nextInt(100) + 1;
        stringBuilder.append(ran);
        int squareOrNot = random.nextInt(2);
        if (squareOrNot == 1) {
          stringBuilder.append((String)this.junior.get(0));
        }

        int rightBracket = random.nextInt(2);
        if (bracketOrNot != 1 && brackets > 0 && rightBracket == 1) {
          stringBuilder.append(")");
          --brackets;
        }

        if (cnt != 4 && (breakOrNot == 1 || cnt == 0)) {
          break;
        }

        int symbolSelect = random.nextInt(4);
        String symbol = (String)this.primary.get(symbolSelect);
        stringBuilder.append(symbol);
      }

      for(bracketOrNot = 0; bracketOrNot < brackets; ++bracketOrNot) {
        stringBuilder.append(")");
      }

      stringBuilder.append("=");
      IOCtrller ioCtrller = new IOCtrller();
      File newFile = ioCtrller.makeFile(user);
      String title = stringBuilder.toString();
      if (ioCtrller.check(newFile, title)) {
        --i;
      } else {
        ioCtrller.writeIn(newFile, i + 1, title);
      }
    }

  }

  public void makeSenior(User user, int number) {
    for(int i = 0; i < number; ++i) {
      Random random = new Random();
      StringBuilder stringBuilder = new StringBuilder();
      int brackets = 0;
      int breakOrNot = false;
      int cnt = 5;
      int squareOrNot = true;

      int bracketOrNot;
      while(cnt-- > 0) {
        int breakOrNot = random.nextInt(2);
        bracketOrNot = random.nextInt(3);
        if (bracketOrNot == 1 && breakOrNot != 1 && cnt != 0) {
          ++brackets;
          stringBuilder.append("(");
        }

        int evolutionOrNot = random.nextInt(2);
        if (evolutionOrNot == 1) {
          stringBuilder.append((String)this.junior.get(1));
        }

        int tFunction = random.nextInt(3) + 1;
        stringBuilder.append((String)this.senior.get(tFunction));
        int ran = random.nextInt(100) + 1;
        stringBuilder.append(ran);
        int squareOrNot = random.nextInt(2);
        if (squareOrNot == 1) {
          stringBuilder.append((String)this.junior.get(0));
        }

        int rightBracket = random.nextInt(2);
        if (bracketOrNot != 1 && brackets > 0 && rightBracket == 1) {
          stringBuilder.append(")");
          --brackets;
        }

        if (cnt != 4 && (breakOrNot == 1 || cnt == 0)) {
          break;
        }

        int symbolSelect = random.nextInt(4);
        String symbol = (String)this.primary.get(symbolSelect);
        stringBuilder.append(symbol);
      }

      for(bracketOrNot = 0; bracketOrNot < brackets; ++bracketOrNot) {
        stringBuilder.append(")");
      }

      stringBuilder.append("=");
      IOCtrller ioCtrller = new IOCtrller();
      File newFile = ioCtrller.makeFile(user);
      String title = stringBuilder.toString();
      if (ioCtrller.check(newFile, title)) {
        --i;
      } else {
        ioCtrller.writeIn(newFile, i + 1, title);
      }
    }

  }
}
点击查看代码

分析:出题类实现随机数接口类。给不同等级做了不同的出题方法,灵活性。同时用列表储存符号,可拓展性强。

IOCtrller类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.test.program01;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class IOCtrller {
  public IOCtrller() {
  }

  public File makeFile(User user) {
    String makePath = "D:\\AutoTestGeneProgram\\TestStorage\\" + user.getUsername();
    File file = new File(makePath);
    Date date = new Date();
    SimpleDateFormat sDF = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    String var10000 = sDF.format(date);
    String testTitle = var10000 + ".txt";
    if (!file.exists()) {
      file.mkdirs();
    }

    File test = new File(makePath, testTitle);

    try {
      test.createNewFile();
    } catch (IOException var9) {
      var9.printStackTrace();
    }

    return test;
  }

  public void writeIn(File file, Integer n, String title) {
    try {
      FileWriter fileWriter = new FileWriter(file, true);
      String num = n.toString() + ".";
      fileWriter.append(num).append(" ").append(title);

      for(int i = 0; i < 2; ++i) {
        fileWriter.append("\r\n");
      }

      fileWriter.flush();
      fileWriter.close();
    } catch (IOException var7) {
      var7.printStackTrace();
    }

  }

  public boolean check(File file, String testTitle) {
    boolean repeat = false;
    String parentPath = file.getParent();
    File parent = new File(parentPath);
    File[] files = parent.listFiles();

    for(int i = 0; i < files.length; ++i) {
      File value = files[i];

      try {
        FileReader fileReader = new FileReader(value);
        BufferedReader bufferedReader = new BufferedReader(fileReader);

        while(true) {
          String usedTitle = bufferedReader.readLine();
          if (usedTitle == null) {
            break;
          }

          String[] uTitle = usedTitle.split(" ");
          if (uTitle.length > 1 && uTitle[1].equals(testTitle)) {
            System.out.println("repeated");
            repeat = true;
          }
        }
      } catch (Exception var13) {
        var13.printStackTrace();
      }
    }

    return repeat;
  }
}
点击查看代码

分析:将文件保存在相对路径下,用户文件夹在对应的用户有题目时才会生成。而且当题目数量较大时,会出现将题分散到两个列表的bug。

Login类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.test.program01;

import java.util.HashMap;
import java.util.Scanner;

public class Login {
  HashMap<String, User> userMap = new HashMap();

  public Login() {
    this.userMap.put("张三1", new User("张三1", "123", "小学"));
    this.userMap.put("张三2", new User("张三2", "123", "小学"));
    this.userMap.put("张三3", new User("张三3", "123", "小学"));
    this.userMap.put("李四1", new User("李四1", "123", "初中"));
    this.userMap.put("李四2", new User("李四2", "123", "初中"));
    this.userMap.put("李四3", new User("李四3", "123", "初中"));
    this.userMap.put("王五1", new User("王五1", "123", "高中"));
    this.userMap.put("王五2", new User("王五2", "123", "高中"));
    this.userMap.put("王五3", new User("王五3", "123", "高中"));
  }

  public void setUserType(String name, String teacherType) {
    if (teacherType.equals("小学")) {
      ((User)this.userMap.get(name)).setType(teacherType);
    } else if (teacherType.equals("初中")) {
      ((User)this.userMap.get(name)).setType(teacherType);
    } else if (teacherType.equals("高中")) {
      ((User)this.userMap.get(name)).setType(teacherType);
    } else {
      System.out.println("输入小学、初中或高中");
    }

  }

  public void userLogin(String name, String password) {
    User user = (User)this.userMap.get(name);
    System.out.println("当前选择:为" + user.getType() + "出题");
    if (!user.getPassword().equals(password)) {
      System.out.println("请输入正确的用户名、密码");
    } else {
      while(true) {
        while(true) {
          System.out.println("准备生成" + user.getType() + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录;输入切换为XX,可更改题目种类):");
          String inStr = (new Scanner(System.in)).next();
          if (inStr.length() > 4) {
            String sub = inStr.substring(0, 3);
            if (sub.equals("切换为")) {
              this.setUserType(name, inStr.substring(3, 5));
            } else {
              System.out.println("输入内容有误");
            }
          } else {
            int num = 0;

            try {
              num = Integer.parseInt(inStr);
            } catch (NumberFormatException var7) {
              var7.printStackTrace();
            }

            if (num == -1) {
              return;
            }

            if (num >= 10 && num <= 30) {
              user.createTest(user, num);
              System.out.println("题目生成完毕,请到文件夹中查看");
            } else {
              System.out.println("请输入10-30之间的自然数 或 输入-1退出");
            }
          }
        }
      }
    }
  }
}
点击查看代码

分析:用户的初始化放在了用户操作类中,调用userLogin()登录后直接进入了用户界面。但缺少了对错误用户名或者密码判断的功能

main

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.test.program01;

import java.util.Scanner;

public class Main {
  public Main() {
  }

  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    Login login = new Login();

    while(true) {
      System.out.println("请输入用户名、密码,以空格分离");
      login.userLogin(in.next(), in.nextLine().trim());
    }
  }
}

分析:使用Scanner(),但个人感觉登陆界面可以多少加以装饰

四、总结体会

优点:

  1. 代码逻辑清晰,各个方法完成功能单一,便于阅读与理解;
  2. 功能实现思路清晰,层次分明,添加括号,判断重复等功能都单独提取出来当成一个方法,易于阅读和修改;
  3. 基本功能都能实现;
  4. 代码结构合理,使用了接口类与其实现,可拓展性好;
  5. 运用了try...catch,合理解决了很多bug;

 

缺点:

      1.登录界面未对错误用户名或密码做出判断,出现bug;

        2.有的方法代码行数太多

        3.高中题目出题不合理,全是三角函数之间的运算

总结:

      在短时间内利用自己所学实现众多功能实属不易,虽有一些bug,但希望经过改进后能够越来越好。