寒假作业(2/2)

寒假作业(2/2)

这个作业属于哪个课程 [2020春福大软工实践W班]
这个作业要求在哪里 [寒假作业(2/2)]
这个作业的目标 开发一个疫情统计程序
作业正文 [正文链接]
其他参考文献 ...

1. Github仓库地址。

Github仓库地址

2.PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 35
Estimate 估计这个任务需要多少时间 30 35
Development 开发 1070 1135
Analysis 需求分析 (包括学习新技术) 60 80
Design Spec 生成设计文档 30 25
Design Review 设计复审 60 55
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 35
Design 具体设计 300 350
Coding 具体编码 500 510
Code Review 代码复审 30 20
Test 测试(自我测试,修改代码,提交修改) 60 60
Reporting 报告 100 120
Test Report 测试报告 30 40
Size Measurement 计算工作量 30 40
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 40 40
合计 1200 1290

3.解题思路描述格

(1)思路

说实话,作业刚拿到手完全没有思路,最终按照 作业指引慢慢从易到难。

  • 前置要求

  • github初使用和代码规范制定

  • idea初始用

  • 总结一句:其实就是各种软件的下载注册已经再次考验英语水平(学好英语真的很重要,电脑的内存也很重要。。。

  • 分析需求

  • 首先进行命令行的读取并解析

  • 读入文件提取文件信息

  • 用正则表达式的方式进行文本处理

  • 最后将结果输出

此处输入图片的描述
(2)查找资料

  • 根据作业及其附录中的各种资料初步理解git和github
  • 查找JProfiler的使用方法进行单元测试和性能分析
  • 查找java的基本知识和一些数据结构用法,例如ArrayList,HashMap

4.设计实现过程

1.类的设计

  • InfectStatistic //总类
  • Province内部类 //存储省份信息
  • CmdArgs内部类 //解析命令行参数
  • InfectFileManager //文件处理包括读入和输出

2.全局变量

  • 存储命令行参数和参数值
  • log_path;//日志路径
  • out_path;//输出路径
  • date;//日期
  • type_list;//要求的类型(ArrayList
  • province_list;要求的省份(ArrayList
  • province_str;//存储排序好的省份(String [])

3.关键函数的流程图
此处输入图片的描述
此处输入图片的描述
4.代码说明
Province类

static class Province{
        private String name;//省份名称
        private int ip;//感染
        private int sp;//疑似
        private int cure;//治愈
        private int dead;//死亡
        /**
         * 输出结果
         * @return String
         */
        public String printResult(){
            StringBuilder result = new StringBuilder(name);
            if(type_list != null && !type_list.isEmpty()) {//type有参数
                for (String s : type_list) {
                    if (s.equals("ip")) {
                        result.append(" 感染患者").append(ip).append("人");
                    }
                    if (s.equals("sp")) {
                        result.append(" 疑似患者").append(sp).append("人");
                    }
                    if (s.equals("cure")) {
                        result.append(" 治愈").append(cure).append("人");
                    }
                    if (s.equals("dead")) {
                        result.append(" 死亡").append(dead).append("人");
                    }
                }
            }
            else {//type没有参数
                result.append(" 感染患者").append(ip).append("人").append(" 疑似患者").
                        append(sp).append("人").append(" 治愈").append(cure).append("人").
                        append(" 死亡").append(dead).append("人");
            }
            return result.toString();
        }
        /**
         * 获得对应省份在数组province_str的对应位置
         * @return int
         */
        public int getPosition() {
            int position = 0;
            for(int i  = 0; i < province_str.length; i++) {
                if(province_str[i].equals(name)) {
                    position = i;
                    break;
                }
            }
            return position;
        }
    }

代码省略了get和set的部分,printResult()函数对传入的参数type进行处理,有啥加啥,这是我最直接的想法。getPosition()函数获得对应省份在数组province_str的对应位置,因为后面的HashMap<integer,Province>是对Integer进行排序,所以直接在Province类中获取对应索引。

class CmdArgs{
        String[] args;
        /**
         * 传入命令行参数数组构造
         * @param args 命令行参数数组
         */
        CmdArgs(String[] args) {
            this.args = args;
        }
        /**
         * 获得命令行参数值
         * @return boolean
         */
        public boolean checkCmd() {
            if(!args[0].equals("list")) {
                System.out.println("错误:命令不存在");
                return false;
            }
            if(!has()) {//判断命令是否有log和out参数
                System.out.println("错误:命令缺少必要的参数");
                return false;
            }
            for(int i = 1; i < args.length; i++) {
                switch (args[i]) {
                    case "-log":
                        i = getLogPath(i);
                        if (i == -1) {
                            System.out.println("错误:日志路径有误");
                            return false;
                        }
                        ...
                        break;
                    default:
                        System.out.println("错误:未知参数");
                        return false;
                }
            }
            return true;
        }
        /**
         * 判断该命令是否有对应的必要参数
         * @return boolean
         */
        boolean has() {
            return Arrays.asList(args).contains("-log") && Arrays.asList(args).contains("-out");
        }
       ...
    }

CmdArgs类获取命令中的参数和参数值并存储在全局变量。主要是根据索引值来获取对应的参数值,并不再细说。

/**
         * 类型判断
         * @param content 日志中的内容
         * @param province_list 要求输出的省份
         * @return ArrayList<province>
         */
        public ArrayList<Province> match(String content, ArrayList<String> province_list) {
            ArrayList<Province> result = new ArrayList<>();
            if(province_list != null && !province_list.isEmpty()) {
                for(String s : province_list) {
                    Province p =new Province(s, 0, 0, 0, 0);
                    result.add(p);
                }
            }
            String pattern1 = "(\\S+) 新增 感染患者 (\\d+)人";
            String pattern2 = "(\\S+) 新增 疑似患者 (\\d+)人";
            String pattern3 = "(\\S+) 感染患者 流入 (\\S+) (\\d+)人";
            String pattern4 = "(\\S+) 疑似患者 流入 (\\S+) (\\d+)人";
                    ...
                    while (matcher1.find()) {
                        addIp(result, matcher1);
                    }
                    while (matcher2.find()) {
                        addSp(result, matcher2);
                    }
                    while (matcher3.find()) {
                        moveIp(result, matcher3);
                    }
                    while (matcher4.find()) {
                        moveSp(result, matcher4);
                    }
                    ...
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }

我将文件读取出的内容存取在string中,匹配时每读取一行匹配一行,并根据对应的方法新建对应的Province类并存入ArrayList match中。

/**
         * 省份排序
         * @param result 省份集合
         * @return HashMap<Integer, province>
         */
        private HashMap<Integer, Province> sort(ArrayList<Province> result) {
            HashMap<Integer, Province> result_map = new HashMap<>();
            int country_ip, country_sp, country_cure, country_dead;
            country_ip = country_sp = country_cure = country_dead = 0;
            for (InfectStatistic.Province province : result) {
                country_ip += province.getIp();
                country_sp += province.getSp();
                country_cure += province.getCure();
                country_dead += province.getDead();
                result_map.put(province.getPosition(), province);
            }
            Province country = new Province("全国", country_ip, country_sp, country_cure, country_dead);
            result_map.put(0, country);
            return result_map;
        }

对省份排序,我用了HashMap<Integer, Province>,Integer是对应省份的索引,Province是对应省份的疫情情况信息,map会自动按照key排序。

6.单元测试截图和描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

此处输入图片的描述

7.单元测试覆盖率优化和性能测试

  • 覆盖率
    此处输入图片的描述
  • 性能测试
    此处输入图片的描述

8.代码规范

代码规范

9.心路历程与收获

  • 刚上手的时候很绝望,所以的名词都很陌生,把作业看了一遍又一遍,最后还是根据作业的提示,从简到难,特别感谢助教的博客寒假第二次作业引导和分析,第一天真的觉得没有希望了,每天数着日子,最后还是一点一滴写出来了,感谢所有帮助我的小伙伴,也感谢自己没有放弃。噢利给!!!!
  • 收获:我能说我最大的收获是电脑内存炸了吗?不可以!!
    我觉得这次作业要学习很多新的知识,git和github的使用之类的,还有idea这个可爱的IDE,单元测试中有很多需要改进的bug,真的不是代码打完了,就完了那回事了。还有最大的收获就是自己的意志力变强了,感谢自己么的放弃。

10.技术路线图相关的5个仓库

posted @ 2020-02-18 18:59  wxy402  阅读(247)  评论(3编辑  收藏  举报