软件工程实践第二次作业——个人实战
软件工程实践第二次作业——个人实战
| 这个作业属于哪个课程 | 软件工程实践-2023学年-W班 |
|---|---|
| 这个作业要求在哪里 | 软件工程实践第二次作业——个人实战 |
| 这个作业的目标 | 完成对世界游泳锦标赛跳水项目相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序 |
| 其他参考文献 | 《构建之法》《源代码管理》 |
目录
- 软件工程实践第二次作业——个人实战
- Gitcode项目地址
- PSP表格
- 解题思路描述
- 对于数据的获取
- 开始时想到了三个方法:
- Json的解析
- 对input.txt文件的读取
- 接口设计和实现过程
- 接口设计
- 接口实现
- 关键代码展示
- 性能改进
- 单元测试
- 异常处理
- 心得体会
Gitcode项目地址
https://gitcode.net/xjr16/project-java
PSP表格
| 软工开发阶段 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|
| 计划 | 10 | 20 |
| 开发 | 420 | 600 |
| 需求分析 (包括学习新技术) | 30 | 60 |
| 生成设计文档 | 15 | 30 |
| 设计复审 | 15 | 15 |
| 代码规范 (为目前的开发制定合适的规范) | 5 | 5 |
| 具体设计 | 40 | 40 |
| 具体编码 | 300 | 520 |
| 代码复审 | 60 | 180 |
| 测试(自我测试,修改代码,提交修改) | 60 | 30 |
| 报告 | 30 | 30 |
| 测试报告 | 30 | 30 |
| 计算工作量 | 10 | 10 |
| 事后总结, 并提出过程改进计划 | 60 | 30 |
| 合计 | 1110 | 1800 |
解题思路描述
对于数据的获取
开始时想到了三个方法:
- 通过爬虫软件获取网页资源获取信息
- 通过获取网站api获取json信息进行解析
- 通过获取网站api获取json信息进行解析后,将其转为csv文件进行储存,通过代码调取csv文件进行信息获取
- 最后选择了第三点
- 获取api

- 解析api并转换成csv

Json的解析
- 学习maven管理资源包的办法
- 导入json包进行解析
- 在getdata中成功获取到信息
对input.txt文件的读取
scanner.nextLine().trim()的读取获取input.txt里面的内容再调用函数对output.txt进行输出
接口设计和实现过程
接口设计
- 通过在抽象类中定义构造函数,并在子类中使用super关键字调用父类的构造函数,可以实现在新类中直接获取不同功能所需的信息
- 子类再通过获取的信息,完成具体的函数实现其功能
接口实现

- 通过运行
getData获取csv数据表格 CompletionResult,CompletionResultDetail,Player都继承与AbstractPlayers,分别处理不同指令
关键代码展示
基础功能
public Player(String fullName, String gender, String country) { this.fullName = fullName; this.gender = gender; this.country = country; } @Override public String toString() { return "Full Name:" + fullName + "\nGender:" + gender + "\nCountry:" + countryName(country) + "\n-----\n"; } public static void printPlayers(List<Player> players, PrintWriter writer) { for (Player player : players) { writer.print(player); } }public static List<CompletionResult> readCompletionResult(String Result) throws FileNotFoundException { List<CompletionResult> CompletionResult = new ArrayList<>(); InputStream stream = CompletionResult.class.getResourceAsStream(Result); if (stream == null) { throw new FileNotFoundException( Result + " not found"); } try (Scanner scanner = new Scanner(stream)) { scanner.nextLine(); // skip header line while (scanner.hasNextLine()) { String[] data = scanner.nextLine().split(","); String[] divePoints = data[2].split(" \\+ "); CompletionResult.add(new CompletionResult(data[0].trim(), data[5].trim(), divePoints, data[3].trim(), data[4].trim(), data[6].trim(), data[1].trim())); } } return CompletionResult; }public static void printCompletionResult(List<CompletionResult> CompletionResult, PrintWriter writer) { for (CompletionResult player : CompletionResult) { writer.println("Full Name:" + player.getName()); writer.println("Rank:" + player.getRank()); //去除null值 String scores = Arrays.stream(player.getDivePoints()) .filter(Objects::nonNull) .collect(Collectors.joining(" + ")); writer.println("Score:" + scores + " = " + player.getTotalPoints()); writer.println("-----"); } }主类
public class DWASearch { public static void main(String[] args) throws IOException { List<Player> players = new ArrayList<>(); InputStream stream = DWASearch.class.getResourceAsStream("/players.csv"); if (stream == null) { throw new FileNotFoundException("/csv/players.csv not found"); } try (Scanner scanner = new Scanner(stream)) { scanner.nextLine(); // skip header line while (scanner.hasNextLine()) { String[] data = scanner.nextLine().split(","); players.add(new Player(data[3].trim(), data[1].trim(), data[0].trim())); } } try (Scanner scanner = new Scanner(new File("input.txt")); PrintWriter writer = new PrintWriter(("output.txt"))) { while (scanner.hasNextLine()) { String command = scanner.nextLine().trim(); if (command.isEmpty()) { continue; // skip empty lines } if ("players".equals(command)) { printPlayers(players, writer); } else if (command.startsWith("result ")) { String condition = command.substring(7); // 获取后面的值 boolean hasDetail = condition.endsWith(" detail"); condition = hasDetail ? condition.substring(0, condition.length() - 7) : condition; // 判断条件后的detail switch (condition) { case "women 1m springboard": if (hasDetail) { printDetailedCompletionResult(readCompletionResult("/Women 1m Springboard.csv"), writer);// 这里是当指令包含detail时执行的代码 } else CompletionResult.printCompletionResult(CompletionResult.readCompletionResult("/Women 1m Springboard.csv"), writer); break; //... default: writer.println("N/A"); writer.println("-----"); break; } } else { writer.println("Error"); writer.println("-----"); } } } }datil功能实现
public static Map<String, CompletionResultDetail> readCompletionResult(String Result) throws FileNotFoundException { Map<String, CompletionResultDetail> playerScoresMap = new HashMap<>(); try (Scanner scanner = new Scanner(Objects.requireNonNull(CompletionResultDetail.class.getResourceAsStream(Result)))) { scanner.nextLine(); // skip header line while (scanner.hasNextLine()) { String[] data = scanner.nextLine().split(","); String[] divePoints = data[2].split(" \\+ "); String fullName = data[0].trim(); String phaseName = data[6].trim(); String scores = Arrays.stream(divePoints) .filter(Objects::nonNull) .collect(Collectors.joining(" + ")); CompletionResultDetail completionResultDetail = playerScoresMap.computeIfAbsent(fullName, k -> new CompletionResultDetail(fullName, data[1].trim(), data[5].trim())); completionResultDetail.addScore(phaseName, scores); completionResultDetail.addRank(phaseName, data[4].trim()); // 添加排名 completionResultDetail.setTotalPoints(data[3].trim()); // 读取总分 } } return playerScoresMap; } public static void printDetailedCompletionResult(Map<String, CompletionResultDetail> playerScoresMap, PrintWriter writer) { for (Map.Entry<String, CompletionResultDetail> entry : playerScoresMap.entrySet()) { writer.println("Full Name:" + entry.getKey()); writer.println("Rank:" + entry.getValue().getRank("Preliminaries") + " | " + entry.getValue().getRank("Semifinals") + " | " + entry.getValue().getRank("Finals")); // 打印排名 writer.println("Preliminary Score:" + entry.getValue().getScore("Preliminaries") + " = " + entry.getValue().getTotalPoints()); writer.println("Semifinal Score:" + entry.getValue().getScore("Semifinals") + " = " + entry.getValue().getTotalPoints()); writer.println("Final Score:" + entry.getValue().getScore("Finals") + " = " + entry.getValue().getTotalPoints()); writer.println("-----"); } }性能改进
文件读取优化:在所有涉及文件读取的地方,可以使用BufferedReader来替换Scanner,以提高文件读取的效率
替换前


- 替换成BufferedReader后


单元测试
- 测试代码

- 测试结果

异常处理
- 对文件的读取做出了异常处理

心得体会
- 学习到了基础的开发流程,对文件与流,json解析与api获取都有了新的认识,从中获益许多。
...全文


