这个作业属于哪个课程 | 2020春S班-福州大学 |
---|---|
这个作业的要求在哪里 | 软工实践寒假作业(2/2) |
这个作业的目标 | 1.github的初步使用 2.代码规范的制定 3.疫情统计程序 |
作业正文 | 正文 |
其他参考文献 | 菜鸟教程,CSDN博客 |
一.作业仓库地址
仓库链接
二.构建之法阅读成果
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 60 |
Estimate | 估计这个任务需要多少时间 | 60 | 60 |
Development | 开发 | 480 | 300 |
Analysis | 需求分析 (包括学习新技术) | 120 | 150 |
Design Spec | 生成设计文档 | 30 | 50 |
Design Review | 设计复审 | 30 | 20 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 120 | 60 |
Coding | 具体编码 | 480 | 360 |
Code Review | 代码复审 | 60 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 60 | 60 |
Test Repor | 测试报告 | 60 | 60 |
Size Measurement | 计算工作量 | 30 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 25 |
三.解题思路
1.需求分析
题目要求:
- 能够在命令行运行;
- 能够读取log目录下的文件;
*能够根据正确的命令把想要的数据输出成文件
对日志文本进行分析:
日志中的-type的改变情况一共有八种。
一个省有4种-type,感染患者ip,疑似患者sp,死亡患者dead,治愈患者cure。
-type改变的情况里,一个-type改变另一个-type也会改变的情况有:
- 治愈患者增加时,感染患者减少;
- 死亡患者增加时,感染患者减少;
- 疑似患者被确诊时,感染患者增加,疑似患者减少;
- 疑似患者从省1流动到省2时,省1疑似患者减少,省2疑似患者增加;
- 感染患者从省1流动到省2时,省1感染患者减少,省2感染患者增加。
对结果文本和其相应命令进行分析:
命令有5个参数,-log和-out必有,-date只有一个,-type和-province的个数不确定。参数可能出现的情况有(只考虑指令格式正确):
- 没有-date时,-date被默认为日志中的最后一天;
- 有-date,但是-date比日志最早的日期早患者比日志最后一天晚,报错:日期超出范围;
- 有-date, 且-date在日志最早的日期和日志最后的日期之间,但是日志中没有这个日期,输出日志中最后一个比-date小的日期的数据;
- 没有-type时,输出所有-type;
- 没有-province时,输出对应-date日志中涉及的省份;
- 有-province但是当前的-province在日志中没有出现时也要输出。
拿到题目后我开始思考要给日志数据什么样的数据结构。经过分析后,我写出了如下的数据的结构:
Province //用来代表某个日期某个省份的数据
- name //省份名
- ip //感染患者人数
- sp //疑似患者人数
- cure//治愈人数
- dead//死亡人数
Lib//用来代表一个日期包含的数据,因为是在Lib类中写的,所以用Lib命名
- date//日期
- Vector
provinces //Province组成的向量,在new Lib的时候,provinces会初始化,里面有用全国各省的名字初始化的Province,并且它们按拼音排好了序
做好这些之后我开始实现功能:
首先是文件的读取
然后是对文件中读取的数据的处理
接着是数据写入文件的功能
最后是对main函数参数的处理
程序的流程图:
代码说明:
处理命令行参数的方法
//根据对应的参数标志找到mian函数参数中的数据的函数
//parament可能是-log,-out,-date,-type,-province中的一个
//args是main函数参数数组
public static String getParaments(String parament,String[] args)
{
int i=1;
//result是待返回的字符串
String result="";
//遍历args[]数组
for(;i<args.length;i++)
{
//如果args[]数组中能找到parament相等的字符串
if(args[i].contentEquals(parament)==true)
{
//那么就说明,这个字符串的下一个或者下几个是它的对应参数
for(int j=i+1;j<args.length;j++)
{
if(result.contentEquals("")==true)
result=args[j];
else result=result+" "+args[j];
if(j+1>=args.length)
{
//如果数组越界就退出循环
break;
}
else if(args[j+1].contentEquals("-log")||
args[j+1].contentEquals("-out")||
args[j+1].contentEquals("-date")||
args[j+1].contentEquals("-type")||
args[j+1].contentEquals("-province"))
{
//如果已经是别的参数标志了也退出循环
break;
}
}
}
}
//如果没有找到对应的参数标志就说明这个参数没有,用空格表示
if(result.contentEquals("")==true)
{
return " ";
}
//最后返回字符串
return result;
}
public static void main(String[] args){
//根据参数标识找到相应的数据
String log=getParaments("-log",args);
log=log.substring(0,getParaments("-log",args).length()-1);
String out=getParaments("-out",args);
String date=getParaments("-date",args);
String type=getParaments("-type",args);
String province=getParaments("-province",args);
//如果没有-log,-out就说明参数不合法
if(log.contentEquals(" ")==false&&out.contentEquals(" ")==false)
{
list(log,out,date,type,province);
}
else System.out.println("指令错误");
}
对于数据的处理,我的想法是按发生的情况的字符串长度来进行分类的,如图所示:
于是有了如下的处理情况的函数:
//处理数据的函数
public static void OpData(String data,Lib lib)
{
String[] strarray=data.split(" |人");
if(strarray.length==5)
{
//人员流动的情况
Flow(lib,strarray);
}
else if(strarray.length==4)
{
//确诊或者增长或者排除的情况
SureOrIncreaseOrMove(lib,strarray);
}
else if(strarray.length==3)
{
//治愈或者死亡的情况
CureOrDead(lib,strarray);
}
找到对应省份的函数
//在全国的省份中找到对应省份的函数,lib是日期,y是省
public static int Find(Lib lib,String[] strarray,int y)
{
for (int i=0;i<lib.provinces.size();i++)
{
Province temp=lib.provinces.get(i);
if(temp.getName().contentEquals(strarray[y])==true)
{
//如果找到就返回下标,并标识出它是当天改变的省份
temp.setIsinlog();
return i;
}
}
//找不到返回-1
return -1;
}
处理人口流动的函数
//处理人口流动情况的函数
public static void Flow(Lib lib,String[] strarray)
{
Province temp1,temp2;
int i=Find(lib,strarray,0),j=Find(lib,strarray,3);
if(i!=-1&&j!=-1)
{
temp1=lib.provinces.get(i);
temp2=lib.provinces.get(j);
if(strarray[1].contentEquals("感染患者")==true)
{
temp1.moveIp(Integer.parseInt(strarray[4]));
temp2.addIp(Integer.parseInt(strarray[4]));
}
else
{
temp1.moveSp(Integer.parseInt(strarray[4]));
temp2.addSp(Integer.parseInt(strarray[4]));
}
lib.provinces.remove(i);
lib.provinces.insertElementAt(temp1,i);
lib.provinces.remove(j);
lib.provinces.insertElementAt(temp2,j);
}
else
{
System.out.println("流入发生错误");
}
}
处理死亡或者治愈情况的函数:
//处理死亡或者治愈情况的函数
public static void CureOrDead(Lib lib,String[] strarray)
{
int i=Find(lib,strarray,0);
if(i!=-1)
{
Province temp1=lib.provinces.get(i);
Province temp2=lib.provinces.get(0);
if(strarray[1].contentEquals("死亡")==true)
{
temp1.moveIp(Integer.parseInt(strarray[2]));
temp1.addDead(Integer.parseInt(strarray[2]));
temp2.moveIp(Integer.parseInt(strarray[2]));
temp2.addDead(Integer.parseInt(strarray[2]));
}
else
{
temp1.moveIp(Integer.parseInt(strarray[2]));
temp1.addCure(Integer.parseInt(strarray[2]));
temp2.moveIp(Integer.parseInt(strarray[2]));
temp2.addCure(Integer.parseInt(strarray[2]));
}
lib.provinces.remove(i);
lib.provinces.insertElementAt(temp1,i);
lib.provinces.remove(0);
lib.provinces.insertElementAt(temp2,0);
}
else
{
System.out.println("治愈死亡发生错误");
}
}
处理确诊或者排除情况的函数
//处理确诊排除或者增长情况的函数
public static void SureOrIncreaseOrMove(Lib lib,String[] strarray)
{
int i=Find(lib,strarray,0);
if(i!=-1)
{
Province temp1=lib.provinces.get(i);
Province temp2=lib.provinces.get(0);
if(strarray[1].contentEquals("新增")==true)
{
if(strarray[2].contentEquals("感染患者")==true)
{
temp1.addIp(Integer.parseInt(strarray[3]));
temp2.addIp(Integer.parseInt(strarray[3]));
}
else
{
temp1.addSp(Integer.parseInt(strarray[3]));
temp2.addSp(Integer.parseInt(strarray[3]));
}
}
else if(strarray[1].contentEquals("排除")==true)
{
temp1.moveSp(Integer.parseInt(strarray[3]));
temp2.moveSp(Integer.parseInt(strarray[3]));
}
else
{
temp1.moveSp(Integer.parseInt(strarray[3]));
temp1.addIp(Integer.parseInt(strarray[3]));
temp2.moveSp(Integer.parseInt(strarray[3]));
temp2.addIp(Integer.parseInt(strarray[3]));
}
lib.provinces.remove(i);
lib.provinces.insertElementAt(temp1,i);
lib.provinces.remove(0);
lib.provinces.insertElementAt(temp2,0);
}
else
{
System.out.println("确诊排除增加发生错误");
}
}
四.关于单元测试
我去百度了一下单元的测试的内容,发现了需要注意的地方
然后我的函数大多数是静态方法
所以我只能写了如下的代码代为测试
public static void main(String[] args){
//根据参数标识找到相应的数据
long l=System.currentTimeMillis();
String log=getParaments("-log",args);
log=log.substring(0,getParaments("-log",args).length()-1);
String out=getParaments("-out",args);
String date=getParaments("-date",args);
String type=getParaments("-type",args);
String province=getParaments("-province",args);
//如果没有-log,-out就说明参数不合法
if(log.contentEquals(" ")==false&&out.contentEquals(" ")==false)
{
list(log,out,date,type,province);
}
else System.out.println("指令错误");
l=System.currentTimeMillis()-l;
System.out.println("程序花费了"+l+"毫秒");
}
下面是程序的运行截图
五.代码规范
相关链接
六.心路历程和收获
这次寒假让作业我学会了使用github,学会了在博客园上用markdown写博客。在写代码的过程中让我深刻地了解到了一个知识:windows地命令行地默认编码不是utf-8,eclipse地默认编码也不是utf-8,这些都需要自己设置,不设置的后果就是输出乱码。当我第一次看见输出乱码的时候很慌,一下变得很焦虑,但是当我发现怎么解决这个问题并轻松地解决这个问题之后又很有成就感。虽然在学习过程中踩了很多坑,犯了很多蠢,但战胜困难并学到东西是一件很开心的事情。
PS:老师,我是2月9号才加的微信群,错过了第一次寒假作业。