• 软工实践寒假作业(2/2)


    这个作业属于哪个课程 2020春|S班 (福州大学)
    这个作业要求在哪里 寒假作业(2/2)
    这个作业的目标 开发一个疫情统计程序
    作业正文 软工实践寒假作业(2/2)
    其他参考文献 Github

    Github仓库地址

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 10 20
    Estimate 估计这个任务需要多少时间 5 5
    Development 开发 300 180
    Analysis 需求分析 (包括学习新技术) 120 240
    Design Spec 生成设计文档 30 50
    Design Review 设计复审 10 60
    Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 30
    Design 具体设计 30 30
    Coding 具体编码 30 30
    Code Review 代码复审 30 60
    Test 测试(自我测试,修改代码,提交修改) 60 60
    Reporting 报告 30 60
    Test Repor 测试报告 30 10
    Size Measurement 计算工作量 10 5
    Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 20
    合计 755 850

    解题思路描述

    阅读题目 理解题目
    发现java的知识忘得差不多了 先去网上查了点cmd运行java的资料 理解题目中的“命令”“命令行参数”“参数”是什么意思
    理解题目的需求 是对信息按规定要求的整理
    仔细理解每个要求的具体内容 保证不出错
    每个信息有他的子信息 首先想到构造结构体(java中是类的实例) 把单个省份的情况封装起来进行操作
    读取用字符串数组“命令”“命令行参数”“参数” 并按各个参数产生分支 再处理各个分支的具体工作
    发现文件中有几种固定的格式并用空格分开 想到用空格分割字符串 再按格式中关键字的前后文读出具体的信息

    实现过程

    代码说明

    读取参数

    public static void readParameter(String args[]) {
        	for(int i = 0;i<args.length;i++) {
        		if(args[i].equals("-log"))
            	path = args[i+1];
            	if(args[i].equals("-out"))
            	out = args[i+1];
            	if(args[i].equals("-date"))
                date = args[i+1];
            	if(args[i].equals("-type")) {
            		i++;
            		while(i < args.length&&args[i].charAt(0) != '-') {
            			type.add(args[i]);
            			i++;
            		}
            		i--;
            	}
            	if(args[i].equals("-province")) {
            		i++;
            		while(i < args.length&&args[i].charAt(0) != '-') {
            			province.add(args[i]);
            			i++;
            		}
            		i--;
            	}
        	}
    	}
    

    读取-path目录下的文件 在读取完-date参数对应的文件后退出 用信息中的关键字判断读入的方式

    public static void readFile(File[] tempList) throws NumberFormatException, IOException {
            if(!date.equals("")) {
        		if(tempList[tempList.length-1].getName().toString().substring(0,10).compareTo(date)<0) {
            		System.out.print("日期超出范围!");
            		System.exit(0);
            	}
        	}
        	for(int i=0;i<tempList.length;i++) {    		
        		if(tempList[i].isFile()) {
        			if(!date.equals("")) { 			
        				if(tempList[i].getName().toString().substring(0,10).compareTo(date)>0) {
        					break;		
        				}
            		}
        			BufferedReader br = new BufferedReader(  
        				     new UnicodeReader(  
        				     new FileInputStream(tempList[i]),   
        				     "UTF-8")); 
        			InputStreamReader read = new InputStreamReader(new FileInputStream(tempList[i]), "UTF-8");
                    BufferedReader reader = new BufferedReader(read);
        			String str;     			
        			while ((str = br.readLine())!= null) {
        				String[] arrays = str.split("\s+");
        				for(int j = 0;j<arrays.length;j++) {
        					Info t = new Info();					
        					switch(arrays[j]) {
        						 case "新增":
        							 t.province=arrays[j-1];							 
        							 if(list.contains(t)) {
        								 if(arrays[j+1].equals("感染患者")) {
        									 list.get(list.indexOf(t)).infected+=Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        									 all.infected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        								 }
        								 else {
        									 list.get(list.indexOf(t)).suspected+=Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        									 all.suspected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        								 } 								 
        							 }
        							 else {
        								 if(arrays[j+1].equals("感染患者")) {
        									 t.infected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
        									 all.infected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        								 }
        								 else {
        									 t.suspected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
        									 all.suspected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        								 }  
        								 
        								 list.add(t);
        							 }
        				            break;
        				         case "流入":
        				        	 Info from = new Info();
        				        	 Info to = new Info();
        				        	 from.province = arrays[j-2];
        				        	 to.province = arrays[j+1];
        							 if(list.contains(to)) {
        								 if(arrays[j-1].equals("感染患者")) {
        									 list.get(list.indexOf(from)).infected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        									 list.get(list.indexOf(to)).infected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1)); 
        								 }
        								 else {
        									 list.get(list.indexOf(from)).suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        									 list.get(list.indexOf(to)).suspected += Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
        								 }     								 
        							 }
        							 else {
        								 if(arrays[j-1].equals("感染患者")) {
        									 list.get(list.indexOf(from)).infected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        									 to.infected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
        								 }
        								 else {
        									 list.get(list.indexOf(from)).suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));
        									 to.suspected = Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1));  
        								 }   								 
        								 list.add(to);
        							 }
        				            break;
        				         case "死亡":
        							 t.province = arrays[j-1];
        							 list.get(list.indexOf(t)).infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 list.get(list.indexOf(t)).dead += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 all.infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 all.dead += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        				            break;
        				         case "治愈":
        				        	 t.province = arrays[j-1];
        				        	 list.get(list.indexOf(t)).infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 list.get(list.indexOf(t)).cured += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 all.infected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 all.cured += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        				            break;
        				         case "确诊感染":
        				        	 t.province = arrays[j-2];
        				        	 list.get(list.indexOf(t)).suspected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 list.get(list.indexOf(t)).infected += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1));   
        							 all.suspected -= Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
        							 all.infected += Integer.parseInt(arrays[j+1].substring(0,arrays[j+1].length()-1)); 
         				            break;
        				         case "排除":
        				        	 t.province = arrays[j-1];
        				        	 list.get(list.indexOf(t)).suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1)); 
        				        	 all.suspected -= Integer.parseInt(arrays[j+2].substring(0,arrays[j+2].length()-1)); 
         				            break;
        				         default:
        				            break;
        					}
        				}
        			}  			
        			reader.close();
        			br.close();
        		}
        		
        		
        	}     	
        	Collections.sort(list, new Comparator<Info>() {
    			@Override
    			public int compare(Info o1, Info o2) {
    				// TODO Auto-generated method stub
    				Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);  
    				 return com.compare(o1.province, o2.province); 
    			}
            });
    	}
    

    输出到命令行检查 写入-out路径的文件 根据-province和-type的有无判断输出和写入方式

    public static void out() throws IOException {
        	FileWriter fw = new FileWriter(out);
    		BufferedWriter fout = new BufferedWriter(fw);
        	if(province.size()>0) {
        		if(province.contains("全国")) {
        			printTypeInfo(all, type,fout);	
        		}
    			if(type.size()>0) {
    				for(int k = 0;k<province.size();k++) {
    					Info t = new Info();
    					t.province = province.get(k);
        				if(list.contains(t)) {
        					printTypeInfo(list.get(list.indexOf(t)), type, fout);
        				}
        				else {
        					printTypeInfo(t, type, fout);
        				}
        			}
    			}
    			else {
    				for(int k = 0;k<province.size();k++) {
    					Info t = new Info();
    					t.province = province.get(k);
        				if(list.contains(t)) {
        					printInfo(list.get(list.indexOf(t)), fout);
        				}
        				else {
        					printInfo(t, fout);
        				}
        			}
    			}
    		}
    		else {
    			if(type.size()>0) {
    				for(int k = 0;k<list.size();k++) {
    					printTypeInfo(list.get(k), type, fout);
        			}
    			}
    			else {
    				printInfo(all,fout);
    				for(int k = 0;k < list.size();k++) {
    					printInfo(list.get(k),fout);	
        			}
    			}
    			
    		}
        	fout.close();
    	}
    

    无法确定读入的文件的编码方式 统一在读取时去除BOM防止意外的字符

    class UnicodeReader extends Reader {   //工具类用于读取文件去除BOM
    	  PushbackInputStream internalIn;  
    	  InputStreamReader internalIn2 = null;  
    	  String defaultEnc;  
    	  
    	  private static final int BOM_SIZE = 4;   
    	  UnicodeReader(InputStream in, String defaultEnc) {  
    	     internalIn = new PushbackInputStream(in, BOM_SIZE);  
    	     this.defaultEnc = defaultEnc;  
    	  }  
    	  
    	  public String getDefaultEncoding() {  
    	     return defaultEnc;  
    	  }      
    	  public String getEncoding() {  
    	     if (internalIn2 == null) return null;  
    	     return internalIn2.getEncoding();  
    	  }      
    	  protected void init() throws IOException {  
    	     if (internalIn2!=null) return;  	  
    	     String encoding;  
    	     byte bom[] = new byte[BOM_SIZE];  
    	     int n,unread;  
    	     n = internalIn.read(bom, 0, bom.length);  
    	  
    	     if ( (bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) &&  
    	                 (bom[2] == (byte)0xFE) && (bom[3] == (byte)0xFF) ) {  
    	        encoding = "UTF-32BE";  
    	        unread = n-4;  
    	     } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) &&  
    	                 (bom[2] == (byte)0x00) && (bom[3] == (byte)0x00) ) {  
    	        encoding = "UTF-32LE";  
    	        unread = n-4;  
    	     } else if (  (bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) &&  
    	           (bom[2] == (byte)0xBF) ) {  
    	        encoding = "UTF-8";  
    	        unread = n-3;  
    	     } else if ((bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF)) {  
    	        encoding = "UTF-16BE";  
    	        unread = n-2;  
    	     } else if ((bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE)) {  
    	        encoding = "UTF-16LE";  
    	        unread = n-2;  
    	     } else {  
    	        // Unicode BOM mark not found, unread all bytes  
    	        encoding = defaultEnc;  
    	        unread = n;  
    	     }      
    	     //System.out.println("read=" + n + ", unread=" + unread);  
    	  
    	     if (unread>0)
    	    	 internalIn.unread(bom,(n-unread),unread);  
    	  
    	     // Use given encoding  
    	     if (encoding == null) {  
    	        internalIn2 = new InputStreamReader(internalIn);  
    	     } else {  
    	        internalIn2 = new InputStreamReader(internalIn, encoding);  
    	     }  
    	  }  
              public void close() throws IOException {  
    	     init();  
    	     internalIn2.close();  
    	  }  
    	  
    	  public int read(char[] cbuf,int off,int len) throws IOException {  
    	     init();  
    	     return internalIn2.read(cbuf, off, len);  
    	  }  
    	  
    }  
    

    存放信息使用的类

    class Info implements Comparable<Info>{
    	String province;
    	int infected = 0;
    	int suspected = 0;
    	int dead = 0;
    	int cured = 0;
    	@Override
    	public int compareTo(Info o) {
    		// TODO Auto-generated method stub
    		Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);  
    		 return com.compare(this.province, o.province); 
    	}
    	public boolean equals(Object o) {
    		Info t = (Info)o;
    		return this.province.equals(t.province);
    	}
    }
    

    单元测试

    log内容

    测试1

    @Test
    void test1() throws FileNotFoundException, IOException { //无参数情况
    	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output1.txt"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试2

    @Test
    void test2() throws FileNotFoundException, IOException { //省份参数无记录情况
    	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output2.txt","-province","湖南"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试3

    @Test
    void test3() throws FileNotFoundException, IOException { //带日期参数
    	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output3.txt","-date", "2020-01-21"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试4

    @Test
    void test4() throws FileNotFoundException, IOException { //带类型参数
    	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output4.txt","-type","cure"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试5

    @Test
    void test5() throws FileNotFoundException, IOException { //带多个省份参数
    	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output5.txt","-province","福建","全国"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试6

    @Test
    void test6() throws FileNotFoundException, IOException { //同时带日期和类型参数
    	String args[]= {"list", "-date", "2020-01-25", "-log", "D:/log/", "-out", "D:/output6.txt","-type","cure"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试7

    @Test
    void test7() throws FileNotFoundException, IOException { //同时带日期和省份参数
    	String args[]= {"list", "-date", "2020-01-22", "-log", "D:/log/", "-out", "D:/output7.txt","-province","福建"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试8

    @Test
    void test8() throws FileNotFoundException, IOException { //同时带日期、无记录省份、类型参数
    	String args[]= {"list",  "-log", "D:/log/", "-out", "D:/output8.txt","-type","cure","-province","福建","江苏"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试9

    @Test
    void test9() throws FileNotFoundException, IOException { //同时带日期省份类型参数
    	String args[]= {"list", "-date", "2020-01-22", "-log", "D:/log/", "-out", "D:/output9.txt","-type","sp","-province","福建"};
    	InfectStatistic.main(args);
    }
    

    结果

    测试10

    @Test
    void test10() throws FileNotFoundException, IOException { //同时带日期多个类型多个省份参数
    	String args[]= {"list", "-date", "2020-01-22", "-log", "D:/log/", "-out", "D:/output10.txt","-type","ip","dead","-province","福建","全国"};
    	InfectStatistic.main(args);
    }
    

    结果

    单元测试覆盖率及性能优化

    单元测试覆盖率
    在范例给的log基础上添加了其他的情况 增加覆盖率

    性能测试

    代码规范

    codstyle.md

    心路历程与收获

    《构建之法》中提到:关于工程师与程序员的区别是关于代码的规范程度。没读这本书之前,并不太懂软件工程的概念,只是认为软件的核心的就是代码,那么软件工程的核心就是写代码的程序员如何写好代码。在一开始的读书过程中,我颠覆了以往的观念,但后来其实想想也并无大错,其实软件工程的一系列方法,都是为了让程序员更好的去完成工作。软件这门工程,也如同盖楼一样,一个人的能力强大, 最多让某个结构更加坚固,但是软件工程着眼的是整个工程,并不简简单单局限于某个点某个面。我们所罗列的方法与思想,都是为了整个工程流程而服务的。这才是软件工程的核心所在。这次的作业虽然功能很少,但是还是花了我不少的时间。大多数时间是花在强制自己按规范操作,熟悉规范的软件开发流程。

    第一次作业中技术路线图相关的5个仓库

    java学习+面试指南
    一份涵盖大部分Java程序员所需要掌握的核心知识。帮助复习和巩固java知识,为之后的学习工作打好基础。
    HTML,CSS,and JavaScript
    最流行的HTML、CSS和JavaScript框架,用于在web上开发响应性强、移动优先的项目。
    SSM框架
    手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis。
    Java后端
    从Java基础、JavaWeb基础到常用的框架再到面试题都有完整的教程,几乎涵盖了Java后端必备的知识点。
    spring boot demo
    是一个用来深度学习并实战 spring boot 的项目。

  • 相关阅读:
    Uber Go 语言编码规范
    前端架构演进
    看完微软大神写的求平均值代码,我意识到自己还是too young了 https://mp.weixin.qq.com/s/r2nOJvviqK2bZAumNkc7g
    React v18.0 How to Upgrade to React 18
    重写历史 Rewriting History
    记一次网页内存溢出分析及解决实践
    降低了IP层的效率 根据对方给出的窗口值和当前网络的拥塞的程度决定一个报文段应包含多少个字节
    京东家庭号前端分层架构演进及赋能实践
    深入了解 Go 语言与并发编程 GMP
    BBR原理导读
  • 原文地址:https://www.cnblogs.com/tangcen/p/12327531.html
Copyright © 2020-2023  润新知