這個作業屬於哪個課程 |
|
---|---|
這個作業要求在哪里 |
|
結對學號 |
|
這個作業的目標 |
|
作業正文 |
|
其他參考文獻 |
|
一、Github 倉庫地址和代碼規范鏈接
- Github倉庫地址:https://github.com/theguiltyperson/InfectStatisticWeb/tree/hmx
- 代碼規范鏈接:https://github.com/theguiltyperson/InfectStatisticWeb/blob/master/codestyle.md
二、成品演示
-
地圖上方提供日歷,可以選取不同日期查看截止該日全國疫情情況
-
統計數據在地圖上方,只顯示到助教提供的靜態文件最后一個日期
相同感染人數區間的省份可以通過左下方鼠標停留或點擊
-
全國疫情折線圖在地圖下方,可選擇顯示或隱藏確診,疑似,治愈,死亡四條折線
折線上的點顯示當前日期的疫情數據
-
地圖上點擊不同省份會跳轉到該省份疫情數據的折線圖
三、結對討論過程描述
- 作業發布當天晚上,由於技術不足無法實現實時數據更新,我們決定用javeEE課上學的JSP框架和數據庫完成本次作業
四、描述設計實現過程
221701429-前端
-
作業題目有提示用echarts設計圖表,就跟着學了echarts的教程,下載了文件,
在前端用jsp的方式實現頁面,在頁面中加入script,添加圖表,設置圖表的類型和參數,就能夠顯示出來了。
數據部分則是通過Servlet的http請求獲取的,把數據庫中的表的數據實例化成Province后,通過req.setAttribute的方式傳遞參數。
在地圖上設置了點擊事件,將params加到url上傳遞給Servlet判斷,點擊后跳轉到具體省份的疫情的功能就實現了。
221701438-后端
-
與前端交流后,確定我的主要任務是對log文件夾下的日志進行處理,再將日志中數據寫入數據庫,完善疫情數據的讀取和存儲。
結合之前所學,我將每個省份的疫情情況封裝在Province類,把助教提供的靜態日志內容讀取出來,存儲在ArrayList<Province>
再用正則匹配將每個省的疫情數據提取並寫入數據庫,然后完善數據庫的存取。
五、關鍵代碼
- Jsp頁面通過http請求獲得Servlet傳的數據,用div的方式顯示出來,在css中更改樣式使得四塊橫向排版。
<div id="virusSummary">
<%
int totalip = (int) request.getAttribute("totalip");
int totalsp = (int) request.getAttribute("totalsp");
int totalcure = (int) request.getAttribute("totalcure");
int totaldead = (int) request.getAttribute("totaldead");
%>
<div id="ip">
<div class="name">確診</div>
<div class="data"><%=totalip%></div>
</div>
<div id="sp">
<div class="name">疑似</div>
<div class="data"><%=totalsp%></div>
</div>
<div id="cure">
<div class="name">治愈</div>
<div class="data"><%=totalcure%></div>
</div>
<div id="dead">
<div class="name">死亡</div>
<div class="data"><%=totaldead%></div>
</div>
</div>
- 這是用echarts實現疫情地圖的script,tooltip改變數據提示框的輸出格式,visualMap改變確診人數區間對應的顏色提示,series里data部分填入http請求得到的確診人數數據,然后顯示到地圖上。再添加一個function點擊事件,點擊省份后跳轉到該省份的疫情折線圖的頁面。
<div id="chinaMap"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('chinaMap'));
myChart.setOption({
// 數據提示框
tooltip: {
trigger: 'item', // item放到數據區域觸發
formatter: '地區:{b}<br/>確診:{c}' // 提示數據格式br表示換行,地圖 : {a}(系列名稱),{b}(區域名稱),{c}(合並數值), {d}(無)
},
// 工具欄
/*toolbox: {
show: true,
orient: 'horizontal',
left: 'right',
feature: {
dataView: {readOnly: false},
restore: {},
saveAsImage: {}
}
},*/
// 使用透明度來區分疫情嚴重情況
visualMap: {
type: 'piecewise',
pieces: [
{gt: 1500, color: 'darkred'},
{gt: 1000, lte: 1500, color: 'red', colorAlpha: 1},
{gt: 500, lte: 1000, color: 'red', colorAlpha: 0.8},
{gt: 300, lte: 500, color: 'red', colorAlpha: 0.6},
{gt: 100, lte: 300, color: 'red', colorAlpha: 0.4},
{gt: 50, lte: 100, color: 'red', colorAlpha: 0.3},
{gt: 0, lte: 50, color: 'red', colorAlpha: 0.2},
{lte: 0, color: 'white'}
],
},
// 具體數據
series: [
{
name: '各省確診病例', // 系列名稱
type: 'map', // 系列類型,地圖
map: 'china', // 要使用的地圖,即上面注冊的地圖名稱
//roam: true, // 開啟鼠標縮放和平移漫游
label: { // 圖形上的文本標簽,地圖默認顯示數據名
show: true,
formatter: '{b}', // b是數據名,c是數據值
fontSize: 12
},
data:[
<%
int Ip;
for(int i = 0; i < ProvinceName.provinceSize; i++){
//ip = 0;
Ip = (int) request.getAttribute(ProvinceName.provinceName[i] + "Ip");
%>
{name: "<%=ProvinceName.provinceName[i]%>", value: "<%=Ip%>"},
<%}%>
]
}
]
});
//點擊省份后跳轉到具體疫情的頁面
myChart.on("click",function (params) {
window.location.href = "Servlet?flag=2&name="+params.name;
},true)
</script>
- 該部分顯示的是全國四種人數的折線圖,用echarts定制的折線圖樣式,將獲取的日期作為xAxis的數據、四種人數作為每個點的值,實現折線圖。點擊省份進入具體頁面的折線圖與之類似。
<div id="lineChart" style="width: 800px;height:400px; position: center; background-color: #ffffff; padding-top: 40px"></div>
<script type="text/javascript">
var name = "全國";
// 基於准備好的dom,初始化echarts實例
var Chart = echarts.init(document.getElementById('lineChart'),'infographic');
Chart.setOption({
//設置標題
title: {
text: name + '疫情趨勢'
},
//數據提示框
tooltip: {
trigger: 'axis',
},
legend: {
data: ['確診','疑似','治愈','死亡']
},
xAxis: {
data:[<%
List<Province> country = (List<Province>) request.getAttribute("country");
String date;
int ip,totalIp = 0;
int sp,totalSp = 0;
int cure,totalCure = 0;
int dead,totalDead = 0;
for(Province province : country){
date = province.getDate();
%>
"<%=date%>",
<%}%>]
},
yAxis: {},
series: [
{
name: '確診',
type: 'line',
data:[<%
for(Province province : country){
ip = province.getIp();
totalIp += ip;
%>
<%=totalIp%>,
<%}%>]
},
{
name: '疑似',
type: 'line',
data:[<%
for(Province province : country){
sp = province.getSp();
totalSp += sp;
%>
<%=totalSp%>,
<%}%>]
},
{
name: '治愈',
type: 'line',
data:[<%
for(Province province : country){
cure = province.getCure();
totalCure += cure;
%>
<%=totalCure%>,
<%}%>]
},
{
name: '死亡',
type: 'line',
data:[<%
for(Province province : country){
dead = province.getDead();
totalDead += dead;
%>
<%=totalDead%>,
<%}%>]
}
]
},true)
</script>
- Servlet控制前后端數據交互,調用對象類實例化,將參數通過http請求發送給下一個頁面,通過url附帶參數的形式,在Servlet中獲取參數並判斷選擇進入的頁面。
String flag = req.getParameter("flag");
ProvinceDAO provinceDAO =new ProvinceDAOImpl();
//flag=2時跳轉到第二個頁面
if(flag != null && flag.equals("2")){
String name = req.getParameter("name");
provinceDAO =new ProvinceDAOImpl();
List<Province> local = provinceDAO.list(name,true);//獲取當地每天數據
int ip = 0,sp = 0,cure = 0,dead = 0;
//累加當地每天的數據
for (Province province : local) {
ip += province.getIp();
sp += province.getSp();
cure += province.getCure();
dead += province.getDead();
}
req.setAttribute("name",name);
req.setAttribute("totalip",ip);
req.setAttribute("totalsp",sp);
req.setAttribute("totalcure",cure);
req.setAttribute("totaldead",dead);
req.setAttribute("local",local);
req.getRequestDispatcher("concreteInfectStatistic.jsp").forward(req,resp);
}
//否則跳轉到第一個頁面
else{
provinceDAO =new ProvinceDAOImpl();
List<Province> country = provinceDAO.list("全國",true);//獲取全國每天數據
//List<Province> all = provinceDAO.list();//獲取各省份每天的數據
int ip = 0,sp = 0,cure = 0,dead = 0;
//累加全國每天的數據
for (Province province : country) {
ip += province.getIp();
sp += province.getSp();
cure += province.getCure();
dead += province.getDead();
}
String name;
int eachIp;
//查找每個省份的每天的確診數據累加到一個數值上
for(int i = 0; i < ProvinceName.provinceSize; i++) {
name = ProvinceName.provinceName[i];
eachIp = 0;
List<Province> each = provinceDAO.list(name, true);//按省份名獲取省份每天數據
for(Province province : each){
eachIp += province.getIp();
}
req.setAttribute(name+"Ip",eachIp);
}
req.setAttribute("totalip",ip);
req.setAttribute("totalsp",sp);
req.setAttribute("totalcure",cure);
req.setAttribute("totaldead",dead);
req.setAttribute("country",country);
req.getRequestDispatcher("chinaMap.jsp").forward(req,resp);
}
- 讀取目錄下指定日期前的所有日志內容
public static String[] readFile(String path,String date) throws ParseException, IOException {
List allFilePath = getFileName(path,date);
String[] allContent = new String[allFilePath.size()];
for (int i = 0; i < allFilePath.size(); i++){
File file = new File(String.valueOf(allFilePath.get(i)));
StringBuilder result = new StringBuilder();
// 構造一個BufferedReader類來讀取文件
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8"));
String s;
// 使用readLine方法,一次讀一行,並忽略注釋行
while ((s = br.readLine()) != null && !s.startsWith("//")) {
result.append(System.lineSeparator() + s);
}
br.close();
allContent[i] = result.toString();
}
return allContent;
}
- 將正則匹配處理完的數據填入數據庫
public static void connectMysql() throws IOException, ParseException {
for (int i=0; i<date.length; i++){
String[] allContent = readFile("src/infectstatistic/log",date[i]);
ArrayList<Province> province = RegularMatch.match(allContent);
ListAdd(province, date[i]);
}
}
六、《構建之法閱讀心得》、心路歷程和收獲及對隊友的評價
閱讀心得
- 構建之法第四章提到兩人合作開發,我和隊友采用的是前后端分離的,按照作業要求使用Git分支,建立一條dev分支,讓隊友和自己在dev分支上開發,開發結束后再合並到main分支。第一次接觸這樣的結對編程,感到新穎的同時也很陌生,相信在以后的實踐中對這種合作開發會有更多經驗。
- 第五章講述軟件團隊模式和開發流程,至於團隊模式和團隊的開發模式的關系,我個人的理解是一群人在一起做軟件開發,總是要一些方式方法。而這里團隊模式就是這一群人的定性,團隊的開發模式則是這群人使用的方法的定性。
心路歷程
221701429
- 剛開始以為實現地圖會很難,但是知道了echarts之后發現也沒有那么難實現,
就是設置圖表格式和傳入數據的事情,折線圖也是一個意思。收獲也是挺多的,
第一次寫前端頁面,一直設置不好,沒辦法做出自己想要的樣子,甚是苦惱,
但時間問題也只能作罷,美名其曰“精簡”。
這次結對作業鍛煉了我們的合作開發能力,對技術上的也好、配合上的也好,
都有很大的提升,對GitHub的使用也更熟練了一些,總的來說是一件好事。
成長總是要經歷一些挫折的,這也是我的感受。
221701438
- 第一次看到這次作業感覺非常難,畢竟自己很少接觸前后端分離的開發模式,
與隊友討論完也認清自己的任務,代碼雖然不多,但是小BUG還是很多,
因為自己能力不足,很多時候還是在查文檔和看大佬代碼中學習。
本次結對作業采用了全新的結對開發模式,剛上手不是很熟悉,
在查找很多資料后逐漸掌握,這也算學到一種新的技能。
對隊友的評價
221701429
- 他是個靠譜的隊友,能一起合作是我的榮幸,他的部分我完全不用擔心,
都能做好,對前端的部分也能提出一些建議,是個有實力有配合的隊友。
221701438
- 我的隊友代碼規范,對本次作業的看法很多很棒,能給后端很清晰的開發思路。