高级软件工程团队结对作业(学生部门智能匹配)

部门与学生的智能匹配的程序

结对成员

170320053 林静

170327109 张梨贤


2.输入数据

关键数据样例: (https://files.cnblogs.com/files/zlxbky/import.pdf)

考虑因素:

20个部门
部门编号(唯一确定值),部门编号先事先设定好,就把部门编号固定为A10000~A10019,下面学生的意愿还要用到,所以用一个字符串数组存起来;
部门需要的学生数上限:由于限定范围在0~15,所以就是直接随机产生0~15的一个随机数;
部门的特点标签:事先设定多个标签,用数组存起来。生成部门对象时,随机生成3个0-便签数组之间的不重复的数字,在根据数字作为数组下标到标签数组里面找到该标签并输出。
部门常规活动时间:这个的处理方式跟标签类似。考虑到实际情况,部门的活动时间大多是在“10:30~11:30”,“16:30~18:00”,“20:00~21:30”三个时间段,所以我们先预设了21个时间段,一周7天,每天三个,共21个,并用数组存起来。随机生成3个0-时间数组之间的不重复的数字,在根据数字作为数组下标到时间数组里面找到该时间并输出。
300个学生
部门编号(唯一确定值):学生编号先事先设定好,就把学生编号固定为1703271000~1703271299,用一个字符串数组存起来;
绩点成绩,单个,数值(随机生成一个0-10之间的浮点类型数值);
兴趣标签,多个,字符(学生的兴趣标签一定是所有部门特点标签里面的)
意向志愿,每个学生有不多于5个的部门意愿(不能空缺);
空闲时间段,多个,字符。
  • 部门

部门编号:部门编号唯一,从A10000到A10019

部门需要的学生数上限:限定范围定为0-15,即随机产生0-15中的一个数字

部门的特点标签:生成部门对象时,随机生成3个0-便签数组之间的不重复的数字,在根据数字作为数组下标到标签数组里面找到该标签并输出。

部门常规活动时间:随机生成3个0-时间数组之间的不重复的数字,在根据数字作为数组下标到时间数组里面找到该时间并输出。

  • 学生

学生编号:学生编号唯一,学生编号先事先设定好,就把学生编号固定为1703271000~1703271299,用一个字符串数组存起来;

学生名字:从姓氏数组中随机产生一个姓,以及从名字数组中随机产生两个字,组合成名字。
绩点成绩:随机生成绩点成绩,从高到低排序,当意愿相同时优先考虑绩点高的学生

兴趣标签:在生成学生对象时,随机生成3个不重复的兴趣标签。

部门意愿:在生成学生对象时,随机生成1-5个部门意愿。

空闲时间段:在生成学生对象时,随机生成3个不重复的空闲时间段。

3.匹配算法

数据模型

类图

流程图

算法匹配过程

  • Step1:生成300个学生对象(其中包含学号,姓名,兴趣标签,空闲时间段等基础数据)和部门对象(其中包含部门编号,部门标签,常规活动时间段)。
  • Step2:为了不让后生成的学生的优先级过低导致不能进入部门,首先根据绩点进行从高到低进行排序,绩点高的有优先选择权。
  • Step3:在第二步的前提下,以第一志愿优先原则:遍历其第一志愿,当第一志愿对应的部门的人数没有满的情况下,进行匹配判断,匹配判断分为以下两步:
  • Step 3.1 进行时间判断,将学生的空闲时间段与部门的常规活动时间段进行匹配,当三个时间段中有1个时间段互相匹配,进行下一步判断。
  • Step 3.2 时间判断满足的情况下,进行标签匹配。将学生的兴趣标签与部门的标签进行一一对比,当3个兴趣标签中有1个互相匹配,即满足判断,更新学生信息与部门信息(学生:加入部门信息、加入部门数 部门:成员信息、部门人数、部门人数上限等。
  • Step4 对所有的学生,依旧按照成绩排名遍历其所有志愿,当其志愿对应的部门的人数没有满的情况下,进行匹配判断,匹配判断分为以下两步:同上。
  • Step 5 直到遍历完所有学生的所有部门意愿为止,匹配算法截止。

结果分析

部门纳新比例稳定在70%左右。因为纳新部门人数是随机生成的,所有每次的数据量不同,录取比例基本稳定在70%左右。

条件| 学生人数 | 部门纳新人数 | 加入学生数 | 部门招收比例 | 输出匹配学生文件路径|输出匹配部门文件路径
|----- | -----| -----| ---- | -------------------------|-----------|--------|---------|
绩点+时间+标签|300|119|81 | 68%| https://files.cnblogs.com/files/zlxbky/output_conditionS.pdf) | https://files.cnblogs.com/files/zlxbky/output_conditionD.pdf)

4.关键代码解释

  • 实体类(entity)
  • 全局类(global)
  • 方法类(method)
  • 程序入口(main)

实体类(学生类和部门类)

/*学生实体类*/
    private String St_id; //学号
    private String St_name;  //名字
    private float St_grade;  //绩点
    private int [] St_volunter = new int[5];  //学生志愿
    private String [] St_interest=new String [5]; //兴趣标签
    private String [] St_time=new String [5]; //可用时间段
    private List<Dept> myDept = new ArrayList<Dept>(); //当前学生所在部门
/*部门实体类*/
    private  String Dept_id;  //部门编号
    private String [] Dept_tags=new String [5];  //部门标签
    private String [] Dept_time=new String [5];   //部门时间
    private int Dept_num; //部门人数
    private List<Student> myStudent = new ArrayList<Student>(); //当前部门下的学生

生成学生和部门对象的程序

/*生成学生对象*/
public  String createSid(int i){.....}//生成学生学号
public String createSname(){....}//生成学生名字
public int[] creatVolunter(){....}//生成学生部门志愿数组
public float createGrade(){....}//生成学生绩点
public String[] createStime(){....}//生成学生空闲时间
public String[] createStags(){....}//生成学生兴趣标签
public List<Student> createAllStudent(String Sid[],Float SGrade[]){....}//生成学生对象列表
/*生成部门对象*/
public  String createDid(int i){.....}//生成部门编号
public String[] createDtime(){....}//生成部门常规活动时间
public String[] createDtags(){....}//生成部门标签
public List<Dept> createAllDept(){....}//生成部门对象列表

全局类

public class Global {
    public static List<Student> studentList;
    public static List<Dept> deptList;
    public static List<Student> tempdeptList;
     public static Map<Float,String> map;
}

对绩点进行排序

/*对学生绩点进行降序排序*/
public class SetStudentGrade {

    public  static  Map<Float,String> setStudentGrade( ){

        Map<Float,String> map = new TreeMap<Float,String >(
                new Comparator<Float>() {
                    public int compare(Float obj1, Float obj2) {
                        // 降序排序
                        return obj2.compareTo(obj1);
                    }
                });

        for (int i = 0; i < Global.tempdeptList.size(); i++) {
            String id = Global.tempdeptList.get(i).getSt_id();
            map.put(Global.tempdeptList.get(i).getSt_grade(),id );
        }
        return map;
    }

}

匹配方法

public class Matching {
    public static void allocteStudent(int round) {.....}
    }

输出工具类

public class PrintUtils {
    //打印所有的学生对象
    public static void printStudent(List<Student> stulist) throws IOException {....}
    //打印所有的部门对象
    public static  void printDept(List<Dept> deptlist,int d_num[])throws IOException{....}
     //打印部门纳新总人数和匹配人数
    public static  void printNum(List<Dept> deptlist,int d_num[])throws IOException{....}
    //打印匹配好的学生对象
    public static  void printStudentDept(List<Student> studentList)throws IOException{....}

结对感受

由于上一次的结对作业仅仅是原型设计,实现起来可谓是尽情发挥自己的想象力了。然而这次涉及到真正的代码实现,那就产生了较大的难度了。首先,结对作业给我很大的感觉就是要提前规划好个人的分工,不然到了最后会手忙脚乱。其次,要注意代码的规范性问题。结对作业不比个人项目,只要自己看懂就好了,结对作业可能需要你适当的写上注释必要时候可能还需要文档吧。不然看对方的代码真的又耗时又痛苦。而且,结对作业不比个人项目,个人项目由于缺少了那份团队意识感,可能会相拖沓,而结对作业会催促着你早点完成自己的部分不要拖队友的后腿。其实这样的结对编程在实验室项目当中已经有所体验了,所以在实施上没有遇到特别大的难度。

posted @ 2017-10-24 23:43  林逗号  阅读(270)  评论(0编辑  收藏  举报