寒假作业(2/2)— 疫情统计
寒假作业(2/2)
这个作业属于哪个课程 | 2020春W班 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业的目标 | 构建之法、PSP表格、Github使用、疫情统计程序... |
作业正文 | .... |
其他参考文献 | ... |
一、Github仓库地址
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 15 | 20 |
Estimate | 估计这个任务需要多少时间 | 15 | 20 |
Development | 开发 | 990 | 905 |
Analysis | 需求分析 (包括学习新技术) | 180 | 200 |
Design Spec | 生成设计文档 | 60 | 30 |
Design Review | 设计复审 | 30 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 60 | 50 |
Design | 具体设计 | 120 | 130 |
Coding | 具体编码 | 360 | 325 |
Code Review | 代码复审 | 60 | 55 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 85 |
Reporting | 报告 | 90 | 95 |
Test Report | 测试报告 | 30 | 40 |
Size Measurement | 计算工作量 | 20 | 25 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 30 |
合计 | 1095 | 1020 |
三、解题思路描述
- 首先是命令行参数的识别。在CSDN上学习了相关知识:java学习之命令行参数、通过命令行传递参数。
- 其次是日志的读取。学会了读取指定文件夹内所有文件的知识:JAVA基础知识之File类。
- 再次是分析日志内容的编码。因为有些偷懒,所以没有去学习JAVA的正则表达式,写了一大堆代码。后来想想,这样反而浪费了时间,也没有学到这个知识,真的是,。
- 最后是txt文档的生成。就是先得到结果,在输出到文件。
四、设计实现过程
因为做作业的时候,时间也比较紧张了,所以并没有花心思设计几个类、几个函数。结果呢,就把代码塞到了main函数里,幸好代码量不是太多。下面就是一些示意图:
五、代码说明
1. 处理命令行参数
//得到存放各类型命令行参数的ArrayList具体值
for (int i=0;i<args.length;i++)
{
if (args[i].equals("-log")) {
logList=args[++i];
//System.out.println(logList);
logList=logList.replace('/', '\\');
//System.out.println(logList);
}
else if (args[i].equals("-out")) {
outList=args[++i];
outList=outList.replace('/', '\\');
}
else if (args[i].equals("-date")) {
dateList=args[++i];
}
else if (args[i].equals("-type")) {
for (int j=i+1;j<args.length;j++) {
if (!args[j].equals("-out")&&!args[j].equals("-date")&&
!args[j].equals("-log")&&!args[j].equals("-province"))
{
typeList.add(args[j]);
}
else
{
i=j-1;
break;
}
}
}
else if (args[i].equals("-province"))
...
}
}//获取ArrayList循环结束
2. 处理日志文件
//处理日志中的数据
for(String s:arr)
{
if (s.compareTo(dateList+".log")>0)
{
continue;
}
File afile = new File(logList+s);
Scanner sc = new Scanner(afile);
while (sc.hasNext())
{
String first=sc.next();
if (first.equals("//"))
{
sc.nextLine();
}
else
{
int index=0;
for (int i=0;i<32;i++)
{
if (first.equals(province[i]))
{
index=i;
break;
}
}
number[0][4]=1;
number[index][4]=1;
String second=sc.next();
if (second.equals("新增"))
{
String third=sc.next();
String four=sc.next();
four=four.replace("人", "");
int member=Integer.parseInt(four);
if (third.equals("感染患者"))
{
number[0][0]+=member;
number[index][0]+=member;
}
else
{
number[0][1]+=member;
number[index][1]+=member;
}
}
else if (second.equals("感染患者"))
...
}
sc.close();
}
3. 将从日志文件得到的数据转化为所需数据
//得到输出结果
ArrayList<String> result=new ArrayList<String>();
if (provinceInt.size()==0)
{
if (typeInt.size()==0)
{
for (int i=0;i<32;i++)
{
if (number[i][4]==0)
{
continue;
}
String mid=province[i]+" 感染患者"+""+number[i][0]+""+"人"+" 疑似患者"+""+number[i][1]+""+"人"
+" 治愈"+""+number[i][2]+""+"人"+" 死亡"+""+number[i][3]+""+"人\n";
result.add(mid);
}
}
else
{
for (int i=0;i<32;i++)
{
if (number[i][4]==0)
{
continue;
}
String mid=province[i];
for (int j=0;j<typeInt.size();j++)
{
if (typeInt.get(j)==0)
{
mid=mid+" 感染患者"+""+number[i][0]+""+"人";
}
else if (typeInt.get(j)==1)
...
}
mid+="\n";
result.add(mid);
}
}
}
else
{
for (int i=0;i<32;i++)
{
number[i][4]=0;
}
for (int i=0;i<provinceInt.size();i++)
{
number[provinceInt.get(i)][4]=1;
}
if(typeInt.size()==0)
{
for (int i=0;i<32;i++)
{
if (number[i][4]==0)
{
continue;
}
String mid=province[i]+" 感染患者"+""+number[i][0]+""+"人"+" 疑似患者"+""+number[i][1]+""+"人"
+" 治愈"+""+number[i][2]+""+"人"+" 死亡"+""+number[i][3]+""+"人\n";
result.add(mid);
}
}
else
...
}
六、单元测试截图和描述
由于我写代码之前没有仔细看单元测试的内容,所以把所有的代码都写到了main函数里,这就很难测试每一个代码片段了。所以写完以后,我只能修改了一下自己的代码,这样起码main函数可以得到测试结果,。
测试代码
import static org.junit.Assert.*;
import org.junit.Test;
public class InfectStatisticTest
{
@Test
public void testMain()
{
String[] test1=("list -log D:/log/ -out D:/ListOut1.txt -date 2020-01-22").split(" ");
//for(int i=0;i<test1.length;i++)
//System.out.println(test1[i]);
InfectStatistic.main(test1);
assertEquals("全国 感染患者15人 疑似患者22人 治愈2人 死亡1人\n", InfectStatistic.result.get(0));
assertEquals("福建 感染患者5人 疑似患者7人 治愈0人 死亡0人\n", InfectStatistic.result.get(1));
assertEquals("湖北 感染患者10人 疑似患者15人 治愈2人 死亡1人\n", InfectStatistic.result.get(2));
// String[] test2=("list -log D:/log/ -out D:/ListOut2.txt -date 2020-01-22 -province 福建 河北").split(" ");
// InfectStatistic.main(test2);
// assertEquals("福建 感染患者5人 疑似患者7人 治愈0人 死亡0人\n", InfectStatistic.result.get(0));
// assertEquals("河北 感染患者0人 疑似患者0人 治愈0人 死亡0人\n", InfectStatistic.result.get(1));
//
// String[] test3=("list -log D:/log/ -out D:/ListOut7.txt -date 2020-01-23 -type cure dead ip -province 全国 浙江 福建").split(" ");
// InfectStatistic.main(test3);
// assertEquals("全国 治愈4人 死亡3人 感染患者42人\n", InfectStatistic.result.get(0));
// assertEquals("福建 治愈1人 死亡0人 感染患者9人\n", InfectStatistic.result.get(1));
// assertEquals("浙江 治愈0人 死亡0人 感染患者0人\n", InfectStatistic.result.get(2));
}
}
三个测试结果截图
看起来一样,。
七、单元测试覆盖率优化和性能测试,性能优化截图和描述
单元测试覆盖率
怎么说呢,因为我是直接测试main函数,所以命令行要么带province要么不带province,要么带type要么不带type,就不能一次测试把所有情况都覆盖,难搞。
八、代码规范的链接
https://github.com/massizhi/InfectStatistic-main/blob/master/221701141/codestyle.md
九、心路历程与收获
艰辛!做这个项目,发现自己不会的太多了。原来以为在实验室做了几个项目,自己的工程能力应该不错了,结果用到的都是自己的知识盲区。比如实验室用SVN,这里用Git,虽然都是代码管理工具,学起来也十分吃力。自己比较懒,做作业的时候距离截止时间也不多了,所以做的比较匆忙。当然了,不会的东西多,学到的就多,争取对这个项目经历能做一个详细的总结吧。收获也是挺多的,比如软件工程的初步了解、Github的使用、对自己第一次作业定的目标的资料收集、Java命令行参数的获取、Java输入输出等、构建之法、单元测试等。
十、第一次作业中技术路线图相关的5个仓库
-
谷歌全新开源人工智能系统TensorFlow官方文档: TensorFlow官方文档
机器学习作为人工智能的一种类型,可以让软件根据大量的数据来对未来的情况进行阐述或预判。「TensorFlow」是 Google 多年以来内部的机器学习系统。 -
人工智能实战微信小程序demo:小程序demo
里面为很多微信小程序的demo,AI学到一定程度就可以参考demo编写自己的程序了。 -
AI-Practice-Tensorflow-Notes:Tensorflow笔记
里面为人工智能实践:Tensorflow笔记 。 -
机器学习相关教程:https://github.com/MorvanZhou/tutorials。
Python 基础
基础
多线程 threading
多进程 multiprocessing
简单窗口 tkinter
机器学习
有趣的机器学习
强化学习 (Reinforcement Learning)
进化算法 (Evolutionary Algorithm) 如遗传算法等
Tensorflow (神经网络)
PyTorch (神经网络)
Theano (神经网络)
Keras (快速神经网络)
Scikit-Learn (机器学习)
机器学习实战
数据处理
Numpy & Pandas (处理数据)
Matplotlib (绘图)
爬虫
其他
Git (版本管理)
Linux 简易教学 -
吴恩达老师的机器学习课程个人笔记: https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes。
本课程提供了一个广泛的介绍机器学习、数据挖掘、统计模式识别的课程。主题包括:
1、监督学习(参数/非参数算法,支持向量机,核函数,神经网络)。
2、无监督学习(聚类,降维,推荐系统,深入学习推荐)。
3、在机器学习的最佳实践(偏差/方差理论;在机器学习和人工智能创新过程)。
附:总结及改进
1. Github使用
参考资料:Git基础命令、Github Desktop入门、Commit message 和 Change log 编写指南、Git教程
常用命令:
git init : 在需要发送的项目的文件夹的根目录下右键【git bash here】
git add : 将本地文件增加到暂存区
git add . : 此命令表示当前目录的所有文件
git commit : 将暂存区的内容提交到本地仓库(本地分支,默认master分支),会跳出文本编辑器,可以写多行注释。
git commit -m "注释内容"
git remote add origin git@...(唯一标识符SSH):本地项目-远程项目关联
git push : 将本地仓库内容推送到远程仓库(远程分支)
git push -u origin master : 第一次发布项目
git push origin master : 非第一次发布项目
git clone git@...(唯一标识符SSH):从远程下载项目到本地
git pull :将远程仓库(远程分支)内容拉取到本地仓库(本地分支),即更新项目
git pull origin master
中间疑问
- 本地项目与远程项目关联是什么意思?
答:我的理解是两个项目有联系才能互相更新。比如:clone到本地的项目不需要建立关联,因为本身就具有联系。而本地新建的项目则需要与远程项目相关联。 - 暂存区指的是什么?
答:工作区(Working Directory)是在电脑里能看到的目录,工作区有一个隐藏目录.git,这个是Git的版本库(Repository)。Git的版本库里存放了称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。可以简单理解为,我们将需要提交的文件修改放到暂存区(add),然后,提交暂存区的所有修改到分支(commit)。 - 分支的含义?master分支是默认创建的分支吗?origin代表什么?
答:做作业时没有用到分支,只是对master有些疑惑。现在明白了,master分支是默认创建的分支,分支就像自己的另外一个版本,可以在上面修改、测试。当然,具体命令还是有点复杂的,。 master是一个本地分支,origin是默认的远程版本库名称。 - fork与pr的含义?
答:Fork:克隆别人的代码库到自己的github项目中,可以作为子模块的形式使用,或二次开发 。Pull requests (PR): Fork之后,如果希望将自己的修改贡献到原始代码中,可以使用pull requests推送请求到原来仓库中,然后原始代码的作者,根据你提交的内容,考虑是否真的放入源码中。
关于commit
Commit message 包括三个部分:Header(必需),Body(可选)和 Footer(可选)。
Header 部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。
type 用于说明 commit 的类别,只允许使用下面7个标识。
feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
test:增加测试
chore:构建过程或辅助工具的变动
scope用于说明 commit 影响的范围,subject是 commit 目的的简短描述(动词开头)。
2. 正则表达式
参考资料:菜鸟教程、这个更实用些。
正则表达式定义了字符串的模样(结构...),对于匹配字符串很好用,加上捕获组,满足了我预想的功能。为什么要把正则表达式单独拉出来,就是想提醒一下我自己。平时懒惰,晚做作业,不想学新东西,到最后还不是得补上!!!
3. 代码重构
插旗-ing