瀏覽代碼

自动分班,没有最优解提示手动排

lrf 1 年之前
父節點
當前提交
49c625177d
共有 1 個文件被更改,包括 30 次插入19 次删除
  1. 30 19
      app/service/class.js

+ 30 - 19
app/service/class.js

@@ -1,6 +1,5 @@
 'use strict';
 
-
 const assert = require('assert');
 const _ = require('lodash');
 const { ObjectId } = require('mongoose').Types;
@@ -33,7 +32,8 @@ class ClassService extends CrudService {
     if (!newclass) {
       throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '班级信息不存在');
     }
-    // 根据计划和期查询所有上报的学生 并按照学校排序
+    // 根据计划和期
+    // 查询所有上报的学生 并按照学校排序
     const newstudent = await this.stumodel.find({ termid }).sort({ schid: 1 });
     if (!newstudent) {
       throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '学生信息不存在');
@@ -42,6 +42,7 @@ class ClassService extends CrudService {
     const claGroup = _.groupBy(newclass, 'batchid');
     const keys = Object.keys(claGroup);
     const result = {}; // key:班级id;value:学生id数组
+    let cantSolveNotice = false;
     // 循环批次
     for (const bkey of keys) {
       const classList = claGroup[bkey]; // 该批次下的班级列表
@@ -71,7 +72,6 @@ class ClassService extends CrudService {
         // 存入最佳计算结果,但是需要验证,看看这批次的计算结果是否<=班级最少人数;多了可是要吐人的.吐人的写法代码更多
         solve[`${skey}-boy`] = br;
         solve[`${skey}-girl`] = gr;
-
       }
       // 验证最佳结果是否超出班级的最少人数,不是,则处理
       // console.log('计算最优解');
@@ -99,15 +99,17 @@ class ClassService extends CrudService {
       // console.log('补人前');
       // 检查是否有学生剩余,如果有学生剩余,都需要继续进行人的处理,无论是补人还是加人.
       let els = _.flatten(Object.values(studentGroup)).length;
+      // 无法解决,需要手动分配标识
+      let cantSolve = false;
       // 没有剩余的学生,下面也没法处理,结束了(跳过while了)
-      while (els > 0) {
+      while (els > 0 && !cantSolve) {
         // 还有学生,那就需要继续处理,看看是补人还是加人
         // 检查各个班级是否达到人数要求
         const { ok, not } = this.checkClassStatus(result, classList);
         // 如果not里有值,说明还有班级没满足人数要求->补人
         // 如果not没有值,说明参培人员多了->分到每个班里
         if (not.length > 0) {
-        // 进行补人
+          // 进行补人
           // not中的每个班进行补人,每个班补一个人(result[classid]加人),studentGroup[key]减人
           // 如果没人了,break;
           for (const c of not) {
@@ -115,6 +117,11 @@ class ClassService extends CrudService {
             const { _id } = c;
             const stuList = result[_id];
             const claSolve = this.getClassSolve(stuList);
+            // 没有最优解=>没有班级有学生.人数甚至不满足把班级填满.需要手动安排
+            if (claSolve.length <= 0 && els > 0) {
+              cantSolve = true;
+              break;
+            }
             // 根据solve结果,取对应的值,然后做加减
             for (const s of claSolve) {
               const { schid, gender } = s;
@@ -124,19 +131,24 @@ class ClassService extends CrudService {
               result[_id].push(head);
               midList = _.drop(midList);
               studentGroup[`${schid}-${gender}`] = midList;
-              break;// 一次,一班只补一个的重要关键词
+              break; // 一次,一班只补一个的重要关键词
             }
           }
         } else {
-        // 额外加人
-        // 说明下这里为什么要ok:因为在上面的solve,强制以班级最少的人数为均分标准
-        // 所以在班级人数不均等的情况下,出现某班均分完是正好的人数,剩下的班少人,但这时还得先把少人的班先补上才能均摊多的人
-        // 为什么要说明,因为下面代码除了循环的 数组 外,都一样啊
+          // 额外加人
+          // 说明下这里为什么要ok:因为在上面的solve,强制以班级最少的人数为均分标准
+          // 所以在班级人数不均等的情况下,出现某班均分完是正好的人数,剩下的班少人,但这时还得先把少人的班先补上才能均摊多的人
+          // 为什么要说明,因为下面代码除了循环的 数组 外,都一样啊
           for (const c of ok) {
-          // 需要计算出这个班补人的最优解
+            // 需要计算出这个班补人的最优解
             const { _id } = c;
             const stuList = result[_id];
             const claSolve = this.getClassSolve(stuList);
+            // 没有最优解=>没有班级有学生.人数甚至不满足把班级填满.需要手动安排
+            if (claSolve.length <= 0 && els > 0) {
+              cantSolve = true;
+              break;
+            }
             // 根据solve结果,取对应的值,然后做加减
             for (const s of claSolve) {
               const { schid, gender } = s;
@@ -153,8 +165,7 @@ class ClassService extends CrudService {
         // 重新计算人数,就是上面的els计算再执行一次
         els = _.flatten(Object.values(studentGroup)).length;
       }
-
-
+      if (cantSolve) cantSolveNotice = true;
     }
     // for (const key in result) {
     //   console.group(key);
@@ -175,6 +186,7 @@ class ClassService extends CrudService {
     for (const cla of claList) {
       await this.ctx.service.student.arrangeNumber({ classid: cla._id });
     }
+    if (cantSolveNotice) throw new BusinessError(ErrorCode.SERVICE_FAULT, '剩余人数无法继续自动安排,请手动分配班级');
   }
 
   /**
@@ -207,7 +219,8 @@ class ClassService extends CrudService {
     for (const c of classList) {
       const { _id, number } = c;
       const nowNum = alreadyList[_id].length;
-      if (nowNum < number) not.push(c); else ok.push(c);
+      if (nowNum < number) not.push(c);
+      else ok.push(c);
     }
     // 需要排序,需要按上限人数排列,把人少的放上面
     ok = _.orderBy(ok, [ 'number' ], [ 'asc' ]);
@@ -258,7 +271,6 @@ class ClassService extends CrudService {
     return solve;
   }
 
-
   // 取得同样类型的学生
   async getstutype(_students, type) {
     const data = [];
@@ -273,6 +285,8 @@ class ClassService extends CrudService {
 
   // 自动生成班级私有方法
   async autoclass(planid, termid) {
+    // 将本期的学生都重新初始回无班级状态
+    await this.stumodel.updateMany({ termid }, { classid: undefined });
     // 删除所有计划下的班级
     await this.model.deleteMany({ planid, termid });
     // 删除该期课表
@@ -382,7 +396,6 @@ class ClassService extends CrudService {
     await this.ctx.service.student.arrangeNumber({ classid: classid_ });
     // TODO 根据模板复制班级信息
     await this.toSetClassSetting({ classid: classid_ });
-
   }
 
   async notice(data) {
@@ -485,7 +498,6 @@ class ClassService extends CrudService {
       }
     }
     return data;
-
   }
 
   async fetch({ id }) {
@@ -536,7 +548,7 @@ class ClassService extends CrudService {
     const b = batchnum.id(batchid);
     if (!b) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到班级的批次信息');
     const { batch, startdate, enddate } = b;
-    if (batch)cla.batch = batch;
+    if (batch) cla.batch = batch;
     if (startdate) cla.startdate = startdate;
     if (enddate) cla.enddate = enddate;
     // 礼仪教师
@@ -571,7 +583,6 @@ class ClassService extends CrudService {
     return cla;
   }
 
-
   async upclasses(data) {
     for (const _data of data) {
       await this.model.findByIdAndUpdate(_data.id, _data);