运用所学的知识对“测测你的本命专业”进行分析

1.分析对象

https://cdn-act.knowyourself.cc/life_profession/“测测你本命专业进行分析”

2.详细分析

一、网络分析

打开网页按F12选中Network,开始答题以及答题时候服务器端一直向浏览器端发送图片数据,如下图

因为页面没有跳转因此只有可能进行异步获取后端数据,选中XHR进行数据过滤,过滤后没有发现任何数据,因此这是一个纯前端项目。

 

二、项目结构分析

选中Sources来进行源码分析,容易发现这个前端项目是由webpack构建的。该项目的基本文件结构如下图所示:

根据包名易得components是组件包,img是存放图片的包,pages是存放页面的包,util是工具包。

大致浏览包下的源码易知pages包是该项目的核心包。

pages文件的结构大致如下:

 查看了部分源码易得,p-1是开始答题页面包,p-2是答题的页面包,done是答题完成产生结果的包。

因此核心代码在done文件夹下。

3.核心代码分析

对pages/index.tsx核心代码进行分析:

  const select = select_q_list.reduce((l: any, f: any, i: number) => {
    if (i !== 9) {
      // @ts-ignore
      l.push([f.index])
    } else {
      l.push(f.map((v: any) => select_map.indexOf(v)).sort((a: any, b: any) => a - b))
    }

将select_q_list数据转换为select数据,如下图所示

 

 

 用result(select.slice(1))去除select数组的第一个元素,并将数据传输给result。

result.js核心代码分析

config中的0-9和1-10题的题号一一对应,题号中的key表示的是选项的个数,value表示的是与该选项内容相关的专业。

将page/index.tsx的select.slice(1)传输到result.js中

  var result = [];
  for (var topic_num = 0; topic_num < select.length; topic_num++) {
    // 遍历本题答案
    for (var j = 0; j < select[topic_num].length; j++) {
      var user_select = select[topic_num][j];
      // 获取配置
      var tmp = config[topic_num][user_select];
      // 合并
      result = result.concat(tmp);
    }
  }

将select.slice(1)与config对应的数组信息,全部放入result数组中

 var result_map = {};
  var max = -1;
  // 打乱一下result结果
  result.shuffle();
  for (var i = 0; i < result.length; i++) {
    if (typeof result_map[result[i]] == "undefined") {
      result_map[result[i]] = 0;
    }
    result_map[result[i]]++;
    if (max == -1) {
      max = result[i];
    } else {
      if (result_map[result[i]] > result_map[max]) {
        max = result[i];
      }
    }

result_map用来统计出现最多的专业编号并返回给index.tsx,并调用该页面的图片

 4.测试

根据基础的组合知识可以算出前八道单选的可能性是4800种,第九题多选的可能性是286种,所以有1372800种满足题目需求的不同测试用例。本地完成1372800种测试用例的代码。用桶来记录每题出现的次数,如下图所示

 

 

 可以发觉无论怎么填写测试题,都无法出现机电工程学专业,或许是作者留的彩蛋吧!

 测试用例的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
  <script>
    // 结果页id:
// 0:经济学
// 1:哲学
// 2:法学
// 3:社会学
// 4:教育学
// 5:汉语言文学
// 6:外国语言学
// 7:新闻学
// 8:历史学
// 9:数学
// 10:物理学
// 11:化学
// 12:生命科学
// 13:地理学
// 14:心理学
// 15:计算机科学与技术
// 16:土木工程学
// 17:建筑学
// 18:机电工程学
// 19:农林学
// 20:医学
// 21:管理学
// 22:艺术
// 23:戏剧影视导演
// 24:表演艺术
// 25:体育学
// 26:考古学
// 27:电子竞技

//10道题,选择传入数组,因为有多选,数组内套数组
//选择顺序从0开始算,0代表第一个选项,1代表第二个...
//例如 select :[[0],[1],[3],[0],[0,1,2,3],[0,1,2,3,4],[0]]
function getResult(select) {
  if (!Array.prototype.shuffle) {
    Array.prototype.shuffle = function () {
      for (var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x)
        return this;
    };
  }
  var config = {
        0: {
          0: [1, 0, 2, 3, 4, 5, 6, 7, 8, 21, 26],
          1: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26],
          2: [22, 23, 24, 25, 27],
        },
        1: {
          0: [0, 2, 6, 7, 20, 21, 25],
          1: [3, 4, 24],
          2: [5, 14, 22],
          3: [1, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 23, 26, 27],
        },
        2: {
          0: [1, 3, 4, 5, 9, 10, 14, 21, 22, 23, 24, 27],
          1: [0, 2, 6, 7, 8, 11, 12, 13, 15, 16, 17, 18, 19, 20, 25, 26],
        },
        3: {
          0: [0, 2, 3, 4, 6, 7, 20, 21, 24, 25],
          1: [1, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 26, 27],
        },
        4: {
          0: [1, 3, 4, 5, 9, 10, 14, 21, 22, 23, 24, 27],
          1: [0, 2, 6, 7, 8, 11, 12, 13, 15, 16, 17, 18, 19, 20, 25, 26],
        },
        5: {
          0: [1, 0, 2, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27],
          1: [3, 4, 5, 14, 22, 24],
        },
        6: {
          0: [1, 8, 9, 10, 11, 12, 13, 20, 26],
          1: [5, 22, 23, 24],
          2: [15, 16, 17, 18, 19, 25, 27],
          3: [3, 4, 6, 7, 14],
          4: [0, 2, 21],
        },
        7: {
          0: [1, 8, 9, 10, 11, 12, 13, 20, 26],
          1: [5, 22, 23, 24],
          2: [15, 16, 17, 18, 19, 25, 27],
          3: [3, 4, 6, 7, 14],
          4: [0, 2, 21],
        },
        8: {
          0: [4, 5, 7, 14, 21, 23, 6],
          1: [6, 15],
          2: [13],
          3: [10, 16, 17, 18],
          4: [12, 19, 20, 25],
          5: [1, 2, 7, 21],
          6: [0, 9, 15, 16, 18, 10, 14],
          7: [17, 22, 24, 23],
          8: [3, 8, 26, 13],
          9: [11, 12, 19, 20, 26],
          10: [25, 27],
          11: [22, 24],
        },
        9: {
          0: [],
          1: [],
          2: []
        }
      };

      var result = [];
      for (var topic_num = 0; topic_num < select.length; topic_num++) {
        // 遍历本题答案
        for (var j = 0; j < select[topic_num].length; j++) {
          var user_select = select[topic_num][j];
          // 获取配置
          var tmp = config[topic_num][user_select];
          // 合并
          result = result.concat(tmp);
        }
      }
      var result_map = {};
      var max = -1;
      // 打乱一下result结果
      // result.shuffle();
      for (var i = 0; i < result.length; i++) {
        if (typeof result_map[result[i]] == "undefined") {
          result_map[result[i]] = 0;
        }
        result_map[result[i]]++;
        if (max == -1) {
          max = result[i];
        } else {
          if (result_map[result[i]] > result_map[max]) {
            max = result[i];
          }
        }
      }
      
      //console.log(result);
      //console.log(result_map);
      //console.log(max);
      return max;
    }

    // test
    // console.log(getResult([[2],[3],[0],[1],[0],[0],[1],[1],[0,7,10],[1]]));//期望结果 23
    // console.log(getResult([[1],[3],[1],[1],[1],[0],[2],[2],[1,2,6],[1]])); //15
    // getResult([[1],[3],[1],[1],[1],[0],[2],[2],[1,2,6],[1]]);//期望结果 15
    //getResult([[2],[3],[0],[1],[0],[0],[1],[1],[0,7,10],[1]]);//期望结果 23

    /**
     * 测试脚本
     * 
    */
    //前面8道单选全部的可能性,封装到results数组中
    arr = [
          [0,1,2],
          [0,1,2,3],
          [0,1],
          [0,1],
          [0,1],
          [0,1],
          [0,1,2,3,4],
          [0,1,2,3,4]
      ]
      results = [];
      res = [];
      doExchange(arr, 0);
      function doExchange(arr, index){
          for (var i = 0; i<arr[index].length; i++) {
              res[index] = arr[index][i];
              if (index != arr.length - 1) {
                  doExchange(arr, index + 1)
              } else {
                  results.push(res.concat())
              }
          }
      }
      //将results数组中的数变成数组
      for (var i = 0; i < results.length; i++) {
          results[i].forEach(function(value,index,array){
            array[index] = [].concat(value)
          });
      }
      console.log(results);
      //第九题的所有组合算法
      var data = [0,1,2,3,4,5,6,7,8,9,10,11];
      var path = []
      var group = []
      function getGroup(k,startIndex,data = []){
          if(path.length==k){
              group.push(path.concat());
              return;
          }
          for (let i = startIndex; i < data.length; i++) {
              path.push(data[i]);
              getGroup(k,i+1,data);
              path.pop()
          }
      }
      getGroup(2,0,data)
      getGroup(3,0,data)
      console.log(group)

      // 合并1-9题的所有组合
      last = [];
      for (let i = 0; i < results.length; i++) {
          for (let j = 0; j < group.length; j++) {
              //创建一个新的数组
              var arr = [].concat(results[i])
              arr.push(group[j])
              last.push(arr)
          }
      }
      console.log(last);

    var bucket = new Array(28).fill(0) //构建一个长度为28的桶
    for (let i = 0; i < last.length; i++) {
        var index = getResult(last[i])
        bucket[index]++
    }
    console.log(bucket)
  </script>
</body>
</html>
测试用例

 

 PSP:

做什么 日期 开始时间 结束时间  休息时间 合计时间
写博客 9/15    21:18  21:53   0  47min
写博客 9/15   22:06  22:20  2min  12min
        总计   59min
posted @ 2021-09-10 16:34  hokutosei  阅读(173)  评论(0)    收藏  举报