天天看点

结对第二次作业——某次疫情统计可视化的实现

这个作业属于哪个课程 福大20春软工S班
这个作业要求在哪里 结对第二次作业——某次疫情统计可视化的实现
结对学号 221701113、221701128
这个作业的目标 1、实现疫情数据的可视化 2、学习github合作开发
作业正文 正文
其他参考文献 百度 CSDN博客 Echart教程 echarts实现中国地图数据展示

一、代码规范

1、代码规范

2、GitHub仓库

二、功能展示

1、地图页面

结对第二次作业——某次疫情统计可视化的实现

页面上方统计了感染患者,疑似患者,累计治愈和累计死亡四个数据,时间默认为日志文件中最晚的那天,时间可以供用户自由更改。

用户可以在下方看到感染患者与疑似患者全国的分布情况,并且根据各省人数使用不同颜色进行区分,方便用户直观的查看全国患者的分布情况,而当用户的鼠标移到对应的省份上时,会自动显示出该省份对应的省份名和患者人数,并且对应省份会高亮,而通过单击省份可以进入对应省份的详情页。

2、详情页面

结对第二次作业——某次疫情统计可视化的实现

详情页显示了对应省份的名称,并且带有感染患者,疑似患者,累计治愈和累计死亡四个数据以及相对于前一天的人数的增减,上方的日期与地图页对应,且同样支持用户的自行更改,而点击返回地图按键即可返回地图页。

在页面下方可以看到新增确诊趋势,新增疑似趋势,治愈趋势和死亡趋势四个折线图,对应四个数据在七天内的变化趋势,便于用户直观的感受疫情在各个地区的发展。

三、结对过程描述

结对第二次作业——某次疫情统计可视化的实现
结对第二次作业——某次疫情统计可视化的实现

在项目开端,经过简单的讨论就确定了分工。

结对第二次作业——某次疫情统计可视化的实现

经过一段时间的查询了解了GitHub仓库同步的方法。

结对第二次作业——某次疫情统计可视化的实现

中间出现了java类包丢失的情况,导致无法运行java类,最后重新建立项目,并对资源进行搬迁。

结对第二次作业——某次疫情统计可视化的实现

当前后端数据对接完成的时候还出现了无法读取文件的情况。

结对第二次作业——某次疫情统计可视化的实现

关于地图点击跳转的讨论

结对第二次作业——某次疫情统计可视化的实现

中间还遇到utf-8 bom文件读不到第一行数据的问题 转成utf-8即可

四、设计实现过程

本次采用Web实现疫情可视化,为此将其分为前端和后端,前端显示视图,后端进行数据运算和传递,在Eclipse上创建Dynamic Web Project,部署tomcat9.0服务器

  • 前端
    • 前端有两个页面,一个页面显示中国地图和全国的疫情数据,另一个页面则显示省份的疫情数据,并用折线图表示疫情人群的每日趋势
    • 每个页面都可以选择具体的日期,选中后,就能显示那个日期对应的疫情数据
  • 后端
    • 后端有一个servlet,当做控制器,进行传递数据和跳转的中转站,还有两个类,用于统计log文件夹内的疫情统计数据,提供必要的接口
  • 前端实现
    • 将两个页面设置成JSP,并且运用前次作业的原型,来展现前端的HTML样式中国地图采用echarts的china.js来展现
    • 中国地图采用echarts的china.js来展现,通过改变js配置参数,来实现颜色变化和省份数据显示
    • 详情页的折线图同样通过echarts的折线图来实现,横坐标对应日期,纵坐标对应数据
    • 日期选择通过input标签的date类型来实现,选择完日期后即可按提交按钮传参给后端
    • 前端涉及的页面跳转,都会传递一个flag参数给servlet,用于告诉servlet页面需要的需求是什么,点击省份还会传递province来表示省份
    • 加入index.jsp,当做web应用的启动入口,他会经过servlet显示中国地图页面
  • 后端实现
    • servlet接受参数selected(用户选择的时间),province(用户点击的省份),flag(判断要执行的操作和跳转的页面),并通过服务器读取根目录下log文件夹(存放统计文件)的路径
    • InfectMap类继承以前做过的统计疫情数据的InfectStatistic类,来提供接口
      • allStatistic (String date)方法返回一个保存某日所有省市和全国的疫情数据hashmap
      • compare(String province,String date)方法返回某个城市某日疫情数据变化的arraylist
      • latestDate()getDate()方法分别返回文件夹下统计的最新日期和最新七天的日期
结对第二次作业——某次疫情统计可视化的实现

五、代码说明

前后端信息交互控制器,通过接收的参数判断之后执行的操作,并于后端统计文件对接,获取统计文件

String flag = request.getParameter("flag");  //判断跳转信息

   	String selected = request.getParameter("selected"); //判断选择的日期

   	String province = request.getParameter("province"); //判断选择的省份

   	String abpath = getServletContext().getRealPath("/log/"); //获取web根目录下的路径
   
   	if(selected == null) 
   	
                       {
   		
                               InfectMap infect = new InfectMap();
   
   		infect.path = abpath;

   		selected = infect.latestDate(); //获取最新日期

   	}

   	else

   	{

   		InfectMap infect = new InfectMap();
   
   		infect.path = abpath;

   		selected = infect.judgeDate(selected); //判断是否超出或早于统计的日期

   	}

   	request.setAttribute("date", selected);

   	if(flag != null && flag.equals("mapStat"))  //跳转地图页面

   	{
   	
   InfectMap infect = new InfectMap();
   
   	infect.path = abpath;

   		ArrayList<String> increase = infect.compare("全国", selected);

   		request.setAttribute("increase", increase);

   		Map<String, String> stat = infect.allStatistic(selected);

   		request.setAttribute("stat", stat);

   		request.getRequestDispatcher("中国地图.jsp").forward(request, response);

   	}
   	
else if(flag != null && flag.equals("increase"))  //跳转详情页面

   	{

   		InfectMap infect = new InfectMap();
   
   		infect.path = abpath;

   		Map<String, String> stat = infect.allStatistic(selected);

   		request.setAttribute("stat", stat);

   		ArrayList<String> increase = infect.compare(province, selected);

   		request.setAttribute("increase", increase);

   		request.setAttribute("province", province);

   		ArrayList<String> allDate = infect.getDate();

   		request.setAttribute("allDate", allDate);

   		ArrayList<ArrayList<String>> allIncrease = new ArrayList<ArrayList<String>>();

   		for(int i = 0 ; i < allDate.size() ; i++)

   		{

   			ArrayList<String> dateIncrease = infect.compare(province, allDate.get(i));

   			allIncrease.add(dateIncrease);

   		}

   		request.setAttribute("allIncrease", allIncrease);

   		request.getRequestDispatcher("湖北详情页.jsp").forward(request, response);

   	}

   }

           

reading()方法将会读取日志文件并将date日期的数据统计到哈希表statistic中,将日志中没涉及到的省份初始化置0,然后调用countryStatistic()统计全国总人数,再返回这个表

public static Map<String, String> allStatistic (String date)
	/*
	 * 统计出所有省份的数据
	 */
	{
		dateTime = date;
		reading();
		String allProvin[] = {"北京","天津","河北","辽宁","吉林","黑龙江","山东","江苏","上海","浙江","安徽","福建",
						"江西","广东","广西","海南","河南","湖南","湖北","山西","内蒙古","宁夏","青海","陕西","甘肃",
						"新疆","四川","贵州","云南","重庆","西藏","香港","澳门","台湾"};
		for(int i = 0 ; i < allProvin.length ; i++)
		{
			if(!statistic.containsKey(allProvin[i] + "疑似患者"))  //检查哈希表中是否已经存在该省份的数据了
			{
				initStatistic(allProvin[i]);
			}
		}
		sortMap = sortHashkey();
		countryStatic();
		Map<String, String> sta = statistic;
		return sta;
		
	}


           

①conpare方法用于统计某个省在某一个日期的人数变化数据,judgeDate会在reading()中判定用户选择的日期是否早于最早日期,如果早于最早日期,那么变化直接为0,judgeDate设为true

②如果用户没选择日期,那么直接用文件中最新日期,否则就寻找日期对应的日志文件

③读取文件后,判定那个省份的新增、确诊、治愈、死亡,然后进行统计,放入动态数组后返回

public static ArrayList<String> compare(String province,String date) throws FileNotFoundException
	/*
	 * 统计每个省份某个日期的变化趋势
	 */
	{
		judgeDate= false;
		dateTime = date;
		reading();
		ArrayList<String> array = new ArrayList<String> ();
		for(int i = 0 ; i < 4 ; i ++)
		{
			array.add("0");
		}
		if(judgeDate) //true说明比统计文件的最早日期还早
			return array;
		
		if(date == null)
			filename = fileArray[fileArray.length - 1];
		else
		for(int i = 0 ; i < fileArray.length ; i++)
		{
			if(fileArray[i] .getName().equals(date + ".log.txt" ))
			{
				filename = fileArray[i];
				break;
			}				
		}
		
		Scanner sc  = new Scanner(filename,"UTF-8");
		fileContent = new ArrayList<String>();
		while(sc.hasNext())
		{
			String str = sc.next();
			if (str.equals("//"))
				break;
			
			else fileContent.add(str);
		}					      
		sc.close();
		
		for(int i = 0; i < fileContent.size() - 2; i++)
		{
			if(fileContent.get(i + 1).equals("新增") &&  fileContent.get(i).equals(province))  //判别新增
			{
				String str = fileContent.get(i + 3);
				str = str.substring(0 , str.length() - 1); //截取人数
				if(fileContent.get(i + 2).equals("感染患者"))
				{
					int num = Integer.parseInt(array.get(0)) + Integer.parseInt(str);
					array.set(0, String.valueOf(num));
				}
				
				else if(fileContent.get(i + 2).equals("疑似患者"))
				{
					array.set(1, str);
				}
			}
			
			else if(fileContent.get(i + 2).equals("确诊感染") &&  fileContent.get(i).equals(province)) //判别为确诊感染或排除的情况
			{
				String str = fileContent.get(i + 3);
				str = str.substring(0 , str.length() - 1); //截取人数
				int num = Integer.parseInt(array.get(0)) + Integer.parseInt(str);
				array.set(0, String.valueOf(num));
			}
			
			
			else if(fileContent.get(i + 1).equals("死亡")) //判别为死亡的情况
			{
				if(fileContent.get(i).equals(province))
				{
					String str = fileContent.get(i + 2);
					str = str.substring(0 , str.length() - 1); //截取人数
					array.set(3, str);
				}
			}
			
			else if(fileContent.get(i + 1).equals("治愈")) //判别为治愈的情况
			{
				if(fileContent.get(i).equals(province))
				{
					String str = fileContent.get(i + 2);
					str = str.substring(0 , str.length() - 1); //截取人数
					array.set(2, str);
				}
			}
		}
		
		return array;
	}


           

六、心路历程与收获

221701113:

经过这次作业可以说是从头到尾刷新了对于正常工程开发的认知,从之前完全无知的状态脱离了出来,并且更加深刻的理解了在多人合作当中,正确的代码规范和良好的沟通的重要性,在遇到的种种低级错误和基础缺失的问题上,我的队友耐心地为我讲解,使我收获认识了很多,十分的感谢,是一个难得的好队友

221701128:

此次作业需要用github进行合作开发,由于这次是我主导,所以关于github建立库,增加合作者,添加分支等功能都需要我去研究,我也很好地跟我的队友规范了修改代码和上传代码的事宜,分别开发前后端,让我们一开始更新文件不会冲突

之后我后端做完,开始一起着手前端的完善事宜,有可能出现同时修改了文件的情况,所以再修改某个文件前一定要先向对方确认,让对方把自己更新的内容上传了,我再获得最新文件并进行作业,这是团队开发需要注意的问题

因为是合作开发,前后端的对接就需要更多地沟通,知道接口如何使用,这样才能统筹好开发事宜

合作开发经常出现我这边可以运行,对方却无法运行的情况,这时候一定要耐心,好好调试,看看是哪一步出了问题,这样问题才能得以解决

总的来说,这次合作开发对我收获很大,我的队友基础偏弱,但是是个勤奋好学的人,我也因此很耐心的引导他,他也不负我的期待,很好地完成了任务,是一个可以依赖的队友