寒假作业(2/2)——疫情统计
问题 | 内容 |
---|---|
这个作业属于哪个课程 | 这个作业属于哪个课程 |
这个作业要求在哪里 | 寒假作业(2/2)——疫情统计 |
这个作业的目标 | 学习使用Github,Git等工具,学会对项目的开发进行分析 |
作业正文 | 作业2 |
其他参考文献 | 无 |
1.Github仓库地址
我的Github仓库地址:https://github.com/takeyouhomeaa/InfectStatistic-main
2.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 60 | 70 |
Estimate | 估计这个任务需要多少时间 | 1970 | 2025 |
Development | 开发 | 1130 | 1135 |
Analysis | 需求分析 (包括学习新技术) | 60 | 75 |
Design Spec | 生成设计文档 | 60 | 55 |
Design Review | 设计复审 | 30 | 35 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 20 |
Design | 具体设计 | 120 | 130 |
Coding | 具体编码 | 800 | 830 |
Code Review | 代码复审 | 30 | 40 |
Test | 测试(自我测试,修改代码,提交修改) | 150 | 130 |
Reporting | 报告 | 240 | 230 |
Test Report | 测试报告 | 60 | 40 |
Size Measurement | 计算工作量 | 30 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 300 | 350 |
合计 | 1910 | 1955 |
方法
/**
String[] commands 存有输入的命令
String command 存放命令行参数
List
1.判断第一个参数是否是list
2.遍历数组,判断数组数组的元素是否是存储在ListCommand.command的命令行参数
3.如果是,把该元素赋值给command,不是存于params中
4.command值改变前,以及循环次数到数组的长度时,把command ,params以键值对的方式存与listCommand.listMap中
5.
**/
public void commandAnalyze(String[] commands) throws CommandErrorException {
if (!InfectStatistic.commands.contains(commands[0])) {
throw new CommandErrorException();
}
if ("list".equals(commands[0])) {
String command = "";
List
int i;
for (i = 1; i <= commands.length; i++) {
if (i == commands.length) {
if (params.isEmpty()) {
throw new CommandErrorException();
}
listCommand.listMap.put(command, params);
break;
}
if (commands[i].charAt(0) == '-' && !ListCommand.command.contains(commands[i])) {
throw new CommandErrorException();
}
if (!commands[i].equals(command) && !"".equals(command) && ListCommand.command.contains(commands[i])) {
if (params.isEmpty()) {
throw new CommandErrorException();
}
listCommand.listMap.put(command, params);
params = new ArrayList<>();
}
if (ListCommand.command.contains(commands[i])) {
command = commands[i];
} else {
params.add(commands[i]);
}
}
}
}
/**
1.获取-log所带的值
2.判断命令是否带有-date参数,有则以date参数所带的值组合成绝对路径,否则以最新日期组合成绝对路径
3.通过-log 带的值获得日志所有日志的绝对路径
4.根据date所带的值或者最新日期,获得小于等于该日期的所有日志文件的绝对路径
5.遍历日志文件,对每个日志文件按行读取提取省份、状态、人数存储到province集合中
6.根据传递的命令行参数不同,组合存储信息
7.输出文件
**/
public void fileRead(String[] commands) throws IOException {
String input = listCommand.listMap.get("-log").get(0);
String tempString = "";
if (listCommand.listMap.containsKey("-date")) {
String date = listCommand.listMap.get("-date").get(0);
input += "\" + date + ".log.txt";
} else {
input += "\" + getTheLatestDate() + ".log.txt";
}
getFiles(listCommand.listMap.get("-log").get(0));
List
for (String fileName : loadFiles) {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
while ((tempString = reader.readLine()) != null) {
stringProcessing(tempString);
}
reader.close();
}
updateCountry();
if (!listCommand.listMap.containsKey("-type") && !listCommand.listMap.containsKey("-province")) {
stringSynthesis(new ArrayList<>(), new ArrayList<>());
} else if (listCommand.listMap.containsKey("-type") && !listCommand.listMap.containsKey("-province")) {
List<String> typeParams = listCommand.listMap.get("-type");
stringSynthesis(typeParams, new ArrayList<>());
} else if (!listCommand.listMap.containsKey("-type") && listCommand.listMap.containsKey("-province")) {
List<String> provinceParams = listCommand.listMap.get("-province");
stringSynthesis(new ArrayList<>(), provinceParams);
} else {
List<String> typeParams = listCommand.listMap.get("-type");
List<String> provinceParams = listCommand.listMap.get("-province");
stringSynthesis(typeParams, provinceParams);
}
logOutput();
reset();
}
/**
1.把传递进来的日志的一行和对应正则表达式进行匹配
2.匹配成功获取该行中的省份、状态、人数,并把对应province集合中对应省份的flag值变为0
3.把province集合中对应省份的数据提取出来,根据日志现实意义进行数据更新
4.把更新后的数据存回province集合中
**/
public void stringProcessing(String ch) {
String pro = "";
String pro1 = "";
String state = "";
int temp = 0;
int num = 0;
String regex = "(\S+) 新增 (\S\S\S\S) (\d+)人";
String regex2 = "(\S+) (\S+) 流入 (\S+) (\d+)人";
String regex3 = "(\S+) (\S+) (\d+)人";
String regex4 = "(\S+) (\S+) 确诊感染 (\d+)人";
String regex5 = "(\S+) 排除 (\S+) (\d+)人";
if (ch.matches(regex)) {
pro = getPro(ch, 0);
num = getNum(ch);
state = getState(ch, 2);
Map<String, Integer> tempMap = province.get(pro);
tempMap.put("flag", 0);
temp = tempMap.get(state) + num;
tempMap.put(state, temp);
} else if (ch.matches(regex2)) {
pro = getPro(ch, 0);
pro1 = getPro(ch, 3);
num = getNum(ch);
state = getState(ch, 1);
Map<String, Integer> tempMap = province.get(pro);
tempMap.put("flag", 0);
temp = tempMap.get(state) - num;
tempMap.put(state, temp);
tempMap = province.get(pro1);
tempMap.put("flag", 0);
temp = tempMap.get(state) + num;
tempMap.put(state, temp);
} else if (ch.matches(regex3)) {
pro = getPro(ch, 0);
state = getState(ch, 1);
num = getNum(ch);
Map<String, Integer> tempMap = province.get(pro);
tempMap.put("flag", 0);
temp = tempMap.get(state) + num;
tempMap.put(state, temp);
temp = tempMap.get("感染患者") - num;
tempMap.put("感染患者", temp);
} else if (ch.matches(regex4)) {
pro = getPro(ch, 0);
state = getState(ch, 1);
num = getNum(ch);
Map<String, Integer> tempMap = province.get(pro);
tempMap.put("flag", 0);
temp = tempMap.get(state) - num;
tempMap.put(state, temp);
temp = tempMap.get("感染患者") + num;
tempMap.put("感染患者", temp);
} else if (ch.matches(regex5)) {
pro = getPro(ch, 0);
state = getState(ch, 2);
num = getNum(ch);
Map<String, Integer> tempMap = province.get(pro);
tempMap.put("flag", 0);
temp = tempMap.get(state) - num;
tempMap.put(state, temp);
}
}
/**
1.如果命令中带有-province,先把所有省份的flag值改为-1,把-province所带的省份对应的flag改为1
2.如果有带-type参数,则按照对应参数从province中取值
3.否则,全部输出;
**/
public void stringSynthesis(List
if (!countryParams.isEmpty()) {
for (int i = 0; i < 32; i++) {
province.get(provinces[i]).put("flag", -1);
}
for (String param : countryParams) {
province.get(param).put("flag", 0);
}
}
if (typeParams.isEmpty()) {
for (String key : province.keySet()) {
StringBuffer tempString = new StringBuffer();
Map<String, Integer> map = province.get(key);
if (map.get("flag") == -1) {
continue;
} else {
tempString.append(key + " ");
for (String ch : map.keySet()) {
if (!"flag".equals(ch)) {
tempString.append(ch);
tempString.append(map.get(ch) + "人 ");
}
}
result.add(tempString.toString().trim());
System.out.println(tempString.toString().trim());
}
}
} else {
for (String key : province.keySet()) {
StringBuffer tempString = new StringBuffer();
Map<String, Integer> map = province.get(key);
if (map.get("flag") == -1) {
continue;
} else {
tempString.append(key + " ");
for (String param : typeParams) {
if ("ip".equals(param)) {
tempString.append("感染患者");
tempString.append(map.get("感染患者") + "人 ");
} else if ("sp".equals(param)) {
tempString.append("疑似患者");
tempString.append(map.get("疑似患者") + "人 ");
} else if ("cure".equals(param)) {
tempString.append("治愈");
tempString.append(map.get("治愈") + "人 ");
} else if ("dead".equals(param)) {
tempString.append("死亡");
tempString.append(map.get("死亡") + "人 ");
}
}
result.add(tempString.toString().trim());
System.out.println(tempString.toString().trim());
}
}
}
result.add("// 该文档并非真实数据,仅供测试使用");
}
# 6.单元测试截图和描述
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215142442QQ%E5%9B%BE%E7%89%8720200215222354.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215142555QQ%E5%9B%BE%E7%89%8720200215222542.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215142728QQ%E5%9B%BE%E7%89%8720200215222714.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144059QQ%E5%9B%BE%E7%89%8720200215224022.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144210QQ%E5%9B%BE%E7%89%8720200215223837.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144256QQ%E5%9B%BE%E7%89%8720200215223841.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144305QQ%E5%9B%BE%E7%89%8720200215223844.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144311QQ%E5%9B%BE%E7%89%8720200215223847.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144321QQ%E5%9B%BE%E7%89%8720200215223852.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144328QQ%E5%9B%BE%E7%89%8720200215223855.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144520QQ%E5%9B%BE%E7%89%8720200215223908.png)
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215144524QQ%E5%9B%BE%E7%89%8720200215223913.png)
# 7.单元测试覆盖优化和性能测试
* 代码覆盖率分析
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215145445QQ%E5%9B%BE%E7%89%8720200215225426.png)
> 覆盖率达到预期
* 性能分析
> ![图片](https://images.cnblogs.com/cnblogs_com/Ozgblog/1639679/o_200215160645QQ%E5%9B%BE%E7%89%8720200216000623.png)
# 8.代码规范
> 我的代码规范:https://github.com/takeyouhomeaa/InfectStatistic-main/blob/master/221701227/codestyle.md
# 9.心路历程与收获
1. 通过这次作业,了解了开发一个项目有许多流程,不仅仅是编程。
2. 学会了单元测试,也明白了单元测试的重要性。
3. 学习了GitHub、Git工具的使用
4. 发现许多不足,需要继续努力学习
# 10.技术相关的五个仓库
| 库 | 简介 |
| ---- | ---- |
| Spring Framework | Spring框架的源代码库 |
| spring-analysis | Spring框架源码阅读 |
| SpringBoot-Learning | SpringBoot基础教程 |
| JavaEETest | Spring、SpringMVC、MyBatis、Spring Boot案例 |
| SpringMvcStepByStep | SpringMVC基础教程 |