• 软件工程实践2017结对第二次作业


    结对成员:吴君毅(031502629),吴伟根(031502631)
    Github链接:https://github.com/n9705/Dep-Stu

    一、 题目要求

    构造部门和学生输入数据的生成程序,实现一个智能自动分配算法,根据输入信息,输出部门和学生间的匹配信息(一个学生可以确认多个他所申请的部门,一个部门可以分配少于等于其要求的学生数的学生) 及 未被分配到学生的部门 和 未被部门选中的学生。
    分工情况:基本上是我负责数据生成程序,伟根负责部门学生自动分配算法,遇到问题互相帮助探讨。

    二、 数据生成程序

    这部分主要是由我负责
    首先根据题目要求创建两个结构体数组部门和学生,要满足的条件如下:

    学生:

    • 空闲时间段(设置最大为12个,且同一天的不同时间段不能重叠,且根据实 际情况,时间不能是晚上10点后到第二天早上8点之间,且空闲时间段以两小时为单位)
    • 学号(不可重复)
    • 意向部门(不可重复,最多5个)
    • 兴趣标签(不可重复最多8个)

    部门:

    • 活动时间(设置最大为12个,且同一天的不同时间段不能重叠,且根据实际情况,时间不能是晚上10点后到第二天早上8点之间,活动时间为2小时)
    • 部门人数限制(10-15之间)
    • 部门编号(不可重复)
    • 兴趣标签(因为一个部门主要比较专业,所以兴趣标签定为不超过3个)
      原理:通过不断的循环,给学生和部门的结构体数组赋值,其中因为要模拟随机性,所以大量用到了随机数的算法,除了学生学号和部门编号,其他都是随机函数组合出来的。说是随机,但是同一个学生或部门里的一些信息也不能重复,为了避免这个情况,就要给之前随机出的结果做统计,不能重复,具体实现就是把之前的结果送进数组里然后每生成一次就查重一次。最后输出的时候,用Json的格式进行输出。
      核心代码:
    int random_num(int a, int b)//产生 [a,b]的随机数 
    {
    	int rander;
    	rander = (rand() % (b - a + 1)) + a;
    	return rander;
    }
    for (int j = 0; j<a; j++)//产生兴趣标签 
    		{
    			int b;
    			b = random_num(1, 11);
    			for (int x = 0; x<j; x++)//兴趣标签不能重复 
    			{
    				if (num[x] == b)
    				{
    					b = random_num(1, 11);
    					x = 0;
    				}
    			}
    			num[j] = b;
    			stu[i].tags[j] = ttags[b];
    		}
    

    输出文本示例:https://github.com/n9705/Dep-Stu/blob/master/project/input_data.txt
    学生输出示例:

    部门输出示例:

    不足:

    1. 空闲时间因为随机,虽然当天的时间段不会重复,但是因为星期几是随机出来的,所以星期的排列并不是按照从小到大的顺序排列,而是随机排列的。
    2. 因为没有给兴趣标签归类,所以给部门匹配出的兴趣标签会很杂,比如匹配给一个部门加上了游泳和电脑这两个标签,就会感觉这部门不太正经,后期优化下。
    3. 生成数据用了C++输出,然后自己加上格式,并没有用Json的库输出,在但是还是在json_CN上校验通过,输出了正确的Json格式。

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

    数据建模:这部分主要我负责。从生成输入数据的txt中用Json把数据解析出来然后装进部门和学生的结构体数组里。
    核心代码:

    ifstream ifs;
    	ifs.open("input_data.txt");
    	assert(ifs.is_open());
    	Json::Reader reader;
    	Json::Value root;
    if (!reader.parse(ifs, root, false))
    	{
    		return -1;
    	}
    for (int i = 0; i < 300; i++)//给学生结构体数组赋值
    	{
    		int size;
    		size = root["students"][i]["freetime"].size();
    		for (int j = 0; j < size; j++)//给空闲时间赋值
    		{
    			stu[i].free_time[j] = root["students"][i]["freetime"][j].asString();
    		}
    		stu[i].student_no = root["students"][i]["student_no"].asString();//学号赋值
    		size = root["students"][i]["applications_department"].size();
    		for (int j = 0; j < size; j++)//给意向部门赋值
    		{
    			stu[i].applications_department[j] = root["students"][i]["applications_department"][j].asString();
    		}
    		size = root["students"][i]["tags"].size();
    		for (int j = 0; j < size; j++)//给兴趣标签赋值
    		{
    			stu[i].tags[j] = root["students"][i]["tags"][j].asString();
    		}
    	}
    

    匹配程序的思路:这部分主要由伟根负责。先按照学生的意向部门匹配,当部门编号匹配时再进行判断学生的freetime和部门的event schedules是否满足条件,条件为部门某天的活动时间范围小于学生的当天的空闲时间,如果满足,再判断兴趣标签是否有至少一个符合意向部门的兴趣标签,如果有,再判断部门收的人数是否已经达到member_limit,如果没有,则把这个人放入这个部门,然后把该学生的标志修改为已加入。
    原理图:

    核心代码:

    void application(int num)
    {
        for(int i=0;i<5;i++)       //至多5个意向部门 
        {
            for(int j=0;j<20;j++)    //至多20个部门 
            {  
                int count=0;        //计数变量 
                if(stu[num].applications_department[i]==dep[j].department_no)       //第num个学生的第i个意向部门编号匹配到相应部门 
                {
                    set_student(num);                       //对该学生的freetime进行处理 
                    set_department(j);                      //对该部门的event_schedule进行处理 
                    for(int stu_time_count=0;stu_time_count<12;stu_time_count++)     //至多12个空闲时间段  
                    {
                        for(int dep_time_count=0;dep_time_count<12;dep_time_count++ ) //至多12个活动时间段 
                        {
                            if(str1[stu_time_count].compare(str4[dep_time_count])==0)         //匹配星期几 
                            {
                                if(str2[stu_time_count].compare(str5[dep_time_count])>=0&&str3[stu_time_count].compare(str6[dep_time_count])<0)    //时间段比较 
                                {
                                    dep[j].save[count] = stu[num].student_no;         //满足条件就将该学生的学号存入对应的数组 
                                    count++;               //计数加一 
                                    if(count>dep[j].member_limit) continue;
                                }
                            }
                        }
    
                    }
                }   
            }
        }
    }
    

    四、 代码规范

    1、 大括号一定要单独一行
    2、 每个函数都要有注释,解释其功能

    3、 定义一个数组或者变量时,要给出注释说明其功能

    五、 结果评估

    输出的unlucky_student人数比较多,大概一百八左右,原因是匹配程序的选择条件比较简单,先是意向部门编号匹配然后再是时间匹配,而且是由于for语句循环的问题,就较为简单的输出该学生被一个部门入取后不再被其他部门入取。

    六、 结对感受

    这次作业感觉完成的不是很好,主要是因为留给作业的时间太少。由于国庆假期出门旅游,一号出去六号才回来,累得半死七号睡了一天,导致工期严重拖后。。八号才正式开始作业,感觉很对不起自己的队友,是我拖累他了。紧赶慢赶加班熬夜赶才完成了作业的大概,还有很多需要完善的。。真的很想早点回来赶作业,可是无奈票是早就买好的,没法改,花了钱在外面又不能不玩尽兴。。唉,导致作业很赶,自己累也拖累队友,不说了,都是泪。
    这次作业给我最大的收益就是了解了Json这种轻量级的数据交换格式。对代码的输出标准格式有了更深刻的认识,并且掌握了json的数据解析转化,还有熟悉了随机数的用法并且如何在一个给定的范围随机且不重复。
    结对的感受,最大的就是两个人代码风格的差异,所以要制定代码规范。还有遇到问题一定要制定计划,及时沟通,主动联系,不然可能会导致对对方的进度有点不了解且合并代码的时候会因为双方做的接口或者是变量设定不一样导致各种问题,这也仅仅是两个人的小团队,如果是多个人,那会更麻烦,所以学好软件工程是很重要的。还有就是,以后的作业和娱乐一定要安排好= =不能像这次一样这么赶了。

  • 相关阅读:
    protobuf lib库的使用
    protobuf的下载、编译和使用
    使用python和pygame绘制繁花曲线
    经典方块游戏-俄罗斯方块
    经典方块游戏-贪吃蛇
    经典方块游戏-基础
    经典方块游戏一
    Python脚本管理
    SublimeText3设置显示空格及Tab显示为4个空格
    域名解析记录类型
  • 原文地址:https://www.cnblogs.com/n9705/p/7642620.html
Copyright © 2020-2023  润新知