软件工程实践第二次作业

222200111李敬毅 222200111李敬毅 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
这个作业属于哪个课程https://bbs.csdn.net/forums/2401_CS_SE_FZU
这个作业要求在哪里https://bbs.csdn.net/topics/619294904
这个作业的目标完成对2024年巴黎奥运会相关数据的收集,并实现一个能够对国家排名及奖牌个数统计的控制台程序。
其他参考文献无

目录

  • 1、Gitcode项目地址
  • 2、PSP表格
  • 3、解题思路描述
  • 4、接口设计和实现过程
  • 4.1 代码设计
  • 4.2 实现过程
  • 5、关键代码展示
  • 6、性能改进
  • 7、单元测试
  • 8、心得体会

1、Gitcode项目地址

项目地址

2、PSP表格

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

3、解题思路描述

先爬取奥运会的网站数据(赛程数据,奖牌排行榜),然后运用数据进行数据处理编程。

在这里插入图片描述

4、接口设计和实现过程

4.1 代码设计

项目分为三个大类,两个小类。分别为,主函数OlympicSearchMain,指令函数TotalCommand,指令函数ScheduleCommand,以及Medal和Course两个数据对象。主要通过主函数调用两个指令函数来完成,功能1:输出所有选手信息,功能2:输出每日赛程。

4.2 实现过程

主函数OlympicSearchMain:

  • 1、创建输入输出文件,并处理异常。

    try {
              if (!out_file.exists()) {
                  out_file.createNewFile();// 创建输出文件
              }
              writer = new FileWriter(out_file, false);
              writer.append("");
              writer.flush();
          } catch (IOException e) {
              e.printStackTrace();
          } finally {
              if (null != writer)
                  writer.close();
          }
    
          try {
              if (!input_file.exists()) {
                  input_file.createNewFile();// 创建输入文件
                  Files.write(Paths.get(out_file.getPath()), "指令集为空!".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
              }
          } catch (IOException e) {
              e.printStackTrace();
          } finally {
              if (null != writer)
                  writer.close();
          }
    
          try (Scanner scanner = new Scanner(input_file,"UTF-8")) {
              if (!scanner.hasNextLine()) {
                  Files.write(Paths.get(out_file.getPath()), "指令集为空!".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
              }
    
  • 2、读取输入文件的指令,并处理异常

try (Scanner scanner = new Scanner(input_file,"UTF-8")) {
            if (!scanner.hasNextLine()) {
                Files.write(Paths.get(out_file.getPath()), "指令集为空!".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
            }
            
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                String[]  strs=line.split(" ");
                if (strs[0].equals("total")) { 
                    //若为total,则调用TotalCommand类函数
                    TotalCommand t = new TotalCommand(output_txt);
                    t.Command();
                    
                }else if (strs.length==2&&strs[0].equals("schedule")) {  
                    //若一行的第一个字符串(以" "为分隔符)为schedule,则判断第二个日期字符串,若日期字符串正确,则调用 ScheduleCommand类函数,否则输出日期格式错误。
                    ScheduleCommand s = new ScheduleCommand(output_txt, strs[1]);
                    if (!s.isBoolean()) {
                            Files.write(Paths.get(out_file.getPath()), "N/A\n-----\n".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                    }else{
                        s.Command();
                    }
                }else{
                    //都不是则输出指令错误
                    Files.write(Paths.get(out_file.getPath()), "Error\n-----\n".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                }
           }
        }

5、关键代码展示

指令代码展示,以TotalCommand 类为例。
通过Gson将json转化为java对象,用Medal对象储存数据。
然后写入输出文件

public void Command() throws IOException{
        
        File out_file = new File(output_txt);
        
        FileReader fileReader;
        fileReader = new FileReader("src\\main\\resources\\data\\medal.json");
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<Medal>>() { }.getType();
        ArrayList<Medal> list = gson.fromJson(fileReader, type);
        list.forEach(medal -> {

            String line1 = "rank" + medal.getRank() + ":" + medal.getCountryid()+"\n";
            String line2 = "gold:" + medal.getGold()+"\n";
            String line3 = "silver:" + medal.getSilver()+"\n";
            String line4 = "bronze:" + medal.getBronze()+"\n";
            String line5 = "total:" + medal.getCount()+"\n";
            String line6 = "-----"+"\n";

            try {
                Files.write(Paths.get(out_file.getPath()), line1.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line2.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line3.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line4.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line5.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line6.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });      
    }

6、性能改进

  • 将所有的写入内容合并到一个StringBuilder中,最后一次性写入文件,减少文件操作次数。
    改进前:
public void Command() throws IOException{

        File out_file = new File(output_txt);
        FileReader file_reader= new FileReader("src\\main\\resources\\data\\schedule"+" "+date+".json",StandardCharsets.UTF_8); 
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<Course>>() { }.getType();
        ArrayList<Course> list = gson.fromJson(file_reader, type);
        list.forEach(course -> {   
            String line1 = "time:" + course.getStardate()+"\n";
            String line2 = "sport:" + course.getItemcodename()+"\n";
            String line3;
            if (course.getHomename().length()<1) {
                line3 = "name:" + course.getTitle()+"\n";
            }else{
                line3 = "name:" + course.getTitle()+" "+course.getHomename() + "VS"+course.getAwayname()+"\n";
            }
            String line4 = "venue:" + course.getVenuename()+"\n";
            String line5 = "-----"+"\n";
            try {
                Files.write(Paths.get(out_file.getPath()), line1.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line2.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line3.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line4.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
                Files.write(Paths.get(out_file.getPath()), line5.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

改进后:

public void Command() throws IOException{

        File outFile = new File(output_txt);
        String filePath = "src\\main\\resources\\data\\schedule"+" "+date+".json";

        try (FileReader fileReader = new FileReader(filePath, StandardCharsets.UTF_8)) {
            Gson gson = new Gson();
            Type type = new TypeToken<ArrayList<Course>>() {}.getType();
            
            ArrayList<Course> list = gson.fromJson(fileReader, type);

            StringBuilder content = new StringBuilder();
            for (Course course : list) {
                content.append("time:").append(course.getStartdate()).append("\n");
                content.append("sport:").append(course.getItemcodename()).append("\n");
                content.append("name:");
                if (course.getHomename().isEmpty()) {
                    content.append(course.getTitle()).append("\n");
                } else {
                    content.append(course.getTitle()).append(" ").append(course.getHomename()).append("VS").append(course.getAwayname()).append("\n");
                }
                content.append("venue:").append(course.getVenuename()).append("\n");
                content.append("-----\n");
            }

            Files.write(Paths.get(outFile.getPath()), content.toString().getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
        }
    }
  • 优化了字符串拼接逻辑,提高了代码的可读性和性能。

7、单元测试

代码覆盖率:

在这里插入图片描述


单元测试

在这里插入图片描述

8、心得体会

这次作业是一次综合能力很强的作业,要求的内容基本需要新学,包括爬虫,maven依赖管理,json数据处理等等,对我来说是一项很大的挑战。一开始起步很艰难,学了很多关于爬虫的知识,也询问了很多同学的有关经验。到后面编写代码的过程才开始逐步上手,尽管还是举步维艰。经过这次作业,我认识到了很多自己的不足之处,也收获到了很多新知识,新领域,总得来说,对这个学期是一个很好的开始,对于下一次的作业,更要加倍努力。

...全文

相关推荐

PairProject:W班软件工程实践结对第二次作业仓库

结对第二次作业-顶会热词统计的实现 为了不遗漏作业内容,这里有一个清单检查表方便同学们快速检阅。 fork仓库,和伙伴商讨如何通过github协作/代码规范等 编程实现 功能一,操作爬取的论文列表 功能二,爬取结果分析展示 功能三,爬取论文信息(附加功能,实现有附加分) 其他附加功能 部署 发布发布版本,发起拉取请求 撰写博客,在预先之前提交一份博客 包含作业描述和目录 核对评分标准 上一次结对作业中,大家都和小伙伴完成了原型的设计,那么现在再联合小伙伴动手实现原型中的部分功能吧。采用网络技术来实现原型中的功能。 一,作业内容 1.基础功能 功能1:对已爬取的论文列表进行操作 可对论文列表进行删除; 可对论文列表进行查询详细信息(支持模糊查询,查询结果的展示,排序等功能可自行设计); 功能2:分析已爬取到的论文信息,提取top10个热门领域或热门研究方向 形成如关键字图谱之类直观的查看方式

ywnwx

软件工程第二次作业 计算机学院

软件工程第二次作业 计算机学院

Mingyuan Deng

2024年机器人软件工程学课程作业项目仓库_包含四次作业任务_第一次作业使用OpenCV实现图片显示功能_第二次作业开发简易聊天程序_第三次作业构建消息发布订阅系统_期末大作业完成.zip

2024年机器人软件工程学课程作业项目仓库_包含四次作业任务_第一次作业使用OpenCV实现图片显示功能_第二次作业开发简易聊天程序_第三次作业构建消息发布订阅系统_期末大作业完成.zip

2501_91769822

第二次作业.zip

第二次作业.zip

weixin_64193024

2024年机器人软件工程学课程作业项目仓库-包含四次作业任务-第一次作业使用OpenCV实现图片显示功能-第二次作业开发简易聊天程序-第三次作业构建消息发布订阅系统-期末大作业完成.zip

搜索引擎2024年机器人软件工程学课程作业项目仓库_包含四次作业任务_第一次作业使用OpenCV实现图片显示功能_第二次作业开发简易聊天程序_第三次作业构建消息发布订阅系统_期末大作业完成.zip

taozodew123
评论
收藏 已收藏
分享
返回顶部