寒假作业(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初始用
总结一句:其实就是各种软件的下载注册已经再次考验英语水平(学好英语真的很重要,电脑的内存也很重要。。。
- 分析需求
- 首先进行命令行的读取并解析
- 读入文件提取文件信息
- 用正则表达式的方式进行文本处理
最后将结果输出
- 根据作业及其附录中的各种资料初步理解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 [])
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
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
*/
public ArrayList match(String content, ArrayList province_list) {
ArrayList 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
*/
private HashMap sort(ArrayList result) {
HashMap 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
6.单元测试截图和描述
7.单元测试覆盖率优化和性能测试
- 覆盖率
-
8.代码规范
代码规范
9.心路历程与收获
- 刚上手的时候很绝望,所以的名词都很陌生,把作业看了一遍又一遍,最后还是根据作业的提示,从简到难,特别感谢助教的博客寒假第二次作业引导和分析,第一天真的觉得没有希望了,每天数着日子,最后还是一点一滴写出来了,感谢所有帮助我的小伙伴,也感谢自己没有放弃。噢利给!!!!
收获:我能说我最大的收获是电脑内存炸了吗?不可以!!
我觉得这次作业要学习很多新的知识,git和github的使用之类的,还有idea这个可爱的IDE,单元测试中有很多需要改进的bug,真的不是代码打完了,就完了那回事了。还有最大的收获就是自己的意志力变强了,感谢自己么的放弃。
10.技术路线图相关的5个仓库
- Vue2全家桶仿微信App项目,支持多人在线聊天和机器人聊天
- 专为现代Web构建的基于Node .js的论坛软件
- 前端入门和进阶学习笔记,超详细的Web前端学习图文教程。
- 扩展表,用于与一些使用最广泛的CSS框架集成。
- 小型渐进式客户端HTTP请求库,以及具有相同API的Node.js模块,支持许多高级HTTP客户端功能