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

222200224徐逸凡 2024-09-10 16:59:55
这个作业属于哪个课程2401_CS_SE_FZU
这个作业要求在哪里软件工程实践第二次作业——个人实战
这个作业的目标完成对2024年巴黎奥运会相关数据的收集,并实现一个能够对国家排名及奖牌个数统计的控制台程序。
其他参考文献构建之法

目录

  • 1.项目地址
  • 2.psp表格
  • 3.解题思路描述
  • 3.1获取网站数据
  • 3.2 处理输入数据
  • 4.接口设计与实现过程
  • 4.1 readRankFile
  • 4.2 readScheduleFile
  • 4.3 isDuringOlympics
  • 5.关键代码展示
  • 5.1按行判断输入
  • 5.2输出奖牌榜
  • 5.3输出赛程
  • 5.4判断日期是否合理
  • 6.性能改进
  • 7.单元测试
  • 8.异常处理
  • 9.心得体会

1.项目地址

项目地址

2.psp表格

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

3.解题思路描述

首先需要获取网站的数据,存储到data目录中,随后根据input.txt中的内容,将处理好的数据输入到output.txt中

3.1获取网站数据

img

使用浏览器插件Instant Data Scraper 爬取每日赛程数据和奖牌榜数据,简单高效,但爬取后的数据还需要进一步修改来和输出要求相匹配

3.2 处理输入数据

一共要实现两种功能,输出每日赛程和选手奖牌榜,要实现可以读入多行数据并判断每行输入是否合法,先检测total与schedule,若为total则输出选手奖牌榜,schedule需要跳过空格读取日期,还要判断日期是否合法,如果不合法输出N/A,其余输入都将报错输出Error和分隔符

4.接口设计与实现过程

4.1 readRankFile

读取奖牌榜文件并输出至输出文件

4.2 readScheduleFile

读取每日赛程文件并输出至输出文件

4.3 isDuringOlympics

判断schedule 日期是否合法,如果日期不合法则返回false,但不会中止程序进行,保证了程序的连续性,从开始到结束能够平滑地运行,不会因为错误、异常或外部干扰而中断。

5.关键代码展示

5.1按行判断输入

private static void processInput(String inputLine, String dataDirPath, BufferedWriter writer) throws IOException {
    if ("total".equals(inputLine)) {
        String rankFilePath = dataDirPath + File.separator + "rank.txt";
        Lib.readRankFile(rankFilePath, writer);
    } else if (inputLine.startsWith("schedule")) {
        String[] parts = inputLine.split("\\s+", 2);
        if (parts.length == 2) {
            String date = parts[1];
            if (Lib.isDuringOlympics(date)) {
                String scheduleFilePath = dataDirPath + File.separator + date + ".txt";
                Lib.readScheduleFile(scheduleFilePath, writer);
            } else {
                writer.write("N/A");
                writer.newLine();
                writer.write("-----");
                writer.newLine();
            }
        } else {
            writer.write("Error");
            writer.newLine();
            writer.write("-----");
            writer.newLine();
        }
    } else {
        writer.write("Error");
        writer.newLine();
        writer.write("-----");
        writer.newLine();
    }
}

5.2输出奖牌榜

public static void readRankFile(String rankFilePath, BufferedWriter writer) {
    try (BufferedReader rankReader = new BufferedReader(new InputStreamReader(new FileInputStream(rankFilePath), StandardCharsets.UTF_8))) {
        String line;
        while ((line = rankReader.readLine()) != null) {
            writer.write(line);
            writer.newLine();
        }
    } catch (IOException e) {
        System.err.println("I/O error occurred: " + e.getMessage());
        e.printStackTrace();
    }
}

5.3输出赛程

public static void readScheduleFile(String scheduleFilePath, BufferedWriter writer) {
    try (BufferedReader scheduleReader = new BufferedReader(new InputStreamReader(new FileInputStream(scheduleFilePath), StandardCharsets.UTF_8))) {
        String line;
        while ((line = scheduleReader.readLine()) != null) {
            writer.write(line);
            writer.newLine();
        }
    } catch (IOException e) {
        System.err.println("I/O error occurred: " + e.getMessage());
        e.printStackTrace();
    }
}

5.4判断日期是否合理

public static boolean isDuringOlympics(String date) {
    try {
        SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
        Date olympicStart = sdf.parse("0724");
        Date olympicEnd = sdf.parse("0811");
        Date givenDate = sdf.parse(date);
        return givenDate.compareTo(olympicStart) >= 0 && givenDate.compareTo(olympicEnd) <= 0;
    } catch (ParseException e) {
        System.err.println("ParseException caught: " + e.getMessage());
        e.printStackTrace();
        return false;
    }
}

6.性能改进

使用了缓冲(Buffering)来提高 I/O 性能的,特别是在处理文件读写操作时。缓冲的基本原理是将数据暂存到内存中的一个缓冲区,当缓冲区满或者显式地调用刷新操作时,再将数据一次性写入到磁盘或从磁盘读取。这样可以减少实际的 I/O 操作次数,从而提高性能。提将小的、频繁的数据请求合并为较大的、
较少的传输,从而提高数据传输的效率。

7.单元测试

使用Junit4框架

img

1.测试 "total" 指令读取排名文件
2.测试 "schedule" 指令与有效日期
3.测试 "schedule" 指令与无效日期
4.测试 "schedule" 指令缺少日期
5.测试未知指令
6.测试空行输入
7.测试 "total" 指令但文件不存在
8.测试 "schedule" 指令但文件不存在
9.测试输入包含额外空白
10.测试输入包含非预期字符

8.异常处理

捕获IOException、ParseException、FileNotFoundException来实现,当文件未找到时会提示调用者"File not found",其他类型的I/O异常、解析字符串日期时也会提示调用者异常的出现

9.心得体会

学习了爬虫技术和测试技术,编程方面难度不大,完成的也比较顺利,前期数据处理和后期的代码测试花费了大量时间,深刻体会到了项目开发的不容易,也对自己的能力有更深刻的认知,在软件开发这个领域,还有很多知识需要学习,还有很长的路要走。

...全文
231 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
文末附数据集可视化效果图。 【数据集概况】 · 检测类别(中文):[护栏(bollard)] · 训练集:2239 张 · 验证集:640 张 · 测试集:320 张 · 总计:3199 张 城市街道护栏目标检测数据集... 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 94 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.7341** mAP50-95 | 0.3921 Precision | 0.7873 Recall | 0.6713 train/box_loss | 1.5260 train/cls_loss | 0.8206 val/box_loss | 1.7977 val/cls_loss | 1.1156 【训练过程分析】 94 轮训练后 mAP50 为 0.7341,模型基本收敛但还有提升余地。Loss 曲线下降正常,后期趋于平缓。mAP50-95 为 0.3921,和 mAP50 差距 0.34,定位精度是主要短板。 【模型性能评估】 Precision 0.7873、Recall 0.6713,精度高于召回,存在一定漏检。 【预测效果展示】 验证集预测效果一般,大部分目标能被检出,但存在部分漏检或框边缘贴合度不足的情况。 【改进建议】 1. 增强难例挖掘:在大规模数据中筛选误检、漏检样本做针对性增强。 2. 提升输入分辨率:640 对定位精度支撑不足,尝试 800 或 1024 改善 mAP50-95。 3. 调优 NMS 和置信度阈值:当前精召偏低,适当调整过滤阈值平衡输出质量。 【预测效果展示】

113

社区成员

发帖
与我相关
我的任务
社区描述
202401_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 助教_林日臻
  • 防震水泥
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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