using System; using System.Collections.Generic; using System.Linq; namespace mxdemo.Mind { #region models /// /// 选科组合 /// public class SubjectGroup { public int Limitation { get; set; } // 人数限制 public string Name { get; set; } public string Code { get; set; } public long Id { get; set; } } /// /// 志愿 /// public class Preference { public int Rank { get; set; } // 第1、2、3志原 越小优先级越高 public long GroupId {get;set;} public long StudentId { get; set; } public long Id { get; set; } } /// /// 得分情况 /// public class GroupScore { public decimal Score { get; set; } public long StudentId { get; set; } public long GroupId { get; set; } } /// /// 学生信息 /// public class Student { public long Id { get; set; } public string No { get; set; } public string Name { get; set; } } public class ElectiveElement { public Student Student { get; set; } public Preference Preference { get; set; } public SubjectGroup Group { get; set; } // 计算属性 public int PreferenceRank { get; set; } // 志愿排名 public int GroupRank { get; set; } // 组合排名,即成绩排名(组合全校排名),同样越小优先级越高 } #endregion public class ElectiveResult { public ElectiveResult(List students) { this.UnmatchedStudents = students; } public List MatchedStudents { get; set; } = new List(); public Dictionary> MatchedDetails { get; set; } = new Dictionary>(); public List UnmatchedStudents { get; set; } public void AppendMatched(ElectiveElement element) { // 应该还有更多细节需要考虑 var appendStudent = element.Student; if (MatchedStudents.Contains(appendStudent)) return; if (UnmatchedStudents.Contains(appendStudent)) RemoveUnmatched(appendStudent); var appendGroup = MatchedDetails.ContainsKey(element.Group) ? MatchedDetails[element.Group] : new List(); if (appendGroup.Count < element.Group.Limitation) { MatchedDetails[element.Group] = appendGroup; AddMatchedAndDetails(element); } else { AddUnmatched(appendStudent); } } private void AddMatchedAndDetails(ElectiveElement element) { // 应该还有更多细节需要考虑 MatchedDetails[element.Group].Add(element); MatchedStudents.Add(element.Student); } private void AddUnmatched(Student student) { // 应该还有更多细节需要考虑 UnmatchedStudents.Add(student); } private void RemoveUnmatched(Student student) { // 应该还有更多细节需要考虑 UnmatchedStudents.Remove(student); } } public interface IElectiveStrategy { /// /// 从开放选科中取出按优先级分组的选科 /// /// List> GetAllPrioritizedGroups(); /// /// 参与这次运算的志愿优先级集合 /// /// List> GetAllPrioritizedPreferenceRanks(); /// /// 参与这次运算的所有学生 /// /// List GetAllStudents(); } public abstract class ElectiveEngine: IComparer { protected IElectiveStrategy ElectiveStrategy { get; set; } protected ElectiveEngine(IElectiveStrategy electiveStrategy) { ElectiveStrategy = electiveStrategy; } public ElectiveResult Execute() { var prioritizedGroups = ElectiveStrategy.GetAllPrioritizedGroups(); var prioritizedPreferenceRanks = ElectiveStrategy.GetAllPrioritizedPreferenceRanks(); var allStudents = ElectiveStrategy.GetAllStudents(); var electiveResult = new ElectiveResult(allStudents); foreach(var groups in prioritizedGroups) { foreach(var ranks in prioritizedPreferenceRanks) { var students = electiveResult.UnmatchedStudents; var elements = BuildElectiveElements(students, groups, ranks); ExecuteCore(elements, electiveResult); } } return electiveResult; } private void ExecuteCore(List elements, ElectiveResult context) { // 核心方法优先级排序, 已经按期望排好了录取顺序 elements.Sort(this); // this.IComparer.Compare // 接下来考虑每个组合容量的问题 foreach(var element in elements) { context.AppendMatched(element); } } protected virtual List BuildElectiveElements(List students, List groups, List ranks) { // 根据组合与志愿 生成不同的选科元素 // 可以按计算需要,相互挂一些引用,方便计算过程中的删除操作 // TODO: 如果引入意向专业,也可以改写这个生成的逻辑 throw new NotImplementedException(); } /// /// 优先级比较 /// /// /// /// public abstract int Compare(ElectiveElement x, ElectiveElement y); } public class PreferenceAheadElectiveEngine : ElectiveEngine { public PreferenceAheadElectiveEngine(IElectiveStrategy electiveStrategy) :base(electiveStrategy) { } public override int Compare(ElectiveElement x, ElectiveElement y) { // TODO: 容错处理 if (x.PreferenceRank == y.PreferenceRank) return y.GroupRank - x.GroupRank; return y.PreferenceRank - x.PreferenceRank; } } public class ScoreAheadElectiveEngine : ElectiveEngine { public ScoreAheadElectiveEngine(IElectiveStrategy electiveStrategy) : base(electiveStrategy) { } public override int Compare(ElectiveElement x, ElectiveElement y) { // TODO: 容错处理 if (x.GroupRank == y.GroupRank) return y.PreferenceRank - x.PreferenceRank; return y.GroupRank - x.GroupRank; } } }