2020 winter operations (2/2) epidemic statistics

This work belongs courses 2020 W Spring classes
Where the job requires Statistics epidemic
The target job Learn to use Git, Github, learn how to do unit testing
Text of the job Text of the job
Other references "Building of the law" ...

A, GitHub repository address

GitHub

Two, PSP form

PSP2.1 Personal Software Process Stages Estimated time consuming (minutes) The actual time-consuming (minutes)
Planning plan 30 22
Estimate Estimate how much time this task requires 30 20
Development Develop 308 330
Analysis Needs analysis (including learning new technologies) 20 40
Design Spec Generate design documents 20 25
Design Review Design Review 15 26
Coding Standard Code specifications (development of appropriate norms for the current development) 12 12
Design Specific design 40 46
Coding Specific coding 135 80
Code Review Code Review 30 35
Test Test (self-test, modify the code, submit modifications) 50 80
Reporting report 32 23
Test Report testing report 10 7
Size Measurement Computing workload 8 5
Postmortem & Process Improvement Plan Later summarized, and process improvement plan 10 11
total 750 762

Third, the problem-solving ideas

First look at this question needs to accept shaped like a $ java InfectStatistic list -date 2020-01-22 -log D:/log/ -out D:/output.txtcommand, log files, get the output file.
Accordingly, program flow of solving the problem is as follows: accepting command to verify the legitimacy of the command, read the file, process the data to obtain the output file
flowchart1

1. command parsing

Command form:
$ java InfectStatistic list -date 2020-01-22 -log D:/log/ -out D:/output.txt

Parameters are as follows:

  • -log: Specify the log file path, that will bring.
  • -out: Path and file name of the output file, this will bring.
  • -province: Specifies the provinces need to be listed in the output file (optional), the log file defaults to the provinces involved.
  • -type: Infection type (Optional) Specify the output file should be listed, the default for all types of infection
  • -date: Specify date (optional), the latest date for the default log file provides.

Thus, the command parsing considered basically completed, can also determine the legality test function of the command

2. Log Files

命令解析完,就该处理输入数据了,数据存在于日志文件中。所以我们要处理数据就需要知道日志文件的结构才好对症下药。
日志文件名形如:年-月-日.log.txt,文件名中的年月日为该日志文件记录的感染变化情况的日期,故命令中提供的-date参数不应大于最新日志文件的日期。
日志文件内容形如:

福建 新增 感染患者 23人
福建 新增 疑似患者 2人
浙江 感染患者 流入 福建 12人
湖北 疑似患者 流入 福建 2人
安徽 死亡 2人
新疆 治愈 3人
福建 疑似患者 确诊感染 2人
新疆 排除 疑似患者 5人

由上,我们可以把数据行分为六种类型:新增、流入、死亡、治愈、确诊感染、排除。
我们只需建立匹配模式,对其中的行进行匹配,就能获取我们想要的数据了

flowchart2

3.输出文件

最后,我们只需按拼音排序将要求省份的要求感染类型以如下形式写进命令要求的输出文件即可

全国 感染患者22人 疑似患者25人 治愈10人 死亡2人
福建 感染患者2人 疑似患者5人 治愈0人 死亡0人
浙江 感染患者3人 疑似患者5人 治愈2人 死亡1人

四、设计实现过程

我从需求中提取出命令和文件两个类,分别负责管理命令和管理文件。
命令类CommandHandler:检验命令参数合法性,获取需要处理的日志文件列表,接受文件处理类返回的数据行,匹配模式,提取数据,统计各类型感染数据,生成数据行交给文件管理类进行写入,获得输出文件。

文件管理类FileOperator:接受命令管理类传入地路径和数据行,对文件进行读写

classchart

这个题目的结构设计的相对简单

五、代码说明

程序的主函数相对简单,从命令中获取参数、检验参数合法性、获取输出文件

if __name__=="__main__":
    if sys.argv[1]!='list':
        print('Command Error')
        exit(1)

    #获取参数
    logPath=Lib.findInformation('-log')
    outPath=Lib.findInformation('-out')
    provinceList=Lib.findInformation('-province')
    infectTypeList=Lib.findInformation('-type')
    dateList=Lib.findInformation('-date')


    if len(logPath)!=0 or len(outPath)!=0:
        print('Command Error!')
        exit(1)

    #生成命令对象
    if len(dateList)==0:
        command=Lib.CommandHandler(logPath[0],outPath[0],provinceList,
                                   infectTypeList,None)
    else:
        command=Lib.CommandHandler(logPath[0],outPath[0],provinceList,
                                   infectTypeList,dateList[0])

    #检验参数合法性
    if not command.isArgsRightful():
        print('Args Error!')
        exit(2)

    #得到输出文件
    command.getOutputFile()

以下是CommandHandler类的结构

class CommandHandler:

    def __init__(self):
        ...

    def isArgsRightful(self):
        ...

    def getOutputFile(self):
        ...

    def getStaticList(self):
        ...

    def getFileList(self):
        ...

接下来是FileOperator类的结构:

class FileOperator:

    def __init_(self):
        ...

    def writeLine(self,strArg):
        ...

    def readLine(self)
        ...

    def close(self):
        ...

和两个用于获取参数和比较日期的函数:

def findInformation(informationName):
    list=[]
    args=sys.argv
    try:
        i=args.index(informationName)+1
        while i<len(args):
            if args[i][0]!='-':
                list.append(args[i])
            else:
                break
            i+=1
    except ValueError:
        return list
    return list

#比较datestr1和datestr2的大小
def dateCompare(datestr1,datestr2):
    time1=time.mktime(time.strptime(datestr1,"%Y-%m-%d"))
    time2=time.mktime(time.strptime(datestr2,"%Y-%m-%d"))
    return time1>=time2

六、单元测试

单元测试我用了十一个测试分别对不同参数组合,和输出文件的内容进行了测试,测试函数如下:
testFunction

七、单元测试覆盖率和性能优化

  • 单元测试
    单元测试结果如图(测试文件为example中的log文件)
    unittest
    单元测试覆盖率如下:
    coverage
  • 性能优化
    在对代码进一步思考后,发现在对信息进行匹配时每个省份、每个模式、每一个数据行都进行了交叉匹配浪费了很大的资源。于是对其进行了如下的优化:省份也作为提取对象从数据行中进行提取,而不是遍历列表,每个省份都匹配一遍。如:p+' 新增 (.+) (\\d+)人'->'(.+) 新增 (.+) (\\d+)人'

八、代码规范

codestyle.md

九、心路历程和收获

心路历程

一开始拿到这个作业,看到需求我是懵逼的,各种要求、各种文档、各种格式,看的我头昏眼花。还有GitHub、仓库、PSP表格、单元测试,各种各样没有接触过的东西。还有我自己个人原因决定用自学的python语言去完成这一项目,也给我带来了一些问题。语言问题、需求问题、代码组织问题交织在一起。但当我慢慢地分析需求下来,发现这个题目还是很简单的。于是开始着手写了起来,遇到问题,查找资料、思考、重新捋清需求、组织程序结构,终于写好了整个程序的雏形。到了单元测试的时候才是硬菜,由于用的是python,由于测试方法不同于Java,只能从网上找资料写测试程序。以前没有做过程序测试,不懂得如何去做测试数据,怎么测试程序的好坏,一切都是从零开始。

收获

虽然这次的作业花了很长的时间,但收获也很大。学会了使用注册了很久但是从没用过的GitHub、以前自学的python也真正地用了起来,学会了使用Unittest。积累了一些做团队做项目地经验,虽然说只是我一个人在做。

Ten, five warehouses on Github

Architect backend map

Some back-end development issues

Front and back end development projects personal blog

Operation and maintenance notes

Linux real case columns

Guess you like

Origin www.cnblogs.com/Striker-Lin/p/12322677.html