• 第二次结对作业


    队员

    黄腾飞 170327033
    周静平 170327112

    作业需求分析

    • 使用文件录入20个部门,300个学生
    • 部门含有以下属性:
      1、 名称:单个字符串
      2、 编号:单个字符串
      3、 学生人数上限:单个数值
      4、 特点标签:多个字符串
      5、 多个常规活动时间段
    • 学生含有以下属性
      1、 姓名:单个字符串
      2、 学号:单个字符串
      3、 绩点:单个数值
      4、 意愿部门:小于等于5个的多个字符串
      5、 空闲时间段:多个字符串
    • 进行智能匹配,智能匹配要求如下:
      1、 代码规范
      2、 为输入输出设计标准化、通用化、可扩展的接口
      3、 使用不同优先级匹配
    • 文件输出匹配结果,结果种类如下:
      1、 已匹配结果
      2、 未匹配部门
      3、 未匹配学生
    • 生成可执行的exe文件
    • 结果分析
    • 提交代码到Github
    • 撰写博客

    设计思路

    • 配置文件定义输入输出文件以及优先级(可定义多个优先级)
    • 编写生成输入文件的代码,模拟输入信息
    • 获取部门和学生信息
    • 按照志愿顺序进行匹配
      1、 遍历所有学生(从i到n)
      2、 遍历所有部门(从j到m)
      3、 先按照i学生一志愿进行匹配
      4、 i学生的志愿部门如果已存在匹配列表则加入匹配列表,否则建立一个部门对应多个学生的匹配列表
      5、 一志愿匹配完毕后判断学生数是否达到上限,如果达到则进入下一个学生,否则,继续进入下一个志愿的匹配
      6、 如果配置中存在一个或者多个优先级,遍历每个优先级,如果没有则进入第10步
      7、 如果存在绩点优先则将匹配列表中的学生按照绩点排序,选取绩点前j部门学生人数上限的k个同学,如果k>j,匹配队列进入后续处理(第10步),否则标记学生为已匹配
      8、 如果存在兴趣优先则按照学生兴趣与j部门的特点相同的个进行排序,类似绩点选取学生进行操作
      9、 如果存在空闲时间优先,则类似兴趣优先进行操作
      10、 将匹配数大于上限的匹配列表进行随机筛选部门上限个数的学生
    • 打印匹配信息
    • 优化接口

    代码关键部分

    部门类

    public class Department {
    private String departmentName;  // 名称
    private String departmentCode;  // 编号
    private Integer studentLimit;   // 限制学生数[0-15]
    private ArrayList<String> characteristics = new ArrayList<>();  // 特点标签
    private ArrayList<String> routineActivityTime = new ArrayList<>();  // 常规活动时间
    private boolean ismatch = false;    //  是否匹配标识
    ...
    (get和set函数)
    }
    

    学生类

    public class Student {
    private String studentName = null;  // 姓名
    private String studentCode = null;  // 学号
    private Float gradePoint = null;    // 绩点
    private ArrayList<String> interest = new ArrayList<>(); // 兴趣爱好
    private ArrayList<String> departmentWishes = new ArrayList<>(); // 意愿部门
    private ArrayList<String> freeTime = new ArrayList<>(); // 空闲时间
    private boolean isMatch = false;    // 是否已被匹配
    private int sameInterestsNum = 0;    // 爱好相同数
    private int sametime = 0;   // 空闲时间匹配数
    private boolean ismatch = false;    // 是否匹配标识
    ...
    (get和set函数)
    }
    

    部门与学生的匹配类

    /*记录一个部门匹配多个学生信息*/
    public class D_S_Match {
    private Department department;  // 部门
    private ArrayList<Student> students = new ArrayList<>();    //多个学生
    private String studentStr = "/";    // 用于判断学生是否重复录入
    ...
    (get和set函数)
    }
    

    监测匹配是否存在

    /*监测匹配是否存在*/
    try{
        d_s_matches.get(j);
    }catch (IndexOutOfBoundsException ioobe){
        /*不存在则建立一个匹配*/
        D_S_Match dsm = new D_S_Match();
        departments.get(j).setIsmatch(true);
        dsm.setDepartment(departments.get(j));
        d_s_matches.add(dsm);
        if (!d_s_matchesStr.matches("/"+departments.get(j).getDepartmentCode()+"/")){
            d_s_matchesStr = d_s_matchesStr + departments.get(j).getDepartmentCode() + "/";
        }
    }
    

    意愿匹配部门

    //  志愿级别改变,判断人数是否够了
    if(isChange && d_s_matches.get(j).getStudents().size()>=d_s_matches.get(j).getDepartment().getStudentLimit())break;
    isChange = false;
    /*意愿部门匹配部门*/
    String[] dw = students.get(i).getDepartmentWishes().get(index).split("/");
    if ((dw.length==1 && dw[0].equals(departments.get(j).getDepartmentName())) || (dw.length==2 && dw[0].equals(departments.get(j).getDepartmentCode()))){
        if (!d_s_matches.get(j).getStudentStr().matches("/"+students.get(i).getStudentCode()+"/")){
            d_s_matches.get(j).addStudents(students.get(i));
            break;
        }
    }
    

    使用内置快速排序算法

    /*按绩点降序排序*/
    private void sortByGradePoint(ArrayList<D_S_Match> d_s_matchesCopy){
        for (int i = 0;i<d_s_matchesCopy.size();i++){
            Collections.sort(d_s_matchesCopy.get(i).getStudents(), new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    return s2.getGradePoint().compareTo(s1.getGradePoint());
                }
            });
        }
    }
    

    匹配类使用多构造函数

    public DepartmentOfStudentMatchingImpl(){}
    /*参数是否初始化*/
    public DepartmentOfStudentMatchingImpl(Boolean goInit){
        if (goInit) init();
    }
    

    匹配类初始化

    /*初始化数据-获得部门和学生信息*/
    public void init(){
        if (config==null) config = new Config(true);
        MatchIO matchIO = new MatchIO(config,true);
        if (departments==null) departments = matchIO.getDepartments();
        if (students==null) students = matchIO.getStudents();
    }
    

    接口

    public interface DepartmentOfStudentMatching {
        void init();    // 初始化-获得学生和部门
        void matching();    // 进行匹配运算
        void print();   // 打印匹配结果
        <T> void othersPriority(T priority);    //  其他匹配方式,使用泛型参数
        void setConfig(Config config);  // 设置配置文件
        Config getConfig(); // 获得配置文件
        ArrayList<Department> getDepartments(); // 获得部门信息
        void setDepartments(ArrayList<Department> departments); // 设置部门信息
        ArrayList<Student> getStudents();   // 获得学生信息
        void setStudents(ArrayList<Student> students);  // 设置学生信息
    }
    

    数据

    配置文件数据


    importfile[空格][输入文件地址]
    outputfile[空格][输出文件地址]
    priority(空格)(优先级)(空格)(优先级)(空格)(优先级)

    生成的输入数据

    生成的输出数据

    算法测试报告

    优先条件 匹配学生个数 未匹配学生个数 实际耗时(ms) 输出文件路径
    绩点/兴趣/空闲时间 248 52 47 E:web-appproject第二次结队作业IntelligentMatchsrcconfigoutput.txt
    兴趣/空闲时间 253 47 22 E:web-appproject第二次结队作业IntelligentMatchsrcconfigoutput(1).txt
    绩点 218 92 28 E:web-appproject第二次结队作业IntelligentMatchsrcconfigoutput(2).txt
    绩点/兴趣 240 60 25 E:web-appproject第二次结队作业IntelligentMatchsrcconfigoutput(3).txt

    其中耗时只计算匹配时的耗时

    程序优势

    • 默认使用配置文件来设置输入输出文件以及优先级,有极大的灵活性
    • 默认输入文件格式简单,方便输入
    • 程序可以不使用文件而使用其他方式录入学生和部门信息,保留录入信息的接口
    • 程序可以不使用文件而使用其他方式来录入配置信息
    • 除了默认的4种匹配方式以外,还可以进行重写othersPriority(T priority)来增加匹配方式

    总结感受

    这次的作业相对于上次有较大的难度,上次只是进行原形的设计,需要的是大胆的想想能力和创造能力,这次主要需要的是代码能力和自身的基础积累。这次的作业,在两个人的沟通上,没有上次那么简单,除了基本逻辑之外,在代码上,对于自身写的代码,如果注释不够清晰明了,很难让对方读懂;同时对方的代码注释清晰明了,我也得花段时间捋一捋才能明白。不过还好的是,这些东西在实验室的项目上遇到过,也学了不少东西,在这里不是很大的坎。

    GitHub地址

  • 相关阅读:
    [创建型] 原型模式
    深复制和浅复制讨论
    设计模式扫盲
    selenium定位不到元素 yimu
    Jmeter拓展插件可查看和lr一样的图形结果 yimu
    python用字典实现switch..case类似的函数调用 yimu
    pycharm运行Pytest,有没有将Pytest写入Python代码中的区别 yimu
    Jmeter HTTPS接口测试的证书导入 yimu
    杭电acm2203
    杭电acm1259
  • 原文地址:https://www.cnblogs.com/zjp17/p/7726629.html
Copyright © 2020-2023  润新知