/// <summary> /// Requires that the words in the list have a category entry and that categories have some multiple of four words in each of them. /// /// Shuffles into lists of 12 words appended without delineation to the return list. /// </summary> /// <returns>The shuffled list of words.</returns> /// <param name="rng">Rng.</param> /// <param name="list">List.</param> /// <param name="lengthOfEachList">Length of each list.</param> protected IronPython.Runtime.List CategoryShuffle(System.Random rng, IronPython.Runtime.List list, int lengthOfEachList) { if (lengthOfEachList != 12) { throw new UnityException("Currently only lists of 12 words are supported by CatFR."); } /////////////in order to select words from appropriate categories, build a dict with categories as keys and a list of words as values Dictionary <string, IronPython.Runtime.List> categoriesToWords = BuildCategoryToWordDict(rng, list); /////////////we will append words to this in the proper order and then return it IronPython.Runtime.List returnList = new IronPython.Runtime.List(); bool finished = false; int iterations = 0; do { iterations++; if (iterations > 1000) { finished = true; throw new UnityException("Error while shuffle catFR list"); } ////////////if there are less than three categories remaining, we are on the last list and can't complete it validly ////////////this is currently handled by simply trying the whole process again if (categoriesToWords.Count < 3) { //start over categoriesToWords = BuildCategoryToWordDict(rng, list); returnList = new IronPython.Runtime.List(); continue; } List <string> keyList = new List <string>(categoriesToWords.Keys); //////////find three random unique categories string randomCategoryA = keyList[rng.Next(keyList.Count)]; string randomCategoryB; do { randomCategoryB = keyList[rng.Next(keyList.Count)]; }while (randomCategoryB.Equals(randomCategoryA)); string randomCategoryC; do { randomCategoryC = keyList[rng.Next(keyList.Count)]; }while (randomCategoryC.Equals(randomCategoryA) | randomCategoryC.Equals(randomCategoryB)); //////////get four words from each of these categories IronPython.Runtime.List groupA = new IronPython.Runtime.List(); IronPython.Runtime.List groupB = new IronPython.Runtime.List(); IronPython.Runtime.List groupC = new IronPython.Runtime.List(); for (int i = 0; i < 4; i++) { groupA.Add(categoriesToWords[randomCategoryA].pop()); } for (int i = 0; i < 4; i++) { groupB.Add(categoriesToWords[randomCategoryB].pop()); } for (int i = 0; i < 4; i++) { groupC.Add(categoriesToWords[randomCategoryC].pop()); } //////////remove categories from dict if all 12 words have been used if (categoriesToWords[randomCategoryA].Count == 0) { categoriesToWords.Remove(randomCategoryA); } if (categoriesToWords[randomCategoryB].Count == 0) { categoriesToWords.Remove(randomCategoryB); } if (categoriesToWords[randomCategoryC].Count == 0) { categoriesToWords.Remove(randomCategoryC); } //////////integers 0, 1, 2, 0, 1, 2 representing the order in which to present pairs of words from categories (A == 1, B == 2, etc.) //////////make sure to fulfill the requirement that both halves have ABC and the end of the first half is not the beginning of the second IronPython.Runtime.List groups = new IronPython.Runtime.List(); for (int i = 0; i < 3; i++) { groups.Add(i); } groups = Shuffled(rng, groups); int index = 0; int first_half_last_item = 0; foreach (int item in groups) { if (index == 2) { first_half_last_item = item; } index++; } IronPython.Runtime.List secondHalf = new IronPython.Runtime.List(); for (int i = 0; i < 3; i++) { secondHalf.Add(i); } secondHalf.Remove(first_half_last_item); secondHalf = Shuffled(rng, secondHalf); bool insertAtEnd = rng.Next(2) == 0; if (insertAtEnd) { secondHalf.Insert(secondHalf.Count, first_half_last_item); } else { secondHalf.Insert(secondHalf.Count - 1, first_half_last_item); } foreach (int item in secondHalf) { groups.append(item); } //////////append words to the final list according to the integers gotten above foreach (int groupNo in groups) { if (groupNo == 0) { returnList.append(groupA.pop()); returnList.append(groupA.pop()); } if (groupNo == 1) { returnList.append(groupB.pop()); returnList.append(groupB.pop()); } if (groupNo == 2) { returnList.append(groupC.pop()); returnList.append(groupC.pop()); } } //////////if there are no more categories left, we're done if (categoriesToWords.Count == 0) { finished = true; } }while (!finished); return(returnList); }