“测试你的本命专业”选项与结果关系探究
1 代码获取
加载好页面后,断网,发现可以正常答题生成结果。推测通过JS即可直接生成结果,在Chrome浏览器中打开F12开发者工具->Network和Console窗口,根据下图红框选中部分推断相关代码应该在index.13918870.js中
构造网址(https://cdn-act.knowyourself.cc/life_profession/static/js/index.13918870.js),在代码末尾找到了//# sourceMappingURL=index.13918870.js.map,根据名称,可以推测与js文件有所联系,由于分析时并不了解.map格式的含义,因此要查询有关.map格式相关介绍的资料(资料来源:http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html),在资料中学习到,这种文件是JS进行源码转换后,对应的sourcemap文件。该文件储存着位置信息,即转换后的代码的位置对应的转换前的位置。
因此尝试构造网址(https://cdn-act.knowyourself.cc/life_profession/static/js/index.13918870.js.map),成功下载到index.13918870.js.map
接下来需要做的是将.map还原成代码转换前的格式,以便于我们分析。因此,接下来要查询有无可以在有map的情况下,帮助转换为JS的工具,查询得知GitHub上有一个开源工具shuji可以从sourcemap反向工程生成JavaScript/CSS源代码,工具地址为https://github.com/paazmaya/shuji。
按照该项目的readme搭载好环境,使用shuji index.13918870.js.map -o c:\xlcs将生成的js源代码放入C盘xlcs目录下,
进入该文件夹,发现result.js,猜测该文件应为输出结果关键js文件。
打开文件验证猜测,
可以看到有对应的代码和注释,是所需的目标文件,接下来分析该文件的流程。
2 流程说明
浏览源代码,给出如下简要流程:
函数名:getResult
输入:select,含义:用户答题选项信息,代码编写者已给出注释
输出:max,含义:最大值
1、为Array数组添加一个打乱元素顺序的函数shuffle()作为备用。
2、定义config对象。该对象中包含0~9十个属性,代表十道题,每个属性里又包括选项属性,属性从0开始代表选项,比如0、1、2、3分别代表A、B、C、D,每个属性对应的是一个数组,数组内的数代表该选项对应的结果。通过原开发者的注释,可以清楚的知道28个数对应的学科,如下:
// 结果页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:电子竞技
如,1: [3, 4, 24],代表选项B是符合3.社会学、4.教育学、24.表演艺术的。
3、从传入参数用户的选择中,使用双重循环遍历并获取对应的config对象。
外层循环:对10道题进行遍历。
内层循环:对每道题内用户选择的答案进行遍历(因为有多选题,需要遍历),并把用户选择的选项号作为数组下标,从config对象里找到该选择可以对应的学科号,把这些学科号拼接到result数组中。
4、创建一个result_map对象,该对象的属性是结果号,值为该结果号对应的数。如:16:2 代表用户作答的所有题中,有两个选项是符合“16.土木工程学”的。
遍历3中得到的result数组,每次遍历首先判断result_map中是否有该学科号?否:创建对应属性,属性值设为0,然后对应属性值+1。是:对应属性值+1。
遍历的同时获取最大值。默认最大值是-1,那么第一次遍历时将max设置为result数组第一个元素对应的学科号。此后,每次遍历对应属性值+1后与max进行比较,遍历结束后即可获得最大值。
3 验证
接下来用一个用例进行验证。
假定我们的预期输出是表演艺术。对应的结果号为24
从config里获知,第一题应选择C。第二题应选择B。第三题应选择A。第四题应选择A。第五题应选择A。第六题应选择B。第七题应选择B。第8题应选择B。第九题应选择第8个选项、第11个选项。第10题无所谓,不影响结果。
按照上面的选择进行测试,实际输出结果如下:
符合预期。
接下来改变专业、改变姓名、改变性别、改变第10题的选项,其他不变,因为认为这些均是无关选项,认为不会影响输出。实际结果如下:
符合预期。
上面选项是最理想最符合该结果的,实际上只要保证,符合上述输入的选择在本次答题中是最多的就可以。因此这里改变几道选项,在第1、2题中选择其他选项,第9题选8、9、11。其他不变。实际结果如下:
接下来多改几个:
1题选A。2题选C。第九题选1、2、3,其他不变
这时,表演艺术只有3-8题符合,而1、2、3、5、6、7、9题都有符合汉语言文学的,汉语言文学成为max,因此结果应该变成汉语言文学,实际输出如下:
4 致谢及补充
以上内容中暂未分析shuffle()的作用,测试部分没有考虑到可能有多个学科符合max的情况。博文https://www.cnblogs.com/ZigHello/p/14825696.html中的分析包含了这些部分,使得我能够意识到并弄清本文中遗漏及不完善之处,在此对博文作者表示感谢。