疫情统计
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 120 | 60 |
Estimate | 估计这个任务需要多少时间 | 1680 | 1860 |
Development | 开发 | 700 | 800 |
Analysis | 需求分析 (包括学习新技术) | 120 | 90 |
Design Spec | 生成设计文档 | 60 | 80 |
Design Review | 设计复审 | 30 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 20 |
Design | 具体设计 | 60 | 30 |
Coding | 具体编码 | 400 | 600 |
Code Review | 代码复审 | 30 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 30 | 15 |
Reporting | 报告 | 40 | 60 |
Test Report | 测试报告 | 60 | 45 |
Size Measurement | 计算工作量 | 60 | 45 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 | 45 |
合计 | 1800 | 1920 |
解题思路描述
1.对程序大致构思
看完题目后,可以把内容分为大致以下几个内容:
1.要读取日志文件,所以我们需要先封装一个读取文件的类,能够将给定路径的文件信息全部传输到类的属性里。
2.要输出文件,所以我们需要封装一个用来写文件的类,该类能够得到读文件类的属性,将得到的信息全部输出到指定路径的文件中。
3.要得到命令行的参数,所以要建立一个能够解读命令行的类,将main函数中的args传给该类的属性string[] str。然后通过该类的方法对str数组进行处理以及分析,最终确定文件信息哪些该输出,哪些不该输出。
2.查阅相关资料
1.首先先确定要用什么语言来完成此次作业,我选择使用的是JAVA语言。所以我先查阅了JAVA的一些基础语法,进行相对全面的复习。
2.复习过后,就可以开始查阅这次作业需要用到的一些常用api,例如日期转成string,将日期格式化,以及日期大小的对比等,还有自定义类的sort排序等等
3.单元测试
这个部分需要编写十个以上的测试用例,我通过控制变量的方法捏造了十几个测试用例,确保我写完的程序能够大体上不出现错误。
设计实现过程
1.创建一个People类用于存储读完文件内容后的信息,该类应该从程序开始到结束一直存在。
2.创建一个Read类,用于处理日志文件,将指定路径的所有日志文件进行患者,疑似患者,治愈,死亡,以及省份的统计。
3.创建一个cmdlist类,用于处理用户输入的命令行,将用户输入的内容分解成date type以及province然后把这些数据存储在people类中。
4.创建一个write类,用于根据people类的cmd参数以及各省情况,将数据写入指定路径的指定文件当中。
5.将上述各类联系起来,构成一个完整的程序.
代码说明
主类
public static void main(String[] args) {
Cmdlist a=new Cmdlist(args);
boolean go=true;//程序运行判断
go=a.isright();
if(go==false)
return;
go=a.isrighttype();
if(go==false)
return;
go=a.isrightprovince();
if(go==false)
return;
Read b=new Read(a.main_Path,a.here,a.date);
b.getFiles();
Write c=new Write(a.out_Path,a.here);
c.writedetail(a.here.kinds,a.here.provinces);
}
Read类的构造函数和方法
public String path;
public People num;
Date now;
Read(String path,People a,Date date){
this.path=path;
this.num=a;
this.now=date;
}
Read类的获取文件方法
public void getFiles() {
String Log_Path=path;
File files = new File(Log_Path);
File[] filelist = files.listFiles();//获取目录下的所有文件
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//规范日期格式
String today = sdf.format(now);
for (int i = 0; i < filelist.length; i++) {
if (filelist[i].getName().compareTo(today+".log.txt") <= 0)
ReadLog(Log_Path + filelist[i].getName());
}
}
Read类的处理文件方法
public void ReadLog(String Log_Path) {
try {
File file = new File(Log_Path);//传入log的路径
String strline=null;//用来存储读出的一行
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8"));
while((strline=bufferedReader.readLine())!=null){//一次读一行
Dealtxt(strline);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Write类构造函数和属性
public String Path;
public People num;
Write(String out_path, People a) {
this.Path = out_path;
this.num = a;
}
Write类的写文件的方法
for(int i=0;i<num.provinces.length;i++){
if (num.provinces[i].quantify != 0) {
fw.write(num.provinces[i].name+" ");
for(int j=0;j<4;j++){
if(num.kinds[j].quantify!=0){
fw.write(num.kinds[j].name);
if (num.kinds[j].name == "感染患者")
fw.write(num.province_infectpeople[num.provinces[i].num] + "人" + " ");
else if (num.kinds[j].name == "疑似患者")
fw.write(num.province_doubtpeople[num.provinces[i].num] + "人" + " ");
else if (num.kinds[j].name == "治愈")
fw.write(num.province_curepeople[num.provinces[i].num] + "人" + " ");
else if (num.kinds[j].name == "死亡")
fw.write(num.province_deadpeople[num.provinces[i].num] + "人" + " ");
}
}
fw.write("\n");
}
}
...//其他类似
People类的属性以及构造函数
public int[] province=new int[35];
public int[] province_deadpeople=new int[35];
public int[] province_curepeople=new int[35];
public int[] province_doubtpeople=new int[35];
public int[] province_infectpeople=new int[35];
kind[] kinds=new kind[4];
province[] provinces=new province[35];
String[] province2={
"全国", "安徽", "澳门" ,"北京",
"重庆", "福建","甘肃","广东",
"广西", "贵州", "海南", "河北",
"河南", "黑龙江", "湖北", "湖南",
"吉林","江苏", "江西", "辽宁",
"内蒙古", "宁夏", "青海", "山东",
"山西", "陕西", "上海","四川",
"台湾", "天津", "西藏", "香港",
"新疆", "云南", "浙江"
};
String[] kindss={
"感染患者","疑似患者","治愈","死亡"
};
Map<String,Integer> map1=new HashMap<String, Integer>();//创建哈希表
cmdlist命令类的属性以及构造函数
public String args[];
public String main_Path;
public String out_Path;
public Date date=new Date();
String date2;
People here=new People();//记录指令指示的省份
int typenum=0;//查看type后面跟随的指令个数
int _date=0;
int _province=0;
int _type=0;
Cmdlist(String args[]) {
this.args = args;
}
cmdlist命令类的一些判断命令是否正确的函数
public boolean isrighttype(){//判断-type
boolean typeright=true;
for(int i=0;i<args.length;i++){
if(args[i].equals("-type")){
_type++;
typenum++;
if(i+1<=args.length)
typeright=dealtype(i);
else
typenum=0;
}
}
return true;
}
public boolean isrightprovince(){//判断省份
for(int i=0;i<args.length;i++){
if(args[i].equals("-province")){
_province++;
if(i+1<=args.length) {
dealprovince(i+1);
}
else{
System.out.println("-province命令必须指明省份");
return false;
}
}
}
return true;
}
...//其他类似
单元测试截图和描述
1.全部测试所用的时间以及是否成功。
#### 2.测试1,不带其余参数的输入与输出 #### 3.测试2,带-date参数并且输入正确的格式日期 #### 4.测试3,带参数-date,但不带日期,默认为当前日期 #### 5.测试4,带参数-date,但是日期格式错误,将会按照当前日期处理 #### 6.测试5,带参数-date并且日期正确,带参数-type以及ip格式正确 #### 7.测试6,带参数-date并且日期正确,带参数-type以及ip sp cure dead格式正确 #### 8.测试7,带参数-date并且日期正确,带参数-type以及ip sp cure dead格式正确,并且调换顺序 #### 9.测试8,带参数-date并且日期正确,带参数-type以及ip sp cure dead格式正确,带参数-province #### 10.测试9,带参数-date并且日期正确,带参数-type以及ip sp cure dead格式正确,带参数-province #### 11.测试10,带参数-date并且日期正确,带参数-type以及ip sp cure dead格式正确,带参数-province,并且出现日志中没有的省份 #### 12.测试11,带参数-date并且日期正确,带参数-type以及ip sp cure 格式正确,带参数-province,并且出现日志中没有的省份 #### 13.测试12,带参数-date并且日期正确,带参数-type以及ip cure 格式正确,带参数-province #### 14.测试13,带参数-date并且日期正确,带参数-type以及ip cure 格式正确,带参数-province,并且出现日志中没有的省份
单元测试覆盖率优化和性能测试
1.单元测试覆盖率
在覆盖率方面,可能是测试单元没有一部分输入错误的样例,所以覆盖率没能到百分百,但对于其他正确代码以及单元测试用例,能够基本覆盖
2.性能测试优化
在性能优化方面,我应该多考虑一些数据结构,减少循环次数,降低时间复杂度,并且减少数组的创建,降低空间复杂度
代码规范的链接
我的代码规范链接:https://github.com/An1ess/InfectStatistic-main/blob/master/221701434/codestyle.md
心路历程与收获
1.培养分析能力
此次作业刚拿到题目时,心情是复杂的,因为题目篇幅太长,细节多,第一遍看下来,看到结尾时开头的内容就都忘光了,
反正活是来了,再矛盾,也得干。于是我拿起笔和纸,将网页上的作业需求分成了好多个部分,一个部分一个部分的看,
并且认为重要的地方就用笔先写在纸上,最后通过脉络将他们联系起来,这样题目看起来就简单易懂了,没有一开始那么复杂。2.加强了我的编码能力
在完成了分析后,便开始编码,一开始不出意料,自己写了很多的bug,踩了很多的坑,也许也留了很多的坑,但是经过非常久的
学习和思考,不断地完善自己的代码,不断地减少bug,这个过程虽然是辛苦的,但却是快乐的,每一次的恍然大悟都伴随着对错误以及
知识点的重新认识,这个过程是值得记录的,是编码能力变强的点点滴滴。3.加强了我的自学能力
这次作业需要用到github desktop以及github的fork等相关操作,从来没接触过的我一开始看到要求时是头皮发麻的。
加上又是全英文的软件,一开始看不懂的地方只能慢慢的百度,等知道了github desktop大致是什么模样后开始查阅资料,
学习github的一些操作例如这次作业的commit以及ignore,经过许久的查阅以及实践,我现在对于github已经有了初步的认识
所以此次作业使我的自学能力加强了。4.加强了我的改bug能力(重要)
这次作业的最后,我通过ide传参的方式以及cmd传参的方式得到程序的结果不同,一开始找不出原因,但找了许久并没有找出来,后来通过输出读取文件的内容才发现
原来是编码格式的问题,后来修改了编码格式,cmd和ide传参的输出结果一样了,才明白有时微小的细节将会是影响整个工程的重要因素,因此注重细节,仔细找出原因
才是我们需要真正掌握的。
技术路线图相关仓库
1.java-bible
链接:https://github.com/biezhi/java-bible
简介:这里记录了一些技术摘要,部分文章来自网络,本项目的目的力求分享精品技术干货,以Java为主。
2.advanced-java
链接:https://github.com/doocs/advanced-java
简介: 互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务等领域知识,后端必看,前端也可学习。
3.technology-talk
链接:https://github.com/aalansehaiyang/technology-talk
简介:汇总java生态圈常用技术框架、开源中间件,系统架构、项目管理、经典架构案例、数据库、常用三方库、线上运维等知识。
4.CS-Notes
链接:https://github.com/CyC2018/CS-Notes
简介:技术面试必备基础知识、Leetcode 题解、后端面试、Java 面试、春招、秋招、操作系统、计算机网络、系统设计。
5.JAVAWeb-Project
链接:https://github.com/muxiao167/Heart-First-JavaWeb
简介:本仓库存放的是Java Web 入门开发教程。面向新手友好,容易上手。