2020软件工程作业_04

第4次作业-结对编程之实验室程序实现

一、作业概述

这个作业属于哪个课程 http://dwz.date/cts4
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2020/homework/11277
这个作业的目标 熟悉前端的开发流程,熟悉HTML、CSS、JAVASCRIPT语言以及部分框架
结对同学 031802233_王振宇 031802225_沈润佳
结对同学的博客链接 https://www.cnblogs.com/runrun225/p/13800631.html
GitHub项目地址 https://github.com/2441461233/031802225_031802233

二、具体分工

031802225 沈润佳:前期资料的收集、前期思路的设计、前期代码的编写、美化代码、博客撰写。

031802233 王振宇:主要代码的编写、单元测试。

三、PSP表格

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

四、解题思路描述与设计实现说明

分析需求可知,需要对输入内容进行处理,并且生成师门树和技能树,鉴于本组小朋友开发经验都不足,在上网查阅大量资料之后,决定使用jQuery 框架有着详细教程上手较快的 antv G6,即一个图可视化的引擎,先用html编写文本框,对输入内容进行分析生成 json 对象后引入G6,生成师门树和技能树。

整体思路鱼骨图展示如下:

数据流图如下:

第0层DFD:

第1层DFD:

各模块详解:

1. 解析文本框内容:

针对每行不同输入(导师、学生信息、学生技能)进行不同处理提取相应信息存于数组。并统计相应的数量,以便之后循环程序的编写。

function submittext() {             //解析输入 每个人赋予一个IDD和相应信息数组
    var Text = document.getElementById("inputtext").value;
    var Lines = Text.split("\n");
    var teacher = new Array(), nameLine = new Array();
    var name = new Array();
    // teacher标识是否是导师,degree标识学位,year标识年级,
    // nameLine存每行完整信息,nameString存:后内容,name存名字
    var branch = 0;
    for (var i = 0; i < Lines.length; i++) {
        if (Lines[i].length == 0) {             //跳过空行
            continue;
        }
        teacher[i] = Lines[i].substr(0, 2);  //分割前两个字,判断是否是“导师”
        if (teacher[i] == "导师") {          //导师处理
            ID++;                          //每个人独有ID
            degree[ID] = "导师";            //degree导师
            NAME[ID] = Lines[i].substring(3);
            degreenum[teachernum] = 0;
            teachernum++;
        }
        else if(/^\d+$/.test(teacher[i])) {                       //非导师处理
            var temp1 = Lines[i].substring(0, 4); //temp1为年级
            var temp2 = Lines[i].substr(5, 2); //temp2为学位等级
            var tempNameString = Lines[i].substring(Lines[i].search(":") + 1);
            name[i] = tempNameString.split("、");

            degreenum[teachernum - 1]++;
            for (var j = 0; j < name[i].length; j++) {      //每个人分配ID  并且存储相关信息
                ID++;
                year[ID] = temp1;
                degree[ID] = temp2;
                NAME[ID] = name[i][j];
                // studentnum[branch]++;
            }
            studentnum[branch] = name[i].length;
            branch++;
        }
        //技能树生成
        else {
            linestr = Lines[i];
            var posi = linestr.search(":");
            var stuName = linestr.substring(0, posi);
            var tempAttris = linestr.substring(posi+1).split("、");
            attris[stuName] = tempAttris;
            console.log(attris);
        }
    }
}

2.将文本框获取内容生成json对象

G6 的数据源要求为json对象。因此需将所获信息转换json对象。我们采用动态创建,根据之后生成的树创建父子节点。下一层为上一层的孩子结点。

var IDD = 0; var kk = 0; var kkk = 0;
for (var k = 0; k < teachernum; k++) {
    IDD++;
    // console.log("teacher="+teachernum);
    var test2 = { id: NAME[IDD], children: [] };           
    for (var i = 1; i <= degreenum[kk]; i++) {
        // console.log(kk+" =="+degreenum[kk]);
        var xxx = new Object();
        xxx.id = year[IDD + 1] + degree[IDD + 1];
        xxx.children = new Array();
        for (var j = 1; j <= studentnum[kkk]; j++) {
            var yyy = new Object();
            IDD++;
            yyy.id = NAME[IDD];
            yyy.children = new Array();
            // 增加个人经历
            if(attris.hasOwnProperty(yyy.id)) {
                console.log("has");
                for(var k = 0; k < attris[yyy.id].length; k++) {
                    var yyychild = new Object();
                    yyychild.id = attris[yyy.id][k];
                    yyychild.children = new Array();
                    yyy.children.push(yyychild);
                }
            }

            xxx.children.push(yyy);
        }
        test2.children.push(xxx);
        kkk++;
    }
    kk++;
    hell = JSON.stringify(test2);

3.根据json对象,使用G6引擎并生成师门树

function pk(data) {
          // function test2(hell){
          // console.log("xxxx");
          // console.log("typeof data is "+typeof  data);
          // console.log(data);
          // console.log("yyyyy");
          // function pick (data=hell) {
          var graph = new G6.TreeGraph({
              container: 'mountNode',
              width: 800,
              height: 1200,
              pixelRatio: 2,
              modes: {
                  default: [{
                      type: 'collapse-expand',
                      onChange: function onChange(item, collapsed) {
                          var data = item.get('model').data;
                          // console.log("type of this shit is",typeof data);
                          // console.log(data);
                          data.collapsed = collapsed;
                          return true;
                      }
                  }, 'drag-canvas', 'zoom-canvas']
              },
}

参考链接:

使用其中的 TreeGraph

参考链接:https://antv-g6.gitee.io/zh/docs/manual/getting-started

使用 JQuery UI 组件库

参考链接:https://www.runoob.com/jqueryui/jqueryui-use.html

注意

  • 区分json字符串和json对象!

  • 引入 G6 的数据源为 JSON 格式的对象

  • jquery ui 是基于 jquery 的 UI 库,提供的是UI组件库;
    而jquery是工具库;

五、附加特点设计与展示

设计意义

  • 任意拖动生成树 ,支持结点缩放→ 帮助老师同学快速了解自己的同门学长学姐学弟学妹,以及快速了解自己和同学伙伴们的技能。
  • 师门技能树可以变大变小 → 万一有同学近视呢?
  • 一键清空按钮 → 便于同学一键删除所有信息,重新输入
  • 贴心的输入格式导航→方便同学按照规定格式输入文本内容

实现思路

  • 一键清空:引入清空的函数
  • 处理用户输入
  • 生成树的优化:使用 G6 引擎

代码详解

  • 一键清空的函数

    function cleartext() {
        location.reload();
    }
    
  • 使用G6 引擎美化图图

    function pk(data) {
        // function test2(hell){
        // console.log("xxxx");
        // console.log("typeof data is "+typeof  data);
        // console.log(data);
        // console.log("yyyyy");
        // function pick (data=hell) {
        var graph = new G6.TreeGraph({
            container: 'mountNode',
            width: 800,
            height: 1200,
            pixelRatio: 2,
            modes: {
                default: [{
                    type: 'collapse-expand',
                    onChange: function onChange(item, collapsed) {
                        var data = item.get('model').data;
                        // console.log("type of this shit is",typeof data);
                        // console.log(data);
                        data.collapsed = collapsed;
                        return true;
                    }
                }, 'drag-canvas', 'zoom-canvas']
            },
    
            /******************美化****************/
            defaultNode: {
                size: 16,
                anchorPoints: [[0, 0.5], [1, 0.5]],
                style: {
                    fill: '#CCFF00',
                    stroke: '#d91808'
                }
            },
    
            defaultEdge: {
                shape: 'cubic-horizontal',
                style: {
                    stroke: '#000000'
                }
            },
    
            layout: {
                type: 'compactBox',
                direction: 'LR',
                // nodeSep:30,
                // rankSep:100,
                getId: function getId(d) {
                    return d.id;
                },
                getHeight: function getHeight() {
                    return 16;
                },
                getWidth: function getWidth() {
                    return 16;
                },
                getVGap: function getVGap() {
                    return 10;
                },
                getHGap: function getHGap() {
                    return 100;
                }
            }
        });
    
        graph.node(function (node) {
            return {
                size: 26,
                style: {
                    fill: '#CCFF00',      //节点颜色
                    stroke: '#2BD54D'  //节点边框
                },
                label: node.id,
                labelCfg: {
                    position: node.children && node.children.length > 0 ? 'left' : 'right'
                }
            };
        });
    

实现成果展示


六、目录说明和使用说明

目录组织形式

zy2.html 为HTML代码编写

zy2.js 为js代码编写

其余为支撑库

运行网页的方法

下载库中所有文件并保证本地相对路径的一致性,打开zy2.html即可运行。

输入内容请按照文本框内的提示输入。

得到生成树后可任意拖拽,并可用滚轮调整页面。

七、单元测试

测试工具:

Mocha

教程

  • 安装配置node.js

  • 安装配置mocha

  • .test.js的编写

  • 配置好单元测试的目录文件

  • 进行单元测试

参考链接:

部分单元测试代码

var submittext = require('../attritest.js');
var expect = require('chai').expect;

describe('技能树测试', function() {
  it('刘六:JAVA、数学建模', function() {
    expect(submittext("刘六:JAVA、数学建模")['刘六']).to.include('JAVA');
  });
  it('李二:字节跳动、京东云', function() {
    expect(submittext("李二:字节跳动、京东云")['李二']).to.include('京东云');
  });
});

构造测试数据的思路,如何应对测试人员的***难

首先输入数据必须满足格式要求,在此基础上构建数据

  • 名字过长? → 并不影响 √
  • 技能过多? →并不影响 √

如果是测试人员的故意***难?

  • 不好好按照规定格式输入数据? → 和测试人员好好沟通!
  • 输入无关数据(并非师门关系或者技能)→ 那就微笑这看着测试人员!

八、GitHub代码签入记录截图

九、困难以及克服困难

  • 对前端知识不熟悉
    • 做出尝试:查阅教程、游览大量博客。
    • 目前解决 √
  • 收获:
    • 学会速读教程,需要什么学什么
    • github进一步熟悉体会到了其方便之处
    • 单元测试进一步熟悉
    • 明白了一个道理:编程语言语法并不十分重要,重要的是思想,有时候思想在,即便熟悉这种语言也可以很快实现

十、评价队友

评价沈润佳同学:

* 做事认真仔细
* 收集、整理资料能力强
* 文字撰写能力强
* 规划性强,能够及时提醒队友
posted @ 2020-10-12 09:56  izyow  阅读(275)  评论(0编辑  收藏  举报