第二次结对编程作业——毕设导师智能匹配
结对学生:翁祖航(031402515),毛仲杰(031402517)
实现方法
我们组用java模拟导师,学生互选的过程。
开发语言:java
开发工具:eclipse
主要的代码及含义如下(数据库截图只含有部分).
1.InitTS类
该类中主要模拟学生,导师互选时填表的过程。由java生成随机数据插入到数据库中,作为输入数据。
输入的数据主要包括
1.初始生成所有的学生信息(学号,绩点),所有的导师(工号,设置的学生数量).
/*
* 初始化学生表。 生成随机数据,模拟随机生成studentNum个学生(随机生成绩点).
*/
public void initStudent() {
DeleteAll("student");
for (int i = 0; i < studentNum; i++) {
int score = new Random().nextInt(100);
int studentID = i + 1;
insertStudent(studentID, score);
}
}
/*
* 向导师表中 插入导师的工号,学生数量。
*/
public void insertTeacher(int teacherID, int studentNum) {
String insertT = "insert into teacher(teacherID,studentNum) values('" + teacherID + "','" + studentNum + "')";
try {
s.execute(insertT);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 初始化导师表。 随机生成导师的学生数量信息。
* 注意:如果随机生成的导师的所有学生数量小于目标的学生数量,则重新生成。
*/
public void initTeacher() {
DeleteAll("teacher");
ArrayList<Integer> arrayList = new ArrayList<>();
int count = 0;
do {
count = 0;
arrayList.clear();
for (int i = 0; i < teacherNum; i++) {
int num = new Random().nextInt(9);
arrayList.add(num);
count += num;
}
} while (count < studentNum);
for (int i = 0; i < teacherNum; i++) {
int studentNum = arrayList.get(i);
insertTeacher(i + 1, studentNum);
}
}
/*
* 调用以上的 两个方法,初始化学生,老师信息。
*/
public void initGenerateTS() {
initStudent();
initTeacher();
}
2.模拟学生填报志愿。学生填报5个志愿(由系统随机生成5个志愿导师的ID).
/*
* 向targetTeacher表中插入学生工号,5个志愿导师的工号。
*/
public void insertTargetTeacher(int studentID, int[] targetTeacher) {
String insertTarT = "insert into targetTeacher(studentID,targetTeacher1,targetTeacher2,targetTeacher3,targetTeacher4,targetTeacher5)"
+ "values('" + studentID + "','" + targetTeacher[0] + "','" + targetTeacher[1] + "','" + targetTeacher[2]
+ "','" + targetTeacher[3] + "','" + targetTeacher[4] + "')";
try {
s.execute(insertTarT);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 模拟 学生选5个志愿的过程。
* 1.获得所有未被导师选中的学生列,以此选中其中一个学生。
* 2.这个学生从导师列(学生数未满)的导师中选择5个导师。
* 3.相应的导师更新他的待选学生列。
*/
public void chooseTargetTeacher() {
DeleteAll("targetTeacher");
for (int i = 0; i < studentList.size(); i++) {
Student current_studnet = studentList.get(i);// 获得当前的学生。
ArrayList<Teacher> target_teacher_list = current_studnet.getTarget_teacher();// 获得学生的目标导师队列。
target_teacher_list.clear();// 将当前学生的目标导师队列清空。
int[] targetTeacher = new int[5];
int bound = teacherList.size();// 获得剩余的导师数量。
for (int j = 0; j < 5; j++) {
int target_teacher_index = new Random().nextInt(bound);// 随机生成选导师的序号。
Teacher target_teacher = teacherList.get(target_teacher_index);// 获得目标导师
targetTeacher[j] = target_teacher.getTeacherID();//添加选中导师的id。
target_teacher_list.add(target_teacher); // 学生填志愿成功,目标导师队列添加导师对象。
target_teacher.getAll_selected_student().add(studentList.get(i));// 导师的对象中添加预选的学生对象。
}
insertTargetTeacher(current_studnet.getStudnetID(),targetTeacher);
}
}
3.模拟导师选择学生。导师从选自己的学生队列中选中自己喜欢的学生。
/*
* 向targetStudent表中添加导师的选中学生的工号。
*/
public void insertTargetStudent(int teacherID,int[] targetStudent)
{
String insertTarS = "insert into targetStudent(teacherID,targetStudent1,targetStudent2,targetStudent3,targetStudent4,targetStudent5,targetStudent6,"
+ "targetStudent7,targetStudent8) values('"+teacherID+"','"+targetStudent[0]+"','"+targetStudent[1]+"','"+targetStudent[2]+"','"+targetStudent[3]+"','"
+targetStudent[4]+"','"+targetStudent[5]+"','"+targetStudent[6]+"','"+targetStudent[7]+"')";
try {
s.execute(insertTarS);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
*
* 模拟导师选学生的过程。
* 1.获得学生数还未满的导师列,依次选中其中一个导师。
* 2.获得当前导师的待选学生列,随机生成此次要选的学生人数,随机从学生列中选中几名学生。
* 3.选中的学生往待选的导师列中添加学生。
*/
public void chooseTargetStudent() {
DeleteAll("targetStudent");
for (int i = 0; i < teacherList.size(); i++) {
Teacher current_teacher = teacherList.get(i);// 获取当前导师
ArrayList<Student> all_selected_student = current_teacher.getAll_selected_student();// 获得该导师的待选学生队列
int leavednum = current_teacher.getLeavednum();// 当前导师还能选几个学生
int randomcount = new Random().nextInt(leavednum + 1);// 随机生成这个导师要选多少个学生。
int[] targetStudent = new int[8];
for (int j = 0; j < randomcount; j++) {
int bound = all_selected_student.size();// 待选学生队列的学生数量。
if (bound == 0) {
break;
}
int index = new Random().nextInt(bound);// 随机生成选中的学生序号。
Student selected_student = all_selected_student.get(index);// 选中的学生。
targetStudent[j] = selected_student.getStudnetID();//添加选中学生的id。
selected_student.getAll_selected_teacher().add(current_teacher);// 选中的学生添加备选的导师队列。
all_selected_student.remove(index);// 选中的学生从备选的学生队列中删除;
}
insertTargetStudent(current_teacher.getTeacherID(),targetStudent);
}
}
4.模拟学生选择目标导师。(因为存在多个导师同时选中一个学生的情况)。学生从自己的待选导师列表中选择一个导师。
/*
* 模拟学生最后选导师的过程(因为同时可能由几个导师同时选中一个学生)
* 1.获得当前还未选中导师的学生列,依次选中其中一个学生。
* 2.从当前学生的待选导师列中,随机选择一位导师。
*
*/
public void chooseTeacher(Student student) {
ArrayList<Teacher> all_selected_teacher = student.getAll_selected_teacher();// 待选的导师队列。
int bound = all_selected_teacher.size();// 待选的导师人数。
if (bound > 0) {
int teacher_index = new Random().nextInt(bound);// 选中的导师序号
Teacher target_teacher = all_selected_teacher.get(teacher_index);// 选中的导师。
int leaved_num = target_teacher.getLeavednum() - 1;// 导师的剩余学生人数减1
target_teacher.setLeavednum(leaved_num);
if (leaved_num == 0) {
target_teacher.setLeavednum(0);// 设置导师的剩余学生人数为0
teacherList.remove(target_teacher);// 导师的剩余学生人数为0,从备选的导师队列中删除。
}
studentList.remove(student);// 学生选中导师,从备用的学生序列中删除。
student.setFinished_teacher(target_teacher);// 学生的导师对象确立。
target_teacher.getStudent_list().add(student);// 导师的所带学生对象确立。
updateStudent(student);
updateTeacehr(target_teacher);
}
}
/*
* 所有学生选中自己的导师。
*/
public void chooseAllTargetTeacher() {
for (int i = 0; i < studentList.size(); i++) {
int current_size = studentList.size();
Student student = studentList.get(i);
chooseTeacher(student);
if (current_size != studentList.size()) {
i--;
}
}
initAllSelectedeTS();
}
2.BackGround类
BackGround类主要模拟后台数据库的数据获取和处理。
1.从数据库中获取学生和导师的信息,存储到Arraylist中。
/*
* 从数据库中获取学生,教师信息,生成ArrayList队列
*
*/
public void initTS(InitTS TS) throws SQLException {
this.initTS = TS;
String getStudent = "select studentID,score from student";
String getTeacher = "select teacherID,studentNum from teacher";
ResultSet resultSetStudent = s.executeQuery(getStudent);
while (resultSetStudent.next()) {
int studentID = resultSetStudent.getInt("studentID");
int score = resultSetStudent.getInt("score");
Student student = new Student(studentID, score);
select_student_list.add(student);
select_student_list_spare.add(student);
}
ResultSet resultSetTeacher = s.executeQuery(getTeacher);
while (resultSetTeacher.next()) {
int teacherID = resultSetTeacher.getInt("teacherID");
int teacherNum = resultSetTeacher.getInt("studentNum");
Teacher teacher = new Teacher(teacherID, teacherNum);
select_teacher_list.add(teacher);
select_teacher_list_spare.add(teacher);
}
TS.setStudentList(select_student_list_spare);
TS.setTeacherList(select_teacher_list_spare);
TS.setPreStudentList(select_student_list);
TS.setPreTeacherList(select_teacher_list);
}
2.实现最后阶段的系统的智能分配。
/*
* 系统后台实现的自动分配算法。
* 1.按照绩点将落选的学生队列重新排列。
* 2.依次选择其中的一位学生,获得他的5个目标志愿导师,若他的导师还有剩余的学生名额则选中该导师。
* 3.剩下是目标导师的名额已经分配完的落选学生,系统为其自动分配。
*
*/
public void autoDistribute() {
Collections.sort(select_student_list_spare);// 为落选的学生排序。
for (int i = 0; i < select_student_list_spare.size(); i++) {
Student student = select_student_list_spare.get(i);// 当前的学生
ArrayList<Teacher> target_teacher = student.getTarget_teacher();// 学生的5个目标导师。
for (int j = 0; j < 5; j++) {
Teacher teacher = target_teacher.get(j);// 学生的当前目标导师。
if (teacher.getLeavednum() > 0) {
teacher.getStudent_list().add(student);// 导师所带的学生队列添加该学生。
student.setFinished_teacher(teacher);// 学生的目标导师确立下来。
select_student_list_spare.remove(student);
int leaved_num = teacher.getLeavednum() - 1;// 导师的剩余学生数量减1.
teacher.setLeavednum(leaved_num);// 设置导师的剩余学生数量。
if (leaved_num == 0) {
select_teacher_list_spare.remove(teacher);// 从备用的导师队列中删除导师。
}
i--;
initTS.updateStudent(student);
initTS.updateTeacehr(teacher);
break;
}
}
}
for (int i = 0; i < select_student_list_spare.size(); i++) {
Student student = select_student_list_spare.get(i);// 当前的学生
int bound = select_teacher_list_spare.size();
int teacherIndex = new Random().nextInt(bound);
Teacher teacher = select_teacher_list_spare.get(teacherIndex);// 学生的当前目标导师。
if (teacher.getLeavednum() > 0) {
teacher.getStudent_list().add(student);// 导师所带的学生队列添加该学生。
student.setFinished_teacher(teacher);// 学生的目标导师确立下来。
select_student_list_spare.remove(student);
int leaved_num = teacher.getLeavednum() - 1;// 导师的剩余学生数量减1.
teacher.setLeavednum(leaved_num);// 设置导师的剩余学生数量。
if (leaved_num == 0) {
select_teacher_list_spare.remove(teacher);// 从备用的导师队列中删除导师。
}
initTS.updateStudent(student);
initTS.updateTeacehr(teacher);
i--;
break;
}
}
}
3.MainTest类(主函数,模拟学生导师互选的整个过程)
public class MainTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
InitTS initTS = new InitTS(30,100);
initTS.initGenerateTS();//模拟生成Teacher表,student表。
BackGround backGroud = new BackGround();
try {
backGroud.initTS(initTS);//后台调用数据库中 teacher表,student表 生成相应的Arraylist队列。
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* 模拟第一轮 学生选导师,导师选学生的过程。
*/
initTS.chooseTargetTeacher();//学生填写5个志愿导师的工号。
initTS.chooseTargetStudent();//导师填写想要带的学生学号。
initTS.chooseAllTargetTeacher();//学生从待选的导师队列中选择一个导师(学生可能有很多导师
/*
* 模拟第二轮 学生选导师,导师选学生的过程。
*/
initTS.chooseTargetTeacher();
initTS.chooseTargetStudent();
initTS.chooseAllTargetTeacher();
/*
* 模拟第三轮 学生先选导师,然后系统按照绩点分配。
*/
initTS.chooseTargetTeacher();
backGroud.autoDistribute();//系统自动分配。
}
}
输入输出的数据库部分截图:
student表:
teacher表:
targetStudent表:
targetTeacehr表:
对算法的评价:
在学生数100,导师人数30的情况下,在经过两轮的选择后大概在10±5的范围内。在第三轮系统分配阶段,在全部学生按照绩点分配后,仍然有一部分学生由于目标的5个导师名额全部分配完而落选。这部分学生一般在5范围内。但系统还是会随机将这些学生分配给名额有剩的导师,这一部分学生相当于完全由系统分配。
不过鉴于整个过程都是系统生成的随机数据,所以个人认为不具备什么参考价值。。。。。。。
本次结对的感受:
由于github,git,coding.net在开发前期基本没有使用过,因为都是同学,开发过程都是在一起做,没有体现出明显的版本的迭代开发,只在最后的完成品出来后,将全部的文件提交上去而已,目前虽然只接触了使用了1,2天,不过确实功能强大,很好用。只不过git bash的使用还不怎么熟练,经常出现一些解决不了的情况。