private ulong GetShuffleComplexity() { ulong combinationCount = new LvCombinationCountCalculator(_groupSizes, _groupSizes.Sum()).GetLvCombinationCount(); if (_maxCombinationCount <= 0) { return(combinationCount * (ulong)_lvCount); } return((ulong)(Math.Sqrt(combinationCount) * 100) + (ulong)_maxCombinationCount * (ulong)_lvCount); }
private ulong GetCombinationCount(IList <int> groupSizes, IList <Student> availableStudents) { var sameGroupSizes = groupSizes.Where(s => s == groupSizes[0]).Skip(1); var otherGroups = groupSizes.Where(s => s != groupSizes[0]); if (sameGroupSizes.Count() == 0) { otherGroups = new List <int>(groupSizes.Skip(1)); } ulong count1 = new LvCombinationCountCalculator(sameGroupSizes.ToList(), availableStudents.Count - groupSizes[0] + 1).GetLvCombinationCount(); ulong count2 = new LvCombinationCountCalculator(otherGroups.ToList(), otherGroups.Sum()).GetLvCombinationCount(); ulong combinationCount = (count1 == 0 ? 1 : count1) * (count2 == 0 ? 1 : count2); return(combinationCount); }
/// <summary> /// This method is used to create best student sitting combinations based on the fields in this class /// </summary> /// <param name="progressPercentage">Completed percentage for the shuffle step which is being executed at that moment</param> /// <param name="progressText">Text containing data about shuffle step which is being executed at that moment</param> /// <param name="progressTimeLeft">Estimated time left for shuffle step which is being executed at that moment to finish</param> /// <returns></returns> public void Shuffle(IProgress <double> progressPercentage = null, IProgress <string> progressText = null, IProgress <TimeSpan> progressTimeLeft = null) { /*BEST COMBINATION ALGORITHM EXPLANATION: * An algorithm which calculates best combination takes 6 parameters into consideration: * * 1st (most important) parameter is maxSittingCount: * max amount of times a student sat with with another student. * Lower amount is better. * * 2nd parameter is minSittingCount: * min amount of times a student sat with another student. * Higher is better. * * 3rd parameter is studentSittingDiff: * (highest sum of student sitting values for a student) - (lowest sum of student sitting value for a student (doesn't need to be the same student)). * Lower number is better since that forces the students to sit in groups of various sizes, instead of alwaays sitting in the biggest/smalled group. * * 4th parameter is minMaxSum: * sum of (max amount of times a student sat with another student) - (min amount of times that same student student sat with another student) for all students. * Lower is better. * * 5th parameter is minAndMaxSittingCountCount: * count of student sitting count values (student sitting count values - amount of times students sat with each other) where student sitting count is min or max. * Lower is better since it means that the deviation from average student sitting count is lower. * * 6th (least important) parameter is groupRepetitionCount: * Sum of amount of times each group in the combination was used in previous combinations * * Algorithm is pretty much doing * lvCombinations.OrderBy(1st parameter).OrderBy(2nd parameter).OrderBy(3nd parameter).OrderBy(4th parameter).First(), * but doing it manually since progress could otherwise only be updated once the best combination is found (which can take a lot of time)*/ //Setup foreach (var student in Students) { student.StudentSittingHistory.Clear(); } _shuffleResult.Clear(); progressPercentage?.Report(0); progressText?.Report("Računanje svih kombinacija sjedenja"); progressTimeLeft?.Report(new TimeSpan(0)); ulong combinationCount = new LvCombinationCountCalculator(_groups.Select(g => g.Size).ToList(), _students.Count).GetLvCombinationCount(); if (combinationCount > (ulong)MaxCombinationCount) { combinationCount = (ulong)MaxCombinationCount; } //Going trough each LV var combinations = GetLvCombinations(progressPercentage, progressTimeLeft, combinationCount); progressPercentage?.Report(0); progressText?.Report("Rasporeda se stvara"); progressTimeLeft?.Report(new TimeSpan(0)); for (int lv = 0; lv < _lvCount; lv++) { //Getting best student sitting combination for current lv LvCombination bestCombination = GetBestLvCombination(combinations, lv, progressPercentage, progressTimeLeft); //Updating shuffle result and progress UpdateStudentHistory(bestCombination, true); _shuffleResult.Add(bestCombination); //If every student sat with other students the same amount of times, there is no need to do further calculations since other lv's would just be repeats of current student sitting combinations if (GetStudentSittingHistoryValues().Distinct().Count() <= 1) { break; } } progressTimeLeft?.Report(new TimeSpan(0)); //DEBUGGING OUTPUT: used for testing purposes Debug_PrintResult(); }