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

31402631 王凌杰

03140264 李烈争

Coding.net链接

问题描述

  • 目标

实现一个毕业生导师智能分配的程序.

  • 输入

老师:30人、老师要求选择的学生数:0~8
学生:100人、绩点、学生的五个志愿

  • 输出

根据输入的信息,输出选择的结果,要求一个学生只能有一个老师,一个老师可以有
0~8个学生,未分配的老师和学生。尽可能少的学生和老师未匹配。

问题分析

第一次讨论的时候,我们打算将各种因素综合起来,合并成老师-学生相互选择的一个权重
然后进行分配,这时候就遇到了下面的问题。影响选择的因素有学生的绩点,志愿,老师的
意愿。在多因素下如何分配各个因素的权重?这个问题讨论了很久,建一个数学模型?有点
困难?各因素乘上一个比例系数,比例系数该如何确定?人为确定吗?如何保证客观公正合理
?匹配一般都是对两个对象建立联系并赋予一定的权值,来体现关系的优先。那么又回到上
面的问题。回过头将导师分配的流程走一遍发现,其实我们不用考虑这样问题。

在流程图中,老师同意学生的选择,对老师来说,不管学生绩点的高低,都是他想要的学生,
所以从老师的角度看,不用管这些学生的先后顺序。但从学生的角度看,绩点某种程度上体现
这个学生那么多个学期的努力。故按绩点将所有学生排序,将绩点高的学生优先分配,然后再
按志愿顺序分配还有名额的老师。执行三轮分配,若还有学生没有选到老师则进行人工干预。
(不过这个概率很低)。

编码环境

Visual Studio 2015
MySql
Navicat For MySql
语言:C#、SQL

代码分析

主函数

    static void Main(string[] args)
    {
        int ResultCount =0;    //结果个数
        int StudentCount =100; //学生个数
        int TeacherCount = 30; //教师个数
        
        DeleteData();          //清空数据
        Console.WriteLine("清空数据成功");
        RandomStudent(StudentCount);  //随机生成学生
        Console.WriteLine("随机学生成功");
        RandomTeacher(TeacherCount);  //随机生成教师
        Console.WriteLine("随机教师成功");


        Console.ReadLine();

        //第一轮选择
        StudentChoice("choice");
        Console.WriteLine("第一轮学生选导师成功");
        TeacherChoice("choice");
        Console.WriteLine("第一轮导师选学生成功");

        Console.ReadLine();
        //第二轮选择
        ResultCount = MySqlReadReturnCount("SELECT * FROM result");//获取结果个数

        //判断所有学生是否都已经分配完毕
        if (ResultCount < StudentCount)
        {
            StudentChoice("secondchoice");
            Console.WriteLine("第二轮学生选导师成功");
            TeacherChoice("secondchoice");
            Console.WriteLine("第二轮导师选学生成功");
        }
        else
        {
            Console.WriteLine("选择导师完毕");
        }

        Console.ReadLine();

        ResultCount = MySqlReadReturnCount("SELECT * FROM result");//获取结果个数
        //判断所有学生是否都已经分配完毕
        if (ResultCount < StudentCount)
        {
            StudentChoice("thirdchoice");
            Console.WriteLine("第三轮学生选导师成功");
            TeacherChoice("thirdchoice");
            Console.WriteLine("第三轮导师选学生成功");
        }
        else
        {
            Console.WriteLine("选择导师完毕");
        }

        Console.ReadLine();


    }

主要函数分析

随机数的生成

    private static void RandomTeacher(int TeacherNumber)//随机生成老师
    {
        string InsertString;
        string TmpID;
        string TmpStudentCount;

        try
        {
            for (int i = 0; i < TeacherNumber; i++)
            {
                TmpStudentCount = NewStudentCount();//随机生成预选学生数
                TmpID = NewID();//根据时间随机生成ID
                InsertString = "INSERT INTO teacher(TeacherID,StudentCount,ChoiceStudentCount) VALUE('" + TmpID + "','" + TmpStudentCount + "', '0' )";
                MySqlWrite(InsertString);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }


      private static void RandomStudent(int StudentNumber)//随机生成学生
    {
        string InsertString;
        string TmpID;
        string TmpGPA;

        try
        {
            for (int i = 0; i < StudentNumber; i++)
            {
                TmpGPA = NewGPA();//随机生成绩点
                TmpID = NewID();//随机生成ID
                InsertString = "INSERT INTO student(StudentID,GPA,IsSelect) VALUE('" + TmpID + "','" + TmpGPA + "', '0' )";
                MySqlWrite(InsertString);
            }
        }
        catch(Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

模拟师生互选函数

   private static void StudentChoice(string TableName)//模拟学生选择导师   TableName为进行分配操作的表名
    {

        //string SelectString = "select * from teacher order by rand() limit 5";
        string SelectTeacherString = "SELECT * FROM teacher WHERE StudentCount != ChoiceStudentCount";
        string SelectStudentString = "SELECT * FROM student WHERE IsSelect ="+0;
        int Count = MySqlReadReturnCount(SelectTeacherString);//还未选满的老师个数
        Console.WriteLine(Count);
        int StudentCount = MySqlReadReturnCount(SelectStudentString);//还未选中学生的个数
        string[] TeacherID = new string[5];
        string TmpID;

        string[] StudentID = MySqlReadArray(SelectStudentString, "StudentID");//获取还未被选中的学生ID

        //每个学生选5个志愿 
        for(int i = 0;i<StudentCount;i++)// StudentCount 为学生个数
        {
            TeacherID = MySqlReadRandom(SelectTeacherString, "TeacherID", Count,5);//获取随机的五个志愿老师ID
        
            for (int f = 0; f < WillCount; f++)//WillCount 为志愿个数
            {
                TmpID = NewID();//生成ChoiceID
                string InsertString = "INSERT INTO "+ TableName + "(ChoiceID,StudentID,TeacherID,WillNumber,IsSelect) VALUE('" + TmpID + "','" + StudentID[i] + "','" + TeacherID[f] + "','"+(f+1).ToString()+ "','" + 0 + "')";
                MySqlWrite(InsertString);//往志愿选择表(choice)添加数据
                Console.WriteLine(TmpID);
            }
        }

    }

     private static void TeacherChoice(string TableName)//模拟导师选择学生      TableName为进行分配操作的表名
    {
        string SelectTeacherString = "SELECT * FROM teacher WHERE StudentCount != ChoiceStudentCount"; //用于查找剩余的导师
        string SelectStudentString = "SELECT * FROM student WHERE IsSelect =" + 0;  //用于查找剩余的学生给你
        string SelectChoiceString = "SELECT * FROM "+ TableName;  //用于访问TableName表
        string UpdateChoiceString;  //用于更新TableName表
        string SelectStudentByChoiceString;  //用于获取TableName表中的StudentID
        string SelectStudentCountByTeacher;  //用于获取teacher表中的StudentCount
        //随机选择
        int ChoiceCount = MySqlReadReturnCount(SelectChoiceString);

        Random TmpRandom = new Random();

        //暂定百分之五十至百分之九十的选定
        int RandomNumber = TmpRandom.Next(ChoiceCount/2, ChoiceCount/10*9);

        string[] ChoiceID = MySqlReadRandom(SelectChoiceString, "ChoiceID", ChoiceCount, RandomNumber);

        //模拟导师选中学生
        for (int i = 0; i < RandomNumber; i++)
        {
            UpdateChoiceString = "UPDATE " + TableName + " SET IsSelect=" + 1 + " WHERE ChoiceID ='" + ChoiceID[i] + "'";//IsSelect用于判断学生在这轮是否被导师选中
            MySqlWrite(UpdateChoiceString);
            Console.WriteLine(ChoiceID[i]);
        }

        //进行分配
        //根据学生绩点排序开始分配老师
        string SelectStudentOrderGPA = "SELECT * FROM student  WHERE IsSelect = 0 ORDER BY GPA DESC";
        int StudentCount = MySqlReadReturnCount(SelectStudentOrderGPA);//获取还未被选中的学生个数
        Console.WriteLine(StudentCount);

        string[] TmpTeacherID = new string[10];
        string[] StudentID = MySqlReadArray(SelectStudentOrderGPA, "StudentID");//获取还未被选中的学生ID
       

        for (int i = 0; i < StudentCount; i++)
        {
            //一个学生有多条选中信息,按志愿顺序开始分配老师
            SelectStudentByChoiceString = "SELECT * FROM "+ TableName + " WHERE StudentID = '" + StudentID[i] + "' AND IsSelect = 1 ORDER BY WillNumber ASC";
            TmpTeacherID = MySqlReadArray(SelectStudentByChoiceString, "TeacherID");
            if (TmpTeacherID != null)
            {

                for (int j = 0; j < TmpTeacherID.Length; j++)
                {
                    SelectStudentCountByTeacher = "SELECT * FROM teacher WHERE TeacherID = '" + TmpTeacherID[j] + "'";
                    int TmpStudentCount = int.Parse(MySqlReadReturn(SelectStudentCountByTeacher, "StudentCount"));//获取老师要选的学生总数
                    int TmpChoiceStudentCount = int.Parse(MySqlReadReturn(SelectStudentCountByTeacher, "ChoiceStudentCount"));//获取老师已选的学生总数

                    if (TmpStudentCount > TmpChoiceStudentCount)//若老师人数未满
                    {
                        //Console.WriteLine(StudentID[i]);
                        MySqlWrite("INSERT INTO result(StudentID,TeacherID) VALUE('" + StudentID[i] + "','" + TmpTeacherID[j] + "')");//更新结果表
                                                                                                                                      
                        MySqlWrite("UPDATE student SET IsSelect = 1 WHERE StudentID = '" + StudentID[i] + "'");//更新学生数据为已被选中
                                                                                                              
                        AllResultCount++;//所有结果条数
                        TmpChoiceStudentCount++;/老师已选学生数++
                        MySqlWrite("UPDATE teacher SET ChoiceStudentCount =" + TmpChoiceStudentCount + " WHERE TeacherID ='" + TmpTeacherID[j] + "'");//更新老师数据已选人数
                        Console.WriteLine(AllResultCount+"学生" + StudentID[i] + "分配成功");
                        break;/选中老师跳出循环,对下个学生进行分配
                    }
                }
            }

        }

    }

其他函数

结果分析

生成数据

student表

teacher表

控制台界面

第一轮选择

模拟学生选择导师
控制台界面

choice表(志愿表)

100个学生 每个学生5个志愿 总共有500条记录
因为初始志愿导师还没有选择所以IsSelect都为0

模拟导师选择学生
控制台界面

choice表

IsSelect纪录该导师是否选择了该学生
result表:

student表

IsSelect纪录学生是否中选

重复轮数

小结&感想

王凌杰

本次结对编程我学会了git的基本使用,同时也对毕设导师匹配系统有了更为深刻的理解和思考。
本来我们也想像其他组那样用算法全自动匹配,然而考虑到很多数学建模的问题,而且感觉有很
多不符合实际的假设。于是我们决定实现模拟人为选择,再设计匹配方式进行匹配。我们匹配思
路主要在模拟导师选择学生之后,即实现按学生绩点来作为学生进行匹配的顺序的依据,而把志
愿顺序作为单个学生匹配不同志愿导师的顺序依据。
除了匹配,本次让我印象深刻的实现随机不重复的从数据库中调出数据。原本打算用"select *
from teacher order by rand() limit 5"直接在数据库中实现,但效率出奇的低,于是便参考了
一些算法,由于时间较赶最后决定用比较Low的list.contain 来判断。

李烈争

学会Git的基本使用,感谢助教推荐的Git博客,很详细。看学长的博客感叹markdown还可以那样用。
各种锚点。可以,很强!感谢队友的大腿,编码过程中耐心的讲解,我代码的能力有待提高。考虑的
过程中思维不够严谨,遗漏一些重要的点,拖了进度。两个人交流的时候要组织好后表达,可以提高
效率。

原文地址:https://www.cnblogs.com/WLJ96/p/5924807.html