1. Github地址
github仓库
2. PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) | 
| Planning | 计划 | 30 | 25 | 
| Estimate | 估计这个任务需要多少时间 | 1760 | 1855 | 
| Development | 开发 | 450 | 400 | 
| Analysis | 需求分析 (包括学习新技术) | 350 | 400 | 
| Design Spec | 生成设计文档 | 50 | 40 | 
| Design Review | 设计复审 | 20 | 20 | 
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 15 | 
| Design | 具体设计 | 150 | 170 | 
| Coding | 具体编码 | 500 | 540 | 
| Code Review | 代码复审 | 20 | 40 | 
| Test | 测试(自我测试,修改代码,提交修改) | 60 | 75 | 
| Reporting | 报告 | 40 | 70 | 
| Test Report | 测试报告 | 30 | 30 | 
| Size Measurement | 计算工作量 | 10 | 10 | 
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 20 | 
| 合计 |  | 1760 | 1855 | 
3. 思路描述
看到题目之后,因为我们传入的命令参数会被存在main函数的args[]数组里,所以第一想法是对args[]数组里的命令参数进行识别,对于-type和-province这种有多个参数的另外设计方法去获取其参数。然后就是对要读取的日志的各种信息的提取,我使用java正则去获取,对于这些信息的保存我创建了province类去保存。
4. 流程图
| main函数分析命令参数 | 
|  | 
| 读取日志 | 
|  | 
| 输出文件 | 
|  | 
5. 代码说明
- 开发语言:Java
- JDK版本:1.8
- 开发环境:IDEA
 class Province implements Comparable<Province>`
 {
    private String province;
    private int ip = 0,sp = 0,cure = 0,dead = 0;
    public Province(String province)
    {
        this.province = province;
    }
 public int compareTo(Province a)
    {
        String province1 = this.province;
        String province2 = a.province;
        Collator instance = Collator.getInstance(Locale.CHINA);
        if(province1.indexOf("重") >= 0){
            province1 = province1.replaceAll("重", "冲");//多音字重chong庆
        }
        if(province2.indexOf("重") >= 0){
            province2 = province2.replaceAll("重", "冲");
        }
        if(province1.equals("全国")) return -1; // 全国排第一
        else if(province2.equals("全国")) return 1;
        return instance.compare(province1,province2);  //按拼音排序
    }
 for(int j = 0;j < args.length;j++) {
            if(args[j].equals("list")) listjudge1++;
            else if(args[j].equals("-log"))
            {
                log = args[j + 1 ];
                listjudge1++;
            }
            else if(args[j].equals("-out"))
            {
                out = args[j + 1];
                listjudge1++;
            }
            else if(args[j].equals("-date")) date = args[j + 1];
            else if(args[j].equals("-type"))
            {
                listjudge3 = 1;
                addtype(args,j,outinformation);
            }
            else if(args[j].equals("-provence"))
            {
                listjudge2 = 1;
                addprovence(args,j,proinformation,proList);
            }
        }
        if(listjudge1!=3||(listjudge2==0&&!proinformation.isEmpty())||(listjudge2==1&&proinformation.isEmpty())
        ||(listjudge3==0&&!outinformation.isEmpty())||(listjudge3==1&&outinformation.isEmpty()))
        {
            System.out.println("命令错误");
            System.exit(0);
        }
  public static void getAllFileName(String path,ArrayList<String> listFileName) //得到日志名字
    {
        String patterndate = "\\d+-\\d+-\\d+";
        Pattern date = Pattern.compile(patterndate); // 创建 Pattern 对象
        File file = new File(path);
        String [] names = file.list();
        if(names != null){
            String [] completNames = new String[names.length];
            for(int i=0;i < names.length;i++){
                Matcher Date = date.matcher(names[i]); // 创建 matcher 对象
                if(Date.find()) completNames[i] = Date.group(0);
            }
            listFileName.addAll(Arrays.asList(completNames));
        }
    }
  for(String name:listFileName)
        {
            if(date==null)
            {
                InformationProcessing(log+name+".log.txt",proList,allpro);
                continue;
            }
            else if(listFileName.get(listFileName.size()-1).compareTo(date)<=0) //若输入的日期超出最新的日志范围
            {
                System.out.println("输入的日期有错");
                System.exit(0);
            }
            else if (listFileName.get(0).compareTo(date) > 0) break; //若输入日期小于最旧的日志
            else if(name.compareTo(date) > 0) break;
            InformationProcessing(log+name+".log.txt",proList,allpro);
        }
  public static void InformationProcessing(String Path,List<Province> proList,Province allpro) //日志信息处理
    {
        int people;
        String pattern = ".*//.*";
        String pattern0 = "(\\d+)";
        String pattern0_1 = ".*感染患者.*";
        String pattern0_2 = ".*疑似患者.*";
        String pattern1 = ".*新增.*";
        String pattern2 = ".*流入.*";
        String pattern3 = ".*死亡.*";
        String pattern4 = ".*治愈.*";
        String pattern5 = ".*确诊感染.*";
        String pattern6 = ".*排除.*";
        Pattern number = Pattern.compile(pattern0); // 创建 Pattern 对象
        try
        {
            File file = new File(Path);
            if(!file .exists())
            {
                System.out.println("路径错误");
                System.exit(0);
            }
            BufferedReader br = new BufferedReader(new FileReader(file));
            String str = null;
            while ((str = br.readLine()) != null)
            {
                Matcher num = number.matcher(str); // 现在创建 matcher 对象
                String arrays[] = str.split(" ");
                if(Pattern.matches(pattern,str)) continue; // 跳过注释内容
                addlist(arrays[0],proList);
                for (Province province1 : proList) {
                    if (arrays[0].equals(province1.getprovince())&&num.find())
                    {
                        people = Integer.valueOf(num.group(0));
                        if(Pattern.matches(pattern1,str)) // 新增
                        {
                            if(Pattern.matches(pattern0_1,str)) // 新增感染患者
                            {
                                province1.setip(province1.getip() + people);
                                allpro.setip(allpro.getip() + people);
                            }
                            else if(Pattern.matches(pattern0_2,str)) //新增疑似患者
                            {
                                province1.setsp(province1.getsp() + people);
                                allpro.setsp(allpro.getsp() + people);
                            }
                        }
                        else if(Pattern.matches(pattern2,str)) //从省一流入省二
                        {
                            addlist(arrays[3],proList); //判断省二有没有在列表里边
                            for (Province province2 : proList) {
                                if (arrays[3].equals(province2.getprovince()))
                                {
                                    if(Pattern.matches(pattern0_1,str))
                                    {
                                        province1.setip(province1.getip() - people);
                                        province2.setip(province2.getip() + people);
                                    }
                                    else if(Pattern.matches(pattern0_2,str))
                                    {
                                        province1.setsp(province1.getsp() - people);
                                        province2.setsp(province2.getsp() + people);
                                    }
                                }
                            }
                        }
                        else if(Pattern.matches(pattern3,str)) //死亡 dead+n,ip-n
                        {
                            province1.setdead(province1.getdead() + people);
                            province1.setip(province1.getip() - people);
                            allpro.setdead(allpro.getdead() + people);
                            allpro.setip(allpro.getip() - people);
                        }
                        else if(Pattern.matches(pattern4,str)) //治愈 cure+n,ip-n
                        {
                            province1.setcure(province1.getcure() + people);
                            province1.setip(province1.getip() - people);
                            allpro.setcure(allpro.getcure() + people);
                            allpro.setip(allpro.getip() - people);
                        }
                        else if(Pattern.matches(pattern5,str)) //确诊感染 sp-n,ip+n
                        {
                            province1.setip(province1.getip() + people);
                            province1.setsp(province1.getsp() - people);
                            allpro.setip(allpro.getip() + people);
                            allpro.setsp(allpro.getsp() - people);
                        }
                        else if(Pattern.matches(pattern6,str)) //排除 sp-n
                        {
                            province1.setsp(province1.getsp() - people);
                            allpro.setsp(allpro.getsp() - people);
                        }
                    }
                }
            }
        } catch (IOException  e) {
            e.printStackTrace();
        }
    }
| 有两个对象数组若有指定provence则输出proinformation对象数组 | 
        for(Province province : proList)
        {
            for(Province pro : proinformation)
            {
                if(province.getprovince().equals(pro.getprovince()))
                {
                    pro.setip(province.getip());
                    pro.setsp(province.getsp());
                    pro.setcure(province.getcure());
                    pro.setdead(province.getdead());
                }
            }
        }
        Collections.sort(proList);
        Collections.sort(proinformation);
        if(listjudge2==1) InformationOut(out,proinformation,outinformation);
        else InformationOut(out,proList,outinformation);
    public static void InformationOut(String out,List<Province> proList,List<String> outinformation) //写出日志信息
    {
        out = out.trim();
        String Path = out.substring(0,out.lastIndexOf("\\")); //分离得到路径
        try {
            File file = new File(Path);
            if (!file.exists())
            {
                System.out.println("路径错误");
                System.exit(0);
            }
            BufferedWriter wr = new BufferedWriter(new FileWriter(out));
            for (Province province : proList)
            {
                if (outinformation.isEmpty())
                {
                    wr.write(province.getprovince() + "共有感染患者" + province.getip() + "人 疑似患者" +province.getsp()
                            + "人 治愈" + province.getcure() + "人 死亡" + province.getdead() + "人\n");
                }
                else
                {
                    wr.write(province.getprovince() + "共有");
                    for (String outthing : outinformation)
                    {
                        if(outthing.equals("ip"))  wr.write("感染患者" + province.getip() + "人 ");
                        if(outthing.equals("sp")) wr.write("疑似患者" + province.getsp() + "人 ");
                        if(outthing.equals("cure")) wr.write("治愈" + province.getcure() + "人 ");
                        if(outthing.equals("dead")) wr.write("死亡" + province.getdead() + "人 ");
                    }
                    wr.write("\n");
                }
            }
            wr.write("// 该文档并非真实数据,仅供测试使用");
            wr.flush();
            wr.close();
        }catch (IOException  e) {
            e.printStackTrace();
        }
    }
6. 单元测试
7. 代码覆盖率


8. 性能分析

9. 我的命名规范
我的命名规范
10. 我的心路历程
一开始也是有的虚的,毕竟我自我感觉我的基础其实不是那么牢靠,而这次作业又是老长一条作业文档,需求也多,怕自己无法完成。
同时像GitHub,单元测试之类也是之前自己未有接触的事物。因而这次作业给我的压力也是挺大的。
所以我不再是赖到快交作业才开始做的学生了,这次我早早的开始作业2的旅途,自学各种作业需求的东西到,慢慢的就大概摸索出个所以然来了。
因为我的舍友都是另一个老师的班的,他们作业比我要晚交。结果就是这次我居然成了先行军,为他们说github之类的时候,我的理解也就慢慢深刻起来。
直到最后我完成了这份作业。感觉有种克服艰难险阻的快感!
11. 5个仓库