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;
}
}
}