软件工程第二次作业———个人实战

222100228郑泽岚 2024-02-29 23:41:14
这个作业属于哪个课程软件工程实践-2023 学年-W 班
这个作业要求在哪里软件工程实践第二次作业——个人实战
这个作业的目标完成对世界游泳锦标赛跳水项目相关数据的收集
其他参考文献...

@

文章目录

  • 零、gitcode 项目地址
  • 一、PSP 表格
  • 二、解题思路描述
  • 功能一:
  • 功能二
  • 三、设计与实现过程在设计和实现过程中,我们将代码组织成了几个函数和类,以实现清晰的逻辑和结构:
  • 四、程序性能改进
  • 五、单元测试展示
  • 六、心路历程与收获

零、gitcode 项目地址

https://gitcode.net/zzl18396534089/project-java

一、PSP 表格

PSPPersonal Software Process Stages预估耗时(分钟)表实际耗时(分钟)
Planning计划12030
• Estimate• 估计这个任务需要多少时间10001150
Development开发800960
• Analysis• 需求分析 (包括学习新技术)200300
• Design Spec• 生成设计文档5030
• Design Review• 设计复审2030
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)6040
• Design• 具体设计6060
• Coding• 具体编码300400
• Code Review• 代码复审6080
• Test• 测试(自我测试,修改代码,提交修改)5020
Reporting报告8060
• Test Repor• 测试报告3030
• Size Measurement• 计算工作量2010
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划3020
合计10001150

二、解题思路描述

在解决此问题时,我们的主要目标是从世界游泳锦标赛的官方 API 中收集跳水项目的相关数据。首先不论功能,现将命令行程序写好并进行测试,与命令行程序一桶的还有输入判断部分。而信息的爬取则通过爬虫程序获取。

功能一:

我们需要根据用户的输入“players”从 API 中发送请求,获取我们想要的选手信息并返回文件流中。

功能二

我们需要根据用户的输入查找特定比赛结果,为了实现这一目标我们需要:
1、获取比赛信息:
我们通过 API 获取比赛项目列表,然后根据用户输入的比赛项目名称,查找相应的比赛项目。

2、获取比赛结果:
对于特定的比赛项目,我们使用其唯一的比赛 ID 从 API 中获取比赛结果。然后,我们提取所需的信息,如选手的全名、排名和得分,并将其输出到输出文件中,遇到比赛 Name 非 Final 的直接进行跳过。

三、设计与实现过程在设计和实现过程中,我们将代码组织成了几个函数和类,以实现清晰的逻辑和结构:

DWASearch 类: 这是程序的入口点,负责解析命令行参数、读取输入文件并写入输出文件。它根据用户的命令调用适当的函数来执行相应的操作。
这是主类的实现:

public class DWASearch {
    public static void main(String[] args) {
        String inputFile = args[0];
        String outputFile = args[1];
        System.out.println(inputFile);
        try {
            BufferedReader reader = new BufferedReader(new FileReader(inputFile));  // 打开输入文件
            BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile)); // 打开输出文件
            String command;    // 逐行读取输入文件并写入输出文件
            while ((command = reader.readLine()) != null) {
                if ("players".equals(command)) {
                    Lib.playersPrint(writer);
                    // writer.write("选手信息...后补");
                } else if (command.startsWith("result") && (!command.endsWith("detail"))) {
                    String project = command.substring(6); // 获取result后比赛项目
                    if (project.startsWith(" ")) {
                        project = project.substring(1);
                        // System.out.println(project);
                        if (project.equals("women 1m springboard") || project.equals("women 3m springboard") || project.equals("women 10m platform")
                                || project.equals("women 3m synchronised") || project.equals("women 10m synchronised") || project.equals("men 1m springboard")
                                || project.equals("men 3m springboard") || project.equals("men 10m platform") || project.equals("men 3m synchronised")
                                || project.equals("men 10m synchronised")) {
                            // System.out.println(project);
                            Lib.searchCompetitionName(project, writer);
                        } else {
                            writer.write("N/A");
                        }
                    } else {
                        writer.write("Error");
                    }
                } else {
                    writer.write("Error");
                }
                writer.write("\n");
                // writer.write("这里的吗?-----");
                writer.write("\n");
            }

            reader.close();
            writer.close();
            // 关闭文件流
            System.out.println("文件流已关闭,检查结果");
        } catch (IOException e) {
            System.out.println("发生错误" + e.getMessage());
        }
    }
}

爬虫的首要步骤是在官网内找到相应的 api,先找到运动员信息,点击 athlete 查看网络响应并随机搜索一个运动员的名字就能找到:

在这里插入图片描述


然后点击 results 随机输入一个比赛名称即可获得各个比赛对应 id:

在这里插入图片描述

最后通过对应比赛 id 找到各个比赛详细信息:

在这里插入图片描述

Lib 类: 这个类包含了用于处理 API 请求和处理 JSON 数据的静态方法。它包括以下功能:

  • 获取选手信息并将其输出到文件中。下列是相关接口和实现:
public static void playersPrint(BufferedWriter writer)
  • 实现:
    public static void playersPrint(BufferedWriter writer) {
        String url = "https://api.worldaquatics.com/fina/competitions/3337/athletes?gender=&countryId=";
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // 设置用户代理

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();

                // 检查返回的是否为JSON数据
                if (isValidJSON(response.toString())) {
                    processJSONDataForPlayers(response.toString(), writer);
                } else {
                    System.out.println("返回的数据不是有效的JSON格式!");
                }
            } else {
                System.out.println("爬取失败啦!: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 根据比赛项目名称查找比赛并获取比赛结果。下列是相关接口和实现:
public static void processJSONDataForPlayers(String jsonData, BufferedWriter writer)
public static void searchCompetitionName(String competitionName, BufferedWriter writer)
public static void processJSONDataForCompetition(String jsonData, BufferedWriter writer, String competitionName)
public static void searchJSONDataForResult(String url, BufferedWriter writer)
  • 实现:
public static void processJSONDataForPlayers(String jsonData, BufferedWriter writer) {
        try {
            JSONArray jsonArray = new JSONArray(jsonData);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject countryObj = jsonArray.getJSONObject(i);
                String countryName = countryObj.getString("CountryName");
                // 处理 Participations 字段
                JSONArray participations = countryObj.optJSONArray("Participations");
                if (participations != null) {
                    for (int j = 0; j < participations.length(); j++) {
                        JSONObject participationObj = participations.getJSONObject(j);
                        String lastName = participationObj.getString("PreferredLastName");
                        String firstName = participationObj.getString("PreferredFirstName");
                        String gender = participationObj.getInt("Gender") == 0 ? "Male" : "Female";
                        String fullName = lastName + " " + firstName;
                        writer.write("Full Name:" + fullName + "\n");
                        writer.write("Gender:" + gender + "\n");
                        writer.write("Country:" + countryName + "\n");
                        writer.write("-----\n");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
public static void searchCompetitionName(String competitionName, BufferedWriter writer) {
        String url = "https://api.worldaquatics.com/fina/competitions/3337/events";
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // 设置用户代理

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();

                // 检查返回的是否为JSON数据
                if (isValidJSON(response.toString())) {
                    processJSONDataForCompetition(response.toString(), writer, competitionName);
                } else {
                    System.out.println("返回的数据不是有效的JSON格式!");
                }
            } else {
                System.out.println("比赛ID爬取失败啦!: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
public static void processJSONDataForCompetition(String jsonData, BufferedWriter writer, String competitionName) {
        try {
            JSONObject jsonObject = new JSONObject(jsonData);
            JSONArray sportsArray = jsonObject.getJSONArray("Sports");
            for (int i = 0; i < sportsArray.length(); i++) {
                JSONObject sportObj = sportsArray.getJSONObject(i);
                JSONArray disciplineList = sportObj.getJSONArray("DisciplineList");
                for (int j = 0; j < disciplineList.length(); j++) {
                    JSONObject disciplineObj = disciplineList.getJSONObject(j);
                    String disciplineName = disciplineObj.getString("DisciplineName");
                    if (disciplineName.equalsIgnoreCase(competitionName)) {
                        String disciplineId = disciplineObj.getString("Id");
                        searchJSONDataForResult(disciplineId, writer);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void searchJSONDataForResult(String url, BufferedWriter writer) {
        String finalUrl = "https://api.worldaquatics.com/fina/events/" + url;
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(finalUrl).openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // 设置用户代理

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
                if (isValidJSON(response.toString())) {
                    processJSONDataForResult(response.toString(), writer);
                } else {
                    System.out.println("返回的数据不是有效的JSON格式!");
                }
            } else {
                System.out.println("比赛信息爬取失败啦!: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 从 JSON 数据中提取所需的信息,如选手姓名、排名和得分。下列是相关接口和实现:
    public static void processJSONDataForResult(String jsonData, BufferedWriter writer) {
        try {
            JSONObject jsonObject = new JSONObject(jsonData);
            JSONArray heats = jsonObject.getJSONArray("Heats");
            for (int i = 0; i < heats.length(); i++) {
                JSONObject heat = heats.getJSONObject(i);
                String heatName = heat.getString("Name"); // 获取 Heat 的名称
                JSONArray results = heat.getJSONArray("Results");
                for (int j = 0; j < results.length(); j++) {
                    JSONObject resultObj = results.getJSONObject(j);
                    String fullName = resultObj.getString("FullName");
                    String totalPoints = resultObj.getString("TotalPoints");
                    int rank = resultObj.getInt("Rank");
                    if (!heatName.equalsIgnoreCase("Final")) {
                        // 如果detail为false且不是final结果,则跳过
                        continue;
                    }
                    if (fullName.contains("/")) {
                        String[] nameArray = fullName.split(" / ");
                        Arrays.sort(nameArray, String.CASE_INSENSITIVE_ORDER);
                        fullName = String.join(" & ", nameArray);
                    }
                    if (heatName.equalsIgnoreCase("Final")) {
                        writer.write("Full Name:" + fullName + "\n");
                        writer.write("Rank:" + rank + "\n");
                        JSONArray dives = resultObj.getJSONArray("Dives");
                        StringBuilder divePointsString = new StringBuilder();
                        for (int k = 0; k < dives.length(); k++) {
                            JSONObject divesObj = dives.getJSONObject(k);
                            String eachResult = divesObj.getString("DivePoints");
                            divePointsString.append(" + ").append(eachResult);
                        }
                        writer.write("Score:" + divePointsString.substring(3) + " = " + totalPoints + "\n");
                        writer.write("-----\n");
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

四、程序性能改进

我们对程序性能进行了改进,主要集中在以下几个方面:

  • HTTP 请求优化: 使用了合适的请求头和连接参数,以提高请求的效率和稳定性。

  • JSON 数据处理优化: 对 JSON 数据的处理进行了优化,尽量减少不必要的循环和嵌套,以提高处理效率。

五、单元测试展示

  • 测试代码:
public class test {
    public static void main(String[] args) {
        // 指定文件名
        String fileName = "input.txt";
        // 指定要生成的行数
        int numLines = 100;
        // 定义有效的事件列表
        List<String> validEvents = Arrays.asList(
                "women 1m springboard", "women 3m springboard", "women 10m platform",
                "women 3m synchronised", "women 10m synchronised",
                "men 1m springboard", "men 3m springboard", "men 10m platform",
                "men 3m synchronised", "men 10m synchronised"
        );
        Random random = new Random();
        int j = 0;
        // 使用 try-with-resources 语句来确保 BufferedWriter 被正确关闭
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            for (int i = 0; i < numLines; i++) {
                j = random.nextInt(validEvents.size());
                String event = validEvents.get(j);
                writer.write("result " + event + "\n");
            }
            System.out.println("文件 " + fileName + " 已生成,包含 " + numLines + " 行指令。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

生成完毕


相关 input·、output 文件已提交。

六、心路历程与收获

在完成本次任务的过程中,确实遇到了一些挑战,如处理复杂的 JSON 数据结构、优化程序性能和处理异常情况等。通过不断的学习和实践,我逐渐解决了这些问题,并取得了相当的收获:

  • 加强了编程技能: 通过实际项目的实践,巩固了 Java 编程基础,并学习了如何处理外部 API 和 JSON 数据。
  • 提高了问题解决能力: 面对各种挑战和困难,学会了如何分析问题、寻找解决方案,并不断优化和改进程序。
  • 通过这次项目,我不仅完成了任务要求,还积累了宝贵的经验和技能,为以后的学习和工作打下了良好的基础。
...全文
78 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

315

社区成员

发帖
与我相关
我的任务
社区描述
福州大学的软件工程实践-2023学年-W班
软件工程需求分析结对编程 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • Pity·Monster
  • 助教张富源
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧