结对编程作业——毕设导师智能匹配

结对编程作业——毕设导师智能匹配

031402317 李佳恺
031402511 黄家俊

问题描述及要求

  • 输入30个老师(包含带学生数的要求的上限,单个数值,在[0,8]内),100个学生(包含绩点信息),每个学生有5个导师志愿(志愿的导师可以重复但不能空缺),要求另外写生成程序随机实现

  • 实现一个智能自动分配算法,根据输入信息,输出导师和学生间的匹配信息(一个学生只能有一个确认导师,一个导师可以带少于等于其要求的学生数的学生) 及未被分配到学生的导师和未被导师选中的学生,要求输出的未被导师选中的学生人数越少越好。

  • 为输入输出设计标准化、通用化、可扩展的接口,为该智能匹配程序模块后期可能的整合入系统提供便利

  • 输入输出的格式,如采用文本文件或数据库的方式输入,可自由讨论确定,但需要明确,为后期可能的整合入系统提供便利

  • 需要为智能匹配算法确立几条分配或排序原则,比如 绩点优先、或其他、或其他等等

编程语言:JAVA

模块设计

  • 实体类(entity)

  • 全局类(global)

  • 方法类(method)

  • 测试类(test)

学生类和导师类的定义

/**学生实体类**/
public class Student {private String sName; // 学生姓名private float gradePoint; // 学生绩点private int[] sapplication = new int[5]; // 学生志愿private int teacherId; // 已选中老师编号
/*** 教师实体类**/
public class Teacher {private int tId;  //教师编号private String tName;  //教师姓名private int sectionMax;  //区间最大值private int sectionRest;  //剩下人数    private List<Student> myStudent = new ArrayList<Student>(); //当前老师下的学生

生成程序代码实现

1. 采用JAVA的random()函数在字符串区间中随机选择5个字符生成学生或导师的姓名

 //生成学生随机姓名,教师姓名方法一样public String createStudentName(){     String stringBase = "abcdefghijklmnopqrstuvwxyz";Random random = new Random();StringBuffer studentName = new StringBuffer();     for (int i = 0; i < 6; i++) {     int number = random.nextInt(stringBase.length()); studentName.append(stringBase.charAt(number));     }     return studentName.toString();          
}

2. random()函数可以产生[0,1]区间的小数,利用其随机产生[1,5]区间的浮点数作为学生绩点

//产生学生的绩点
public float createGradePoint(){Random random = new Random();float gradePoint = random.nextFloat()*4+1;gradePoint =  (float) ((int)((gradePoint*100+5))/100.0);//取小数点后两位return gradePoint;
}

3. 随机产生[1,30]区间的整数作为学生志愿(整数对应导师的Id)

//产生学生的志愿
public int[] creatApplication(){int[] application = new int[5];Random random = new Random ();  boolean[]  bool = new boolean[30];  int randInt = 0;  /**得到5个不同的随机数*/  for(int i = 0; i < 5 ; i++) {  do{  randInt  = random.nextInt(30);  }while(bool[randInt]);   bool[randInt] = true; application[i]=randInt+1;}return application;
}

4. 随机产生[0.8]区间的整数作为老师带学生数的上限

//产生区间上限
public int createSectionMax(){Random random = new Random();int sectionMax = random.nextInt(8);return sectionMax;
}

5. 定义集合来储存100个学生和30个导师(setXXX()方法在学生类和导师类里面定义,用于学生或导师的信息的初始化,另创建class文件定义集合的全局变量)

//产生学生对象
public List<Student> createAllStudent(){CreateMember cm = new CreateMember();List<Student> studentList= new ArrayList<Student>();for(int i=0;i<100;i++){Student s = new Student(); s.setsName(cm.createStudentName());s.setGradePoint(cm.createGradePoint());s.setSapplication(cm.creatApplication());s.setTeacherId(0);studentList.add(s);}return studentList;
}//产生教师对象
public List<Teacher> createAllTeacher(){CreateMember cm = new CreateMember();List<Teacher> teacherList= new ArrayList<Teacher>();for(int i=1;i<=30;i++){Teacher t = new Teacher();t.settId(i);t.settName(cm.createTeacherName());int temp = cm.createSectionMax();Global.countAll+=temp;t.setSectionMax(temp);t.setSectionRest(temp);teacherList.add(t);}return teacherList;
}

匹配算法思想以及代码实现

  • 志愿优先原则,五轮匹配,每轮从选择学生上限未满的导师Id出发,每个导师可以匹配到若干个当前轮次n,学生第n志愿是该老师Id的局部学生集合,并从集合中选择学生

  • 考虑到在上述匹配到的局部学生集合当中学生应当有个排序以实现老师从中筛选出排名靠前的学生,于是这个排序就非常重要

  • 我们知道每个导师的热门程度不同,因此我们定义学生未满的导师有一个热度值heat,并在每轮匹配算法的开始更新heat值,我们先遍历当前轮次全部学生的集合(在代码当中我们是从全部学生的集合当中删掉每轮被选中的学生),得到每个导师共有几个选他的学生sum,然后求出heat=sum/sectionRest(sectionRest为当前轮次老师剩余的选择学生上限)

//设置教师热度值
public class SetTeacherHeat {public void setHeat(){//遍历还在参加选择的教师for(Teacher teacher : Global.teacherList){//累计当前教师此轮的热度值float heat = 0;//遍历还在参加选择的学生for(Student student : Global.studentList){//存储学生志愿int[] tempValue = student.getSapplication();//当学生志愿与当前教师编号,不重复志愿for(int i=0;i<5;i++){if(teacher.gettId()==tempValue[i]){heat++;break;}                   }   }//设置当前教师的热度值heat=heat/teacher.getSectionRest();teacher.setHeat(heat);                  }}}
  • 定义学生有一个综合值composite,每轮匹配算法开始的时候更新其值,其值为该学生绩点gradePoint * g + 该学生剩余志愿导师热度值之和 * v,根据该值进行当前导师的局部学生集合的学生排序。老师选择学生的时候看的是学生的绩点,但是为了让更多的学生能够选到导师,我们认为可以看每个学生选的导师的热度值之和,热度值高代表其竞争压力大,综合绩点和热度值来进行排序。其中g + v = 1 ,其比例我们经过多次测试为g=0.5.v=0.5最为合理。

//获得此轮当前学生临时综合值
public class GetTempComposite {public float getComposite(Student student,int round){//获得学生志愿int[] tempValue = student.getSapplication();//记录学生此轮综合值int tempComposite=0;//变量此轮及之后学生志愿所选教师的热度        for(int i=round;i<=round;i++){//志愿不重复,找到相符就跳出for(Teacher teacher : Global.teacherList ){//当前志愿与教师id相符if(tempValue[i]==teacher.gettId()){//累加tempComposite+=teacher.getHeat();break;}               }       }       return tempComposite;}}
    //更新学生综合值,系数比例g,v;for(Student student : tempStudentList){GetTempComposite gtp = new GetTempComposite();float tempComposite = 0;tempComposite = gtp.getComposite(student, round);float composite=0;float gradePoints=0;gradePoints = student.getGradePoint();composite=gradePoints*g+tempComposite*v;        student.setComposite(composite);}
    // 实现学生按综合值从大到小排序class SortByGradePoint implements Comparator {public int compare(Object o1, Object o2) {Student s1 = (Student) o1;Student s2 = (Student) o2;float temp1=s1.getComposite();float temp2=s2.getComposite();if (temp1 < temp2)return 1;else if (temp1 == temp2) {return 0;}return -1;}}
  • 进行第n轮匹配:

    1. 设置教师列表迭代器来遍历导师集合
    // 设置教师列表迭代器Iterator<Teacher> teacherIterator = Global.teacherList.iterator();

2. for循环遍历学生集合,学生第n志愿为当前导师的Id则列入局部学生集合变量

    List<Student> tempStudentList = new ArrayList<Student>();for (Student student : Global.studentList) {int[] application = student.getSapplication();//学生第round个志愿与教师匹配if (application[round] == teacher.gettId()) {// System.out.println(student.getsName() + "----此轮志愿选择---"// + teacher.gettName());// 将此志愿的学生加到临时列表中tempStudentList.add(student);}}

3. 如果集合内的学生总数大于等于老师的可选择的学生人数上限,则根据集合内学生的排名,选择排名靠前的等于老师选择学生人数上限的学生,并把被选择的学生从全部学生的集合中删除,将导师的可选择学生人数上限置零,并把该导师从导师集合中删除

    // 按绩点从大到小排序Collections.sort(tempStudentList, new SortByGradePoint());// 获得该教师当前限选人数int sectionCurrent = teacher.getSectionRest();/*** 当前申请列表人数大于等于设置人数*/if (tempStudentList.size() >= sectionCurrent) {List<Student> myStudentList = new ArrayList<Student>();for (int i = 0; i < sectionCurrent; i++) {Student s = tempStudentList.get(i);myStudentList.add(s);// 将该学生列表添加到当前教师目录下teacher.addStudent(s);// 将该学生从总学生列表中移除Global.studentList.remove(s);Global.countStu++;checked++;}// 更新该老师剩余人数为0sectionCurrent = sectionCurrent - sectionCurrent;teacher.setSectionRest(sectionCurrent);// 将当前教师存入已完成分配的集合中Global.doneTeacherList.add(teacher);// 将该老师从总教师列表中删除teacherIterator.remove();}

4. 如果集合内的学生总数小于老师的可选择的学生人数上限,则把集合内的学生添加到老师已选择学生的集合里面,并把集合内的学生从全部学生的集合中删除,将导师的可选择学生人数上限更新

   else {/*** 当前申请人数小于限选人数*/sectionCurrent = sectionCurrent - tempStudentList.size();// 更新当前教师剩余人数teacher.setSectionRest(sectionCurrent);for (int i = 0; i < tempStudentList.size(); i++) {Student s = tempStudentList.get(i);// 将该学生添加到当前教师目录下teacher.addStudent(s);// 将该学生从全局学生列表中移除Global.studentList.remove(s);Global.countStu++;checked++;}
}
  • 共五轮,在匹配算法方法中加入参数round表示第几轮,另外建立class文件编写主函数实现算法的调用

      public void allocteStudent(int round) {

这是我们进行g和v数值测量得到的结果


输出和主函数

  • 在PrintUtils.java中定义方法输出总的学生和导师信息以及调用匹配算法后详细地结果


  • 在test.java中调用各种方法实现导师选择以及最终输出未被导师选择的学生人数(输出结果在附件中)

  • !!!!一次随机输入的输出结果


总结

软工第一次写代码很慌很慌,一开始是懵逼的,觉得很难的样子,但其实只要开始认真地思考问题,总能慢慢地解析题目,找到突破点,以及通过揣摩老师的要求慢慢地完善代码。代码完成实现输入输出的那一刻很开心。

一次作业任务下来,我们讨论了3次,花费了5个多小时,第一次讨论围绕了生成程序代码的编写和匹配算法的主要思想,这时候我们还没有导师热度值的想法,第二次是项目的建立以及git的使用,实现在coding.net上面提交代码和文件,第三次是对匹配算法的优化,我们提出了热度值的想法,一次一次的讨论,都是为了能在作业当中获得更高的分数,以及实现对自己的突破,并且博客的编写也经过了两个人多次的整合,努力完善博客的内容。

结对感受

  • 对于第一次结对编程,其中的感受是有好有坏的。好处在于两个人的力量无疑比一个人强大很多,并且不是简单的1+1,比如在生成程序和匹配算法思想的讨论当中,我先提出自己的想法,队友马上就能在我的想法上面衍生出更多的想法,并且能发现对方想法当中的缺点并且共同思考改进的方法,提高了工作的效率和减少代码编写当中犯错的次数。坏处在于代码的分工,两个人编写代码的习惯也不同,这就对代码整合造成困难,这是我们作为一个团队在合作当中需要磨合和学习的,所以在结对过程当中我们也认识到这个困难并克服。

  • 李佳恺:“黄家俊的编写代码的能力比我强很对,Java学的比我深入,比我熟悉,所以在结对当中他完成代码的部分较多,所以工作量占得也比较多,而且这是主动去做的,这一点我很不好意思也很感谢,所以我也尽最大努力地写好随笔,希望能为两个人获得更高的分数,并且我需要加紧Java的学习,毕竟后面还有团队的项目,加油!”

  • 黄家俊:“在此次结对编程中,感受最深的应该是团队交流吧。在整个过程中我和佳恺的交流基本上不存在障碍,我们都能从对方的表达中得到明确的信息,很容易将各自表达的观点扩展开来讨论。其中很关键的一点是,在编码过程中我遇到一个难题,自己一个人想了许久没找到根源,然后在和佳恺交流过程中,灵光一闪,找到了解决的方法。所以在这次合作中,愈发感觉到团队合作的重要性,希望之后还有合作的机会。”

我们的代码----Coding.net

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OptaPlanner - 把example运行起来(运行并浅析Cloud balancing)

经过上面篇长篇大论的理论之后&#xff0c;在开始讲解Optaplanner相关基本概念及用法之前&#xff0c;我们先把他们提供的示例运行起来&#xff0c;好先让大家看看它是如何工作的。OptaPlanner的优点不仅仅是提供详细丰富的文档 &#xff0c;还为各种应用场景提供丰富的示例&am…

软件产品案例分析

软件产品案例分析 第一部分&#xff1a; 评测&#xff1a; 上手体验&#xff1a; 说实话&#xff0c;在老师布置这个作业之前我确实不知道有K米这个APP&#xff0c;我想这是很少去KTV的原因吧。。。不过在接到这个作业后&#xff0c;我就去百度了普及了一下这个app的相关知识。…

vue --- 2.0 编译的实现

初识 假设html中有如下dom: <div id"app"><!-- 插值绑定 --><p>{{name}}</p><!-- 指令解析 --><p l-text"name"></p><p>{{age}}</p><p>{{doubleAge}}</p><!-- 双向绑定实现 -->…

vue --- configureWebpack模拟后台数据

初识 使用vue/cli搭建的项目可以在vue.config.js中,模拟一个后台(express写法)vue.config.js configureWebpack: {devServer: {// 模拟后台服务器 express写法before(app) {app.get(/api/login, function(req, res) {const { username, passwd } req.query;console.log(user…

Linux:客户端的实现

写了一个简单的服务器软件&#xff0c;但是没有写客户端。现在我将客户端实现了&#xff0c;其实昨天已经说了客户端的实现步骤了。 步骤&#xff1a; socket() 初始化 connet()链接 从标准输入读数据fgets() 传数据到服务器write() 读从服务器返回的数据read() 写数据到屏幕上…

HTTP 1.1与HTTP 1.0的比较

HTTP 1.1与HTTP 1.0的比较 一个WEB站点每天可能要接收到上百万的用户请求&#xff0c;为了提高系统的效率&#xff0c;HTTP 1.0规定浏览器与服务器只保持短暂的连接&#xff0c;浏览器的每次请求都需要与服务器建立一个TCP连接&#xff0c;服务器完成请求处理后立即断开TCP连接…

python全栈开发-json和pickle模块(数据的序列化)

一、什么是序列化&#xff1f; 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化&#xff0c;在Python中叫pickling&#xff0c;在其他语言中也被称之为serialization&#xff0c;marshalling&#xff0c;flattening等等&#xff0c;都是一个意思。 为什么要序列化…

Gale-Shapley---婚姻匹配算法算法

原文链接&#xff1a;http://blog.csdn.net/cscmaker/article/details/8291131 &#xff08;一&#xff09;问题的引出&#xff1a; 有N男N女&#xff0c;每个人都按照他对异性的喜欢程度排名。现在需要写出一个算法安排这N个男的、N个女的结婚&#xff0c;要求两个人的婚姻应该…

工具:meson+ninja(安装问题解决)

问题1&#xff1a;Python版本问题 报错信息&#xff1a; NOTICE: You are using Python 3.6 which is EOL. Starting with v0.62.0, Meson will require Python 3.7 or newer ubuntu 18默认的python3是3.6. 解决方案1&#xff1a;从源码安装python 3.7 wget https://www.pyth…

配置 --- vscode自定义代码段Snippets

目标 在vscode中输入vbs-vue 然后产生一个自己想要的模板 写好模板 在线上写好模板传送门: https://snippet-generator.app/ 1是标题,对应 2是前缀.对应在vue中使用的快捷键 vbs-vue3就是需要显示的代码段了 在vscode中配置 1.ctrlshiftp2.选择 Preferences: Configure U…

透明图与元素居中

1,定位让元素居中 1. 透明度 opacity 默认值是1 不透明 0是全透明转载于:https://www.cnblogs.com/Shinigami/p/9709382.html

配置 --- vscode中react格式化解决方案

选择右下角的语言 在弹出框搜react选择 JavaScript React(或者根据需求选择 TypeScript React) 快捷键, windows下 Alt SHIFT F

【商城购物车】购物车逻辑

转载于:https://www.cnblogs.com/xuzhengzong/p/8746677.html

PHP递归实现无限极分类

PHP递归实现无限极分类 摘要 今天在编码的时候要用到二级的栏目分类&#xff0c;所以顺便就把无限极分类给整理了一下&#xff0c;采用的是递归方法 //实现无限级分类public function getTree(){$categorys Category::all();return $this->makeTree($categorys, cate_id,…

react --- 生命周期 给子组件传递数据

子组件 /src/components/LifeCycle.js import React, { Component } from reactexport class LifeCycle extends Component {constructor(props) {super(props);// 常用于初始化状态(状态初始化、属性初始化)console.log("1.组件构建函数执行");}componentWillMoun…

Vue---mock.js 使用

mockjs 概述 在我们的生产实际中&#xff0c;后端的接口往往是较晚才会出来&#xff0c;并且还要写接口文档&#xff0c;于是我们的前端的许多开发都要等到接口给我们才能进行&#xff0c;这样对于我们前端来说显得十分的被动&#xff0c;于是有没有可以制造假数据来模拟后端接…

react --- 按需加载组件

问题描述 使用 antd库时使用按钮,须导入如下 import Button from antd/lib/button import antd/dist/antd.css这样会导入全局的样式. 解决方案,配置按需加载 1.安装 react-app-rewired取代 react-scripts, 可以扩展webapack 的配置, 类似vue.config.jsnpm install react-ap…

flask 实现异步非阻塞----gevent

我们都知道&#xff0c;flask不支持异步非阻塞的请求&#xff0c;我们可以创建一个新项目去测试一下&#xff0c;推荐大家使用pycharm去开发我们的flask 使用特别的方便。 rom flask import Flask import time app Flask(__name__) app.route(/) def hello_world():time.slee…

Axure下拉框级联操作

现实生活中有很多的下拉框是级联操作的&#xff0c;即因为第一个下拉框的选择&#xff0c;影响到后面的下拉框的选择的列表的数据。或许在代码中&#xff0c;这些操作相对比较简单&#xff0c;通过前一个下拉框的选择项来控制后一个下拉框的数据的动态添加。那么&#xff0c;如…