這個作業屬于哪個課程 | 福大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建立庫,增加合作者,添加分支等功能都需要我去研究,我也很好地跟我的隊友規範了修改代碼和上傳代碼的事宜,分别開發前後端,讓我們一開始更新檔案不會沖突
之後我後端做完,開始一起着手前端的完善事宜,有可能出現同時修改了檔案的情況,是以再修改某個檔案前一定要先向對方确認,讓對方把自己更新的内容上傳了,我再獲得最新檔案并進行作業,這是團隊開發需要注意的問題
因為是合作開發,前後端的對接就需要更多地溝通,知道接口如何使用,這樣才能統籌好開發事宜
合作開發經常出現我這邊可以運作,對方卻無法運作的情況,這時候一定要耐心,好好調試,看看是哪一步出了問題,這樣問題才能得以解決
總的來說,這次合作開發對我收獲很大,我的隊友基礎偏弱,但是是個勤奮好學的人,我也是以很耐心的引導他,他也不負我的期待,很好地完成了任務,是一個可以依賴的隊友