zoukankan      html  css  js  c++  java
  • 软件工程实践:结对作业(第二次作业)

    作业地址

    结对第二次作业

    结对成员

    Github

    • Deputy: Department-to-Student bidirectional selection;
    • Deputy-generator:generate corresponding input JSON file for Deputy.

    数据生成程序, Deputy-generator

    一个生成的数据:input_data.json.

    数据生成原理

    部门:
    1.部门编号;
    2.部门纳新上限;
    3.部门固定活动时间;
    4.部门的兴趣标签

    学生:
    1.学号;
    2.选择的部门;
    3.业余时间;
    4.兴趣标签;
    5.是否被部门选中

    生成过程:
    学生:
    (第一步:生成除部门意愿以外的基本信息)

    • 按序生成学生学号(001-300);
    • 对于每一个学生,生成总数在范围[2, 8]之间的空闲时间段,分布一周7天,每个空闲时间段不超过3个小时,空闲时间段开始时间在[480, 1260],即早上八点到晚上九点之间;避免一天之内的空闲时间段的重叠,方法是将之前的时间段作为约束来生成下一时间段;
    • 随机选择兴趣标签数目,不作约束;
    • 生成数量在范围[1, 5]之间的部门意愿数目。
      (第二步:生成部门意愿)
      -首先生成热门部门的数量,经过商量确定为i【24】个,热门的占比为10,剩下的普通部门占比为4,这样我们就可以的到区间为【010i+4(20-i)】(作用在后面体现)
      -然后生成该学生一共选k个部门(k的范围是【1~5】)
      -最后依次生成k个部门,生成的方法是生成一个随机数,其范围是【0~10i+4(20-i)】(从第一步可以得到),然后根据生成的数我们就可以推出时选哪个部门,同时我们会生成一个数据用来存储前面选过的部门,避免重复选择。

    部门:

    • 按序生成部门编号(01-20);
    • 对于每一个部门,生成总数在范围[2, 5]之间的空闲时间段,分布一周7天,每个空闲时间段不超过3个小时,空闲时间段开始时间在[480, 1260],即早上八点到晚上九点之间;避免一天之内的空闲时间段的重叠,方法是将之前的时间段作为约束来生成下一时间段;
    • 随机生成范围在[10, 15]之间的人员限制;
    • 选择数目在[2, 5]之间的兴趣标签。

    考虑的因素

    1.热门部门的占比不同,会有更多的人去报名该部门。

    2.一周之内部门的活动时间最多不超过5次,每一天的活动次数不超过2次,每一次的活动时间不超过3个小时。

    3.学生的兴趣标签可以比较多,因为现在学生的特长更加广泛,但是部门的标签不能太多,因为部门本身就有自己的特色,倾向,这已经使其标签范围不可能太广。

    4.部门的活动时间是早上八点到晚上九点(符合实际,不可能大清早去活动)

    5.每个人分配一到两个部门,这样更加符合学生的实际状况,不会太过劳累,

    数据建模及匹配程序的思路及实现方式

    数据建模

    部门选择学生要考虑三个因素:学生选该部门是第几个志愿(同时也要考虑学生一共有几个志愿),学生兴趣标签和部门标签的匹配程度,学生的业余时间和部门固定活动时间的匹配程度。

    第一个因素(学生选该部门是第几个志愿(同时也要考虑学生一共有几个志愿)):
    显然越前面的志愿分值越高,学生选的志愿越少分值也会越高,同时为了使志愿之间的占比不是线性的(因为线性的区分度太低),这里就采用了取平方的方法。而学生志愿越少得分越高则想到了利用倒数的方法,而经过多次计算不同的值得到的结果,确定分子为2的时候,结果比较满意。
    所以得到这部分的计算公式:
    value1=(2/student_instance.applications_department_number)(5-k)(5-k)
    (其中student_instance.applications_department_number就是学生总得志愿数,k是该志愿是学生的第几志愿)

    第二因素(学生兴趣标签和部门标签的匹配程度):
    学生与部门标签的匹配度乘上某个数就是该部分的得分,而考虑了第一因素,发现第一因素的最高分为50,所以给第二因素的常量也为50。
    所以得到这部分的计算公式:
    value2=(match_tags/department_instance.tag_number)*50
    (其中match_tags是学生与部门标签的匹配的条数,department_instance.tag_number是部门总的标签数)

    第三因数(学生的业余时间和部门固定活动时间的匹配程度):
    根据现实情况,学生的业余时间越多越好,这样部门能更好的管理部员,而这个因素不能占太多的比重,毕竟头两个因素才是重点,所以这个因素是用来当做附加分的,分值也不高,大概在5分左右。
    所以得到这部分的计算公式:
    value3=times*stu_weekday_num/dep_weekday_num
    (其中times是学生与部门的时间匹配数,stu_weekday_num是学生的课余时间总数,dep_weekday_num是部门的固定活动时间总数)

    因此我们可以知道匹配值value=value1+value2+value3

    匹配程序的思路及实现方式

    具体方法定义看:matchAlgorithmTools.cpp
    具体实现过程看:matchAlgorithm.cpp

    下面是对过程的一个步骤分解

    第一步:
    将学生分为两类(有选志愿的和没选志愿的)
    调用matchAlgorithmTools.cpp的void deliverStudent()函数

    第二步:
    记录部门被学生选择的次数(分为0~4个志愿)

    (其中currentDepartment是当前部门,k是第几志愿)

    第三步:
    计算学生的权值(用于部门选择学生)
    调用matchAlgorithmTools.cpp的
    int matchedLevelValue(int k, students student_instance, departments department_instance)函数

    第四步:
    将部门按照受欢迎程度进行排序(之后热门部门将优先选择学生)
    调用matchAlgorithmTools.cpp的void calculateDepOrder()函数

    (计算的数组是由第二步得到algorithmTool.studentWishes二维数组)

    第五步:
    部门选择学生
    根据学生的value排序,拿出前department[currentDepartment].member_limit(就是部门收取人数的上限)个没被其他部门选走的学生加入当前的部门,完成分配。

    代码规范

    本次项目统一使用Github进行源代码管理,两人统一使用Wasdns账号进行提交。我们在结对过程中遵循以下规范:

    • 1.良好的注释习惯:对于每一个代码模块(一行或者多行,函数或者类)都进行详细的注释,保证队友能够理解
    • 2.参考"驼峰命名法"对变量进行命名,要求每一个变量的命名都是有意义的,且能够清楚地通过变量名了解该变量的作用
    • 3.进行异常的判断及处理

    代码佐证:

    	 /*
    	 * The following codes are used to: 
    	 *
    	 * 1.update studentWishes to calculate the order among departments.
    	 *
    	 * 2.calculate studentDepValues(student vs department) to find out
    	 *   that if the student is matched against the department or not.
    	 *   And for the following codes(i.e.L79), the studentDepValues is
    	 *   used to help the department choose students.
    	 * 
    	 */
    	
    	for (int i = 0; i < algorithmTool.eagerStudentNumber; i++) {
    		// current index of eagerStudents
    		int currentStudent = i;
    
    		// the total number of departments 
    		// that chosen by the current student
    		int depTotal = algorithmTool.eagerStudent[currentStudent].applications_department_number;
    		
    		// j: the number of departments
    		// k: the number of student wishes
    
    		// for each of the departments
    		for (int j = 0; j < 20; j++) {
    			int currentDepartment = j;
    			// the number of current department 
    			string currentDepartment_str = department[currentDepartment].department_number;
    
    			// check if the department 
    			// is the chosen one or not
    			for (int k = 0; k < depTotal; k++) {
    				// the k wish of current student
    				string kwish = algorithmTool.eagerStudent[currentStudent].applications_department[k];
    				
    				// if matched, means that 
    				// the student want this department
    				if (kwish == currentDepartment_str) {
    					// add 1 to studentWishes[department_number: currentDepartment][wishes: k]
    					algorithmTool.studentWishes[currentDepartment][k]++;
    
    					// calculate the value between current student 
    					// and current department based on k
    					// (the current number of wishes), the student instance 
    					// and the department instance  
    					int stuDepValue = algorithmTool.matchedLevelValue(k, algorithmTool.eagerStudent[currentStudent], department[currentDepartment]);
    					assert(stuDepValue != -1);
    					// record the stuDepValue 
    					// calculated by matchedLevelValue(...)
    					// in studentDepValues[student_instance_index][department_instance_index]
    					algorithmTool.studentDepValues[currentStudent][currentDepartment] = stuDepValue;
    					break;
    				}
    			}
    		}
    }
    

    结果评估

    运行了助教给的输入样例,结果如下:

    • 1.未匹配人数:190人,占比63%;
    • 2.未匹配部门:2个,占比10%;
    • 3.部门最多招纳人数:10人;
    • 4.部门平均招纳人数:5.5人。

    通过估算,平均每个部门收人上限为10~15个,最多要收取240人左右,而我们运行的结果显示有110人被部门收走,也就是收取人达到百分五十左右,去除和部门不匹配的人,百分五十是可以接受的数据。

    结对感受

    (1)结对感受:

    李鸣:这次结对作业,刚好我和我翔(队友)都是莆田人,所以就算是国庆放假也能够面基结对,整个国庆我们面基了5次,同时还语音结对了3次,可以说是整个国庆都是在结对中度过了,基本上也没消停过,说实话是很难受,毕竟是今年的最后一个法定节假日。但是,在和我翔的结对中也不乏乐趣,经我翔介绍发现了一家很有情趣的咖啡馆,听我翔说买上一杯咖啡可以在这度过一个下午,结对的过程中有让我印象最深的就是我翔的代码规范,真的做的很好,比起我的一团糟代码简直天差地别,这也让我明白了代码规范的重要性,在作业刚开始的时候我翔就自己做好了输入输出的工作,而我的工作主要就是想如何匹配,其他的部分则是我们一起思考,敲代码弄好的,这过程中也发现了结对带来的一个好处就是,敲代码的人头脑可能不会那么清晰,有时候一些小错误发现不了,而一旁的队友一般都会很容易发现这种小错误,节省了很多的时间。总得来说,这次结对是一次不错的体验,唯一的代价估计就是少了个国庆。

    陈翔:我能够深深体会到这两次结对的作业量,在多件事情并行的情况下国庆假期等于没放假了。这次结对,几天内近几k行的代码量,近百余次的Github项目管理记录(不算什么但是我觉得还是要列一下:D),和我鸣多次的电话讨论确定算法模型,见面敲定解决方案。虽然不是第一次和别人合作完成项目,但是本次结对依然获益颇多:一是收获了结对编程的经验,有旁边人实时code review的感觉还是很良好的,因为一个人的时候经常是这种情况:"写bug五分钟,debug两小时",在结对编程中就不会有这种情况的发生,避免了大量不必要时间的浪费,提高了整体效率,此外作为一个小团队也学习了一些团队协作的知识,比如编码规范,模块对接等等;二是充实(填满)了整个假期,提升了整体的编码水平,巩固了(再一次预习了)C++的知识,让我了解到很多Linux下编译、编程的知识以及之前未曾涉及到的JSON的解析方法;三是在结对过程中与我鸣多次交流结下了深厚(?)的友谊,虽然不时会被他和他的小可爱虐一脸,可是他幽默风趣、细心可爱、阳光帅气、有担当负责任,是一个不可多得的好搭档,编码过程中思路清晰,纠正了我不少的问题。

    我对于我鸣的建议有以下两点:

    • 1.编码过程中要时刻注意写注释和代码规范,变量命名时要合理清晰;
    • 2.Github commit的习惯,当你上手学会了Github之后,它会是一个非常棒的工具;
    • 3.好好珍惜女朋友,工作的时候女朋友的电话还是要接的。

    贴上我翔拍摄的咖啡馆(搞基好去处):

    以及店内一只猫(阿布,可撸!!),看见我的电脑包就坐上去了????

  • 相关阅读:
    1026 Table Tennis (30)
    1029 Median
    1025 PAT Ranking (25)
    1017 Queueing at Bank (25)
    1014 Waiting in Line (30)
    1057 Stack (30)
    1010 Radix (25)
    1008 Elevator (20)
    字母大小写转换
    Nmap的基础知识
  • 原文地址:https://www.cnblogs.com/zxlmhh/p/7642836.html
Copyright © 2011-2022 走看看