to top

结对第二次作业

这个作业属于哪个课程
https://edu.cnblogs.com/campus/fzu/2020SpringW/
这个作业要求在哪里
https://edu.cnblogs.com/campus/fzu/2020SpringW/homework/10456
结对学号
221701429 221701438
这个作业的目标
疫情统计可视化的原型
作业正文
....
其他参考文献
....

一、Github 仓库地址和代码规范链接

二、成品演示

  • 地图上方提供日历,可以选取不同日期查看截止该日全国疫情情况
    conv_ops

  • 统计数据在地图上方,只显示到助教提供的静态文件最后一个日期
    相同感染人数区间的省份可以通过左下方鼠标停留或点击
    conv_ops

  • 全国疫情折线图在地图下方,可选择显示或隐藏确诊,疑似,治愈,死亡四条折线
    折线上的点显示当前日期的疫情数据
    conv_ops

  • 地图上点击不同省份会跳转到该省份疫情数据的折线图
    conv_ops

三、结对讨论过程描述

  • 作业发布当天晚上,由于技术不足无法实现实时数据更新,我们决定用javeEE课上学的JSP框架和数据库完成本次作业
    聊天1
    聊天2

四、描述设计实现过程

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
  • 我的队友代码规范,对本次作业的看法很多很棒,能给后端很清晰的开发思路。
posted @ 2020-03-13 20:56  hhxd  阅读(350)  评论(2编辑  收藏  举报