|
@@ -0,0 +1,486 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using static mxdemo.Mind.IStudentClassDispatchService;
|
|
|
+
|
|
|
+namespace mxdemo.Mind
|
|
|
+{
|
|
|
+ // 选科数据与决策会有很多重合的地方
|
|
|
+ public enum EnumElectiveGeneration
|
|
|
+ {
|
|
|
+ Init = 0, // 初始化态,选科正式开启前的状态,开启之后往下一代推进
|
|
|
+ Primary = 1, // 初选(正常报名)阶段,初选时间结束时往下一代推进 (先暂定进入PrimaryDM之前选科设置还可以修改,之后禁止,防止扰乱数据)
|
|
|
+ PrimaryDM, // (PrimaryDecisionMaking)初选录取阶段,应用决策之后,开启补录报名(时间段)并往下一代推进
|
|
|
+ BackTracking, // 补录报名时间结束后往下一代推进
|
|
|
+ BackTrackingDM, // 调剂OR提醒,如果为直接调剂,则跳过FinalAdjust,如果为提醒(设时间段)并往下一代推进
|
|
|
+ FinalAdjust, // 调剂报名期间
|
|
|
+ FinalAdjustDM, // 调剂决策,这个阶段会最终定版
|
|
|
+ RankBalance, // 可选步骤,行为类似强制调剂
|
|
|
+ // Dispatch, // 分班?分班是否要进入此结构?貌似结构不太统一!应该还是要分出去做
|
|
|
+ Terminate // 最终代,选科流程数据全部封存
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum EnumElectiveOperation
|
|
|
+ {
|
|
|
+ None = 0,
|
|
|
+ Canceled,
|
|
|
+ Disabled,
|
|
|
+ Optional,
|
|
|
+ Rejected,
|
|
|
+ Approved,
|
|
|
+ Forced
|
|
|
+ }
|
|
|
+
|
|
|
+ // 待思考问题:
|
|
|
+ /*
|
|
|
+ 1 哪个结点开始不允许修改选科设置
|
|
|
+ 2 未操作志愿、未选完志愿、未响应决策的学生是否需要区分显示
|
|
|
+ 3 补录决策时,是否存在部分调剂、部分提醒的情况?
|
|
|
+ 4 调剂行为定义:直接修改学生最终录取组合,触发发签名
|
|
|
+ */
|
|
|
+
|
|
|
+ #region models
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Generation init时生成的缓存数据,方便后续计算
|
|
|
+ /// 生成开放组合的数据即可
|
|
|
+ /// 每次修改选科设置(在允许范围内修改)需要刷新
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveStudentScore
|
|
|
+ {
|
|
|
+ long id;
|
|
|
+ long roundId;
|
|
|
+
|
|
|
+ long studentId;
|
|
|
+ long groupId;
|
|
|
+
|
|
|
+ decimal scoreTotal; // 9科成绩,看是否有必要存
|
|
|
+ decimal scoreGroup; // 6科成绩
|
|
|
+ int rankTotal; // 9科全校排名,看是否有必要存
|
|
|
+ int rankGroup; // 6科全校排名
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 每一代都为体现学生的选科数据变化,任何操作都可以被记录下来,只是最终哪条生效的问题
|
|
|
+ /// 当然也可以根据实际情况减少部分记录,类下面的注解将讨论这些问题
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveGenerationFlowData
|
|
|
+ {
|
|
|
+ long id;
|
|
|
+ long roundId;
|
|
|
+
|
|
|
+ long studentId;
|
|
|
+ long groupId;
|
|
|
+
|
|
|
+ EnumElectiveGeneration generation;
|
|
|
+ EnumElectiveOperation operation;
|
|
|
+ long operateBy;
|
|
|
+ DateTime operateTime;
|
|
|
+ int rank; // Primary中可能存在多志愿,用来控制此阶段的志愿优先级,如第1志愿=0,第2志愿=1,第三志愿=2
|
|
|
+
|
|
|
+ string remark;
|
|
|
+ // 以下2个字段用来挂载生命周期关键引用对象,具体每个环节挂什么,需要再斟酌。
|
|
|
+ string refType;
|
|
|
+ long refId;
|
|
|
+ }
|
|
|
+ public class ElectiveGenerationFlowLog : ElectiveGenerationFlowData
|
|
|
+ {
|
|
|
+ // + 区分ElectiveGenerationFlowData的字段
|
|
|
+ }
|
|
|
+
|
|
|
+ public class RoundForFlow : mxdemo.Mind.IStudentClassDispatchService.Round // Round到时候合并在一起
|
|
|
+ {
|
|
|
+ bool AllMatched; // 所有学生匹配完毕,可以开始推进排名均衡或者分班
|
|
|
+ EnumElectiveGeneration currentGeneration; // 内部字段
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1 初选决策时,需要进行设置
|
|
|
+ // 2 补录决策时,需要进行设置,此时要根据具体数据来定
|
|
|
+ // 如果所有学生都已经匹配完毕(Approved,Forced都属性已匹配),则可以推进排名均衡或者分班
|
|
|
+ // 如果还有未匹配的,则推进到FinalAdjust
|
|
|
+ public class FlowPushSetting
|
|
|
+ {
|
|
|
+ long id;
|
|
|
+ long roundId;
|
|
|
+ DateTime begin;
|
|
|
+ DateTime end;
|
|
|
+ bool onlyRecommand; // 仅允许学生选择推荐组合, 否则允许学生填报有空缺的组合
|
|
|
+ bool onlyAgree; // 调剂阶段,只允许学生选择同意, 否则允许学生拒绝
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ElectiveEsign
|
|
|
+ {
|
|
|
+ long id;
|
|
|
+ long roundId;
|
|
|
+ long flowDataId; // 对应哪条匹配数据(录取或者调剂)【匹配算法结果表也可如此挂载flowDataId,这样可以追溯匹配原因】
|
|
|
+
|
|
|
+ string esignPath; // 签字保存图片
|
|
|
+ bool actived; // 有效标记,可以考虑:如果学生需要签名且未签名时,如果再遇到新的调剂时,旧的签名还要继续么?我觉得应该是不需要的
|
|
|
+ // 可能还有其它字段
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ 总则:ElectiveGenerationFlowData记录的是每一代数据的最终结果,如果想要更精细的记录,可以结合ElectiveGenerationFlowLog
|
|
|
+ 1 Generation.Init 可有可无,不需要生成初始数据?
|
|
|
+
|
|
|
+ 2 Generation.Primary
|
|
|
+ 报名时:
|
|
|
+ ADD operation=Approved
|
|
|
+
|
|
|
+ 取消时:
|
|
|
+ UPDATE operation=Cancel
|
|
|
+
|
|
|
+ 排名挤出时-被挤出人:
|
|
|
+ UPDATE operation=Disabled, remark = '排名挤出'
|
|
|
+ refType = 'ElectiveGenerationFlowData'
|
|
|
+ refId = ElectiveGenerationFlowData.id // 报名解发挤出那条记录的ElectiveGenerationFlowData.id
|
|
|
+
|
|
|
+ 取消时恢复补挤出的人(只有当被影响的人还有剩余报名次数的时候才自动恢复,因为期间他可能自己又补填了一个志愿):
|
|
|
+ QueryBy refId
|
|
|
+ UPDATE operation=Approved WHEN COUNT(operation=Approved)<setting.PreferenceCount
|
|
|
+ remark = ''
|
|
|
+ refType = ''
|
|
|
+ refId = 0 // 取消对应记录的ID
|
|
|
+
|
|
|
+ Primary中学生的有效报名数据:operation=Approved
|
|
|
+
|
|
|
+ 3 Generation.PrimaryDM
|
|
|
+ 目标:启用算法,给每个学生生成一条决策数据,表示初选录取情况(算法见ElectiveEngine草稿)
|
|
|
+
|
|
|
+ 录取:
|
|
|
+ ADD operation=Approved
|
|
|
+ remark = 录取说明?
|
|
|
+ refType = 'ElectiveEsign'
|
|
|
+ refId = ElectiveEsign.id // 生成一条待签记录
|
|
|
+ // 这样的话签名与选科的代数据就可分割开了,具体说是否一定要学生签名才能推进下一代?
|
|
|
+ // 我看未必,因为学校不可能因为个别钉子户就暂停教务
|
|
|
+
|
|
|
+ 未录取,但自选专业满足
|
|
|
+ ADD operation=Optional, groupId=推荐组合
|
|
|
+ remark = 未录取原因
|
|
|
+ 未录取,也无自选专业满足
|
|
|
+ ADD operation=Rejected, groupId=推荐组合
|
|
|
+ remark = 未录取原因
|
|
|
+
|
|
|
+ PrimaryDM中 operation=[Optional,Rejected]的学生,即是一代补录流程的目标学生
|
|
|
+
|
|
|
+ 4 Generation.BackTracking
|
|
|
+ 操作逻辑重用Generation.Primary
|
|
|
+
|
|
|
+ 5 Generation.BackTrackingDM
|
|
|
+ 操作逻辑重用Generation.PrimaryDM,
|
|
|
+ 计算差别:仅1个志愿,但还是可以引用自选专业,因为学生在此期间可能更改了自选专业
|
|
|
+
|
|
|
+ 操作差别:校长在推动下一代流程时,有可能会开始手动调剂
|
|
|
+ UPDATE operation=Forced // Forced操作等同于Approved录取状态,即告诉学生被调剂了,签字同意即可(即也挂ref钩子)
|
|
|
+
|
|
|
+ 6 Generation.FinalAdjust
|
|
|
+ 可选步骤,有可能跳过,如未跳过,则是调剂报名
|
|
|
+ 同意:前端会强制签名,所以这条在保存时可以直接挂钩ElectiveEsign
|
|
|
+ ADD operation=Approved, refType='ElectiveEsign', refId=ElectiveEsign.id
|
|
|
+ 拒绝:
|
|
|
+ ADD operation=Rejected, remark=不同意原因
|
|
|
+ 附:没有记录则是未参与的
|
|
|
+
|
|
|
+ 7 Generation.FinalAdjustDM
|
|
|
+ 针对未参与的或operation=Rejected, 校长会在此环节强制调剂,以达到最终定版的目的
|
|
|
+ ADD operation=Forced, refType='ElectiveEsign', refId=0 // 待签名
|
|
|
+
|
|
|
+ 8 Generation.RankBalance
|
|
|
+ 可选步骤,也是产生类似Generation.FinalAdjustDM数据逻辑,只是学校出发的角度不一样
|
|
|
+ ADD operation=Forced, refType='ElectiveEsign', refId=0 // 待签名
|
|
|
+
|
|
|
+ 9 Generation.Dispatch 待定应该要分出去单独做
|
|
|
+
|
|
|
+ 10 Generation.Terminate
|
|
|
+ 不产生数据,但需要记录此状态,表示选科数据封存(记录在round实例中)
|
|
|
+ */
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ public interface IElectiveService
|
|
|
+ {
|
|
|
+ #region getElectiveSummary
|
|
|
+ /// <summary>
|
|
|
+ /// 选科过程中的统计数据值,除了要展示之外还需要做查询支持
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveSummaryValue
|
|
|
+ {
|
|
|
+ // 展示字段
|
|
|
+ int groupId; // 组合ID,没有组合为0比如未参与报名人数(实际只有两种统计数据,针对某个组合的统计和不针对组合的统计)
|
|
|
+ int value; // 数值
|
|
|
+ string color; // 支持'R','G','B','',或者'#FA1234'等hexString
|
|
|
+ bool bold; // 加粗,重点展示
|
|
|
+ bool star; // 带*,重点展示
|
|
|
+
|
|
|
+ // 反向查询代码 将统计逻辑的条件关键字放入此代码,回传后台能反向解析并恢复明细
|
|
|
+ // 想法:让统计全部基于ElectiveGenerationFlowData,形成一种或多种QueryDto{roundId:'',generation:'',groupId:''...}等, 序列化实际查询条件
|
|
|
+ string queryCode;
|
|
|
+ bool disabled; // 不支持查询
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 查询的某一列
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveSummaryCategory
|
|
|
+ {
|
|
|
+ string category; // 身份标识,类似字段名/列名,可能被前端用来定制渲染模板
|
|
|
+ string displayName; // 显示名称
|
|
|
+
|
|
|
+ ElectiveSummaryValue[] values;
|
|
|
+ }
|
|
|
+
|
|
|
+ public interface IElectiveGenerationSummary
|
|
|
+ {
|
|
|
+ int roundId { get; set; } // 选科轮次
|
|
|
+ EnumElectiveGeneration generation { get; set; } // 进程代
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 进程代的统计结果从primary开始出数据
|
|
|
+ /// </summary>
|
|
|
+ public class ElectivePrimarySummary : IElectiveGenerationSummary
|
|
|
+ {
|
|
|
+ ElectiveSummaryCategory[][] categories; // 是多维数组,以应对多志愿的情况
|
|
|
+
|
|
|
+ public int roundId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public EnumElectiveGeneration generation { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 非Primary非DM的某一代的统计结果
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveGenerationSummary: IElectiveGenerationSummary
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 对某一代的统计项目,比如在初选决策、补录报名的统计等,下面接口会细述
|
|
|
+ /// </summary>
|
|
|
+ ElectiveSummaryCategory[] categories;
|
|
|
+
|
|
|
+ int IElectiveGenerationSummary.roundId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ EnumElectiveGeneration IElectiveGenerationSummary.generation { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class ElectiveGenerationDMSummary: ElectiveGenerationSummary
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 迭加到某决策代的统计项目,比如当前选科的总录取人数、待签人数、已签人数等,下面接口会细述
|
|
|
+ /// </summary>
|
|
|
+ ElectiveSummaryCategory[] accumulates;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取选科进程的统计数据,一直汇总到当前进程代
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ IElectiveGenerationSummary[] getElectiveSummary();
|
|
|
+ // 下面开始按代来描述ElectiveGenerationSummary需要返回的具体内容
|
|
|
+ /* 一、ElectivePrimarySummary,所需ElectiveSummaryCategory->{category:'',displayName:''}定义如下:
|
|
|
+ * // hht.22/4/10 这个属性不要了 {'expectedCount','设置人数'}, -- 选科设置的人数, 为方便输出与图表展示,可能后续会有重复输出
|
|
|
+ * {'actualCount','实际人数'}, -- 填报第X志愿的人数
|
|
|
+ * {'unfinishedCount','未完成人数'}, -- 未填报第X志愿的人数(根据ElectiveGenerationFlowData实际Approved&Rank情况统计即可,因为如果报名还在进行中,本身就是动态变化的东西)
|
|
|
+ * 按第一志愿、第二志愿、...的顺序输出数据
|
|
|
+ *
|
|
|
+ * 二、ElectiveGenerationDMSummary.accumulates
|
|
|
+ * 仅决策代需要统计此数据,决策代[PrimaryDM BackTrackingDM FinalAdjustDM RankBalance]
|
|
|
+ * {'expectedCount', '设置人数'} -- 选科设置人数
|
|
|
+ * {'approvedCount', '正常录取人数'} -- 到此阶段为止,正常录取人数
|
|
|
+ * {'forcedCount', '调剂录取人数'} -- 到此阶段为止,调剂录取人数
|
|
|
+ * {'esignedCount', '已签人数'} -- 到此阶段为止,触发的有效签名统计
|
|
|
+ * {'esigningCount', '待签人数'} -- 到此阶段为止,阶段触发有效的应签未签统计
|
|
|
+ *
|
|
|
+ * 三、ElectiveGenerationSummary.categories 只统计某代的数据
|
|
|
+ * A PrimaryDM
|
|
|
+ * {'indicateCount','指标'} -- 正负表示超过设置的人数,负数表示低于设置的人数
|
|
|
+ * {'approvedCount, '录取人数'} -- 正常录取人数
|
|
|
+ * {'adjustCount','调剂人数'} -- 未录取人数,理论上应该<=指标的绝对值
|
|
|
+ * {'matchedCount','可调剂人数'} -- 未录取可被调剂的人(志愿不满足但自选专业满足)
|
|
|
+ * {'nonmatchedCount','不可调剂人数'} -- 未录取不可被调剂的人(志愿与自选专业均不满足)
|
|
|
+ *
|
|
|
+ * B BackTracking FinalAdjust
|
|
|
+ * {'matchedApproved','可调剂已填人数'} -- 统计有效补录报名
|
|
|
+ * {'matchedRejected','可调剂已拒绝人数'} -- 统计拒绝报名的人数
|
|
|
+ * {'matchedNonaction','可调剂未完成人数'} -- 统计未参与已经失效的报名人数(因为有可能被排名挤出)
|
|
|
+ * {'nonmatchedApproved','不可调剂已填人数'}
|
|
|
+ * {'nonmatchedRejected','不可调剂已拒绝人数'}
|
|
|
+ * {'nonmatchedNonaction','不可调剂未完成人数'}
|
|
|
+ *
|
|
|
+ * C BackTrackingDM FinalAdjustDM RankBalance
|
|
|
+ * {'approvedCount','补录录取人数'} -- 正常录取 [BackTrackingDM FinalAdjustDM]
|
|
|
+ * {'forcedCount','调剂录取人数'} -- 强制调剂录取 [BackTrackingDM FinalAdjustDM RankBalance]
|
|
|
+ * {'matchedCount','可调剂人数'} -- 正常录取 [BackTrackingDM]
|
|
|
+ * {'nonmatchedCount','不可调剂人数'} -- 正常录取 [BackTrackingDM]
|
|
|
+ *
|
|
|
+ */
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region getElectiveSummaryDetail 汇总明细清单
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 明细肯定是通过 某个组合某个学生 来呈现的
|
|
|
+ /// </summary>
|
|
|
+ public interface IElectiveGengerationDetail
|
|
|
+ {
|
|
|
+ long id { get; set; }
|
|
|
+ EnumElectiveGeneration generation { get; set; }
|
|
|
+ string category { get; set; } // ElectiveSummaryCategory.category
|
|
|
+ int roundId { get; set; }
|
|
|
+ int studentId { get; set; }
|
|
|
+ string studentName { get; set; }
|
|
|
+ int classId { get; set; }
|
|
|
+ string className { get; set; }
|
|
|
+ int groupId { get; set; }
|
|
|
+ string groupName { get; set; }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 此类相当于ElectiveGenerationFlowData的DTO,将字段转义为UI需要的内容
|
|
|
+ /// 明细的学生组合信息, 主要包含报名信息;
|
|
|
+ /// 还有一部分自选专业的信息,需要借助其它接口
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveGenerationDetail: IElectiveGengerationDetail
|
|
|
+ {
|
|
|
+ int rankInTime { get; set; } // 组合即时排名
|
|
|
+ int rankInGroup { get; set; } // 组合全校排名
|
|
|
+ int rankInGrade { get; set; } // 总分全校排名
|
|
|
+ int rankPreference { get; set; } // 志愿RANK 第几志愿
|
|
|
+ string OperateTime { get; set; } // 报名时间
|
|
|
+
|
|
|
+ public long id { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public string category { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public EnumElectiveGeneration generation { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public int roundId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public int studentId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public string studentName { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public int classId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public string className { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public int groupId { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ public string groupName { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 录取明细(包含approved正常录取;forced强制调剂录取),当前组合为录取项
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveGenerationEnrollDetail: ElectiveGenerationDetail
|
|
|
+ {
|
|
|
+ ElectiveGenerationDetail[] otherEnlist; // 非录取报名清单
|
|
|
+ Dictionary<long, string> failedReasons; // 如果有未录取原因,填充在此MAP{key: detailId, value: failed reason}中
|
|
|
+ bool forced; // 是否属于强制调剂
|
|
|
+ bool esigned; // 是否已经签名
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 未录取明细,当前组合是推荐项
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveGenerationDisenrollDetail: ElectiveGenerationDetail
|
|
|
+ {
|
|
|
+ ElectiveGenerationDetail[] enlist; // 之前的报名清单(肯定都没有录取)
|
|
|
+ Dictionary<long, string> failedReasons; // 如果有未录取原因,填充在此MAP中
|
|
|
+ bool agreed; // 同意此组合
|
|
|
+ bool disagreed; // 不同意此组合
|
|
|
+ bool disagreeReason; // 不同意的原因
|
|
|
+ ElectiveGenerationDetail other; // 即没有同意,也没有不同意,选了其它组合
|
|
|
+ bool esigned; // 是否已经签名
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 初选报名搭配使用,展示其它可报组合情况
|
|
|
+ /// </summary>
|
|
|
+ public class ElectiveGenerationOptionalMajor : ElectiveOptionalMajor
|
|
|
+ {
|
|
|
+ int bestMatchedGroupId; // 最佳匹配
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Map: {key: studentid, value: ElectiveGenerationOptionalMajor}
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="studentIds"></param>
|
|
|
+ /// <returns>批量取学生自选专业匹配情况</returns>
|
|
|
+ Dictionary<int, ElectiveGenerationOptionalMajor> getGenerationOptionalMajorsBatch(int[] studentIds);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 通过summary中输出的queryCode反查明细
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="queryCode"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ List<IElectiveGengerationDetail> getElectiveGengerationDetails(string queryCode);
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region decision-making
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 匹配算法,算法名称代表的具体逻辑请看注解(不要顾名思义)
|
|
|
+ /// </summary>
|
|
|
+ public enum EnumElectiveDMAlgorithm
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 按成绩:
|
|
|
+ /// ElectiveEngine中,相当于[未录学生]/[组合*ALL]/[志愿*ALL]一并运行,排序时排名优先;
|
|
|
+ /// 以上逻辑循环迭代,每次只补空缺组合,直至未录学生=0。
|
|
|
+ /// 第1次迭代之后运算的学生均属于可调剂名单,不会有不可调剂名单
|
|
|
+ /// </summary>
|
|
|
+ RankFirst,
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 按专业:
|
|
|
+ /// ElectiveEngine中,相当于[未录学生]/[组合*ALL]/[志愿1][志愿2,志愿3][自选专业伪志愿]/三波运行,排序时排名优先;
|
|
|
+ /// 以上逻辑循环迭代,每次只补空缺组合,直至伪志愿运算结束。
|
|
|
+ /// [志愿1][志愿2,志愿3]迭代的录取学生为正常录取;自选专业伪志愿为可调剂名单;运行结束后的未录学生为不可调剂名单。
|
|
|
+ /// </summary>
|
|
|
+ MajorFirst, //
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 执行选科匹配算法。为减少错误,对DM代数据全删全加可能好点。
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="algorithm"></param>
|
|
|
+ void applyElectiveDMAlgorithm(EnumElectiveDMAlgorithm algorithm);
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region forced
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 决策阶段,强制调剂录取
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="studentId"></param>
|
|
|
+ /// <param name="groupId"></param>
|
|
|
+ void enrollByForce(long studentId, int groupId);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 取消强制调剂操作
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="id">ElectiveGenerationFlowData.id</param>
|
|
|
+ void cancelEnrollByForce(long id);
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region generation推进
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 决策完毕时,推进下一代进行
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="setting"></param>
|
|
|
+ void pushGenerationSetting(FlowPushSetting setting);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 如果在所有学生全部录取的情况,可以在任意决策结点跳转至排名均衡
|
|
|
+ /// </summary>
|
|
|
+ void jumpGenerationRankBalance();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 如果在所有学生全部录取的情况,可以在任意决策结点跳转至终止态,封存数据
|
|
|
+ /// </summary>
|
|
|
+ void terminateGeneration();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 在任意报名阶段,如果校长发现数据已经完全OK,则可以强制推进进程,提前进入决策
|
|
|
+ /// </summary>
|
|
|
+ void flushIntoGenerationDM();
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 排名均衡(略)先完成前面的
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+}
|