public string Populate(int seed, bool checkGrammar)
            {
                Dictionary <int, Word> definedGroupWords = new Dictionary <int, Word>();
                WordDictionaryLookup   wordLookup        = new WordDictionaryLookup(seed);
                BigramDictionaryLookup bigramLookup      = new BigramDictionaryLookup(wordLookup, seed);

                foreach (TemplatePhrase phrase in phrases)
                {
                    phrase.SetSeed(seed);
                    phrase.Populate(definedGroupWords, bigramLookup, wordLookup);
                }

                string result = template;
                int    offset = 0;

                if (checkGrammar)
                {
                    foreach (TemplatePhrase phrase in phrases)
                    {
                        List <TemplateWord> editedWords = GrammarEditor.EditPhrase(phrase.words);
                        foreach (TemplateWord word in editedWords)
                        {
                            result  = result.Substring(0, word.start + offset) + word.Word.Value + result.Substring(word.start + word.length + offset);
                            offset += word.Word.Value.Length - word.ToString().Length;
                        }
                    }
                    result = GrammarEditor.Filter(result);
                }
                else
                {
                    foreach (TemplatePhrase phrase in phrases)
                    {
                        foreach (TemplateWord word in phrase.words)
                        {
                            result  = result.Substring(0, word.start + offset) + word.Word.Value + result.Substring(word.start + word.length + offset);
                            offset += word.Word.Value.Length - word.ToString().Length;
                        }
                    }
                }
                return(result);
            }
 public BigramDictionaryLookup(WordDictionaryLookup wordDictLookup, int seed)
 {
     this.wordDictLookup = wordDictLookup;
     rand = new System.Random(seed);
 }
            public void Populate(Dictionary <int, Word> populatedGroupWords, BigramDictionaryLookup bigramLookup, WordDictionaryLookup wordLookup)
            {
                foreach (TemplateWord word in words)
                {
                    if (word.IsHook)
                    {
                        word.Word = null;
                    }
                }

                List <int> indicesOfCurrentPassToExecute = new List <int>();

                do
                {
                    foreach (int index in indicesOfCurrentPassToExecute)
                    {
                        TemplateWord currentWord = words[index];
                        TemplateWord wordBefore  = (index > 0 && !words[index - 1].NeedsHookPopulated) ? words[index - 1] : null;
                        TemplateWord wordAfter   = (index < words.Count - 1 && !words[index + 1].NeedsHookPopulated) ? words[index + 1] : null;

                        bool populatedByGroup = false;
                        if (currentWord.group != 0 && populatedGroupWords.Count > 0)
                        {
                            Word wordForGroup = null;
                            if (populatedGroupWords.TryGetValue(currentWord.group, out wordForGroup))
                            {
                                populatedByGroup = true;
                                currentWord.Word = wordForGroup;
                            }
                        }
                        if (!populatedByGroup)
                        {
                            if (wordBefore != null && wordAfter != null)
                            {
                                currentWord.Word = bigramLookup.GetRandomBetweenTwoWords(wordBefore.Word, currentWord.PoS, wordAfter.Word);
                            }
                            else if (wordBefore != null)
                            {
                                currentWord.Word = bigramLookup.GetRandomSecondWord(wordBefore.Word, currentWord.PoS);
                            }
                            else if (wordAfter != null)
                            {
                                currentWord.Word = bigramLookup.GetRandomFirstWord(currentWord.PoS, wordAfter.Word);
                            }
                            else
                            {
                                currentWord.Word = wordLookup.GetRandomWordByPOS(currentWord.PoS);
                            }

                            if (currentWord.group != 0)
                            {
                                populatedGroupWords.Add(currentWord.group, currentWord.Word);
                            }
                        }
                        //TODO: yield return for coroutine implementation if needed
                    }
                    indicesOfCurrentPassToExecute.Clear();

                    bool areStillHooks   = false;
                    bool lastWordWasHook = false;
                    for (int i = 0; i < words.Count; i++)
                    {
                        TemplateWord tWord = words[i];

                        bool currentWordIsHook = tWord.NeedsHookPopulated;
                        areStillHooks |= currentWordIsHook;

                        if (currentWordIsHook ^ lastWordWasHook)
                        {
                            if (currentWordIsHook && i > 0)
                            {
                                indicesOfCurrentPassToExecute.Add(i);
                            }

                            if (lastWordWasHook)
                            {
                                indicesOfCurrentPassToExecute.Add(i - 1);
                            }
                        }

                        lastWordWasHook = currentWordIsHook;
                    }

                    if (areStillHooks && indicesOfCurrentPassToExecute.Count == 0)
                    {
                        int times = (int)(rand.NextDouble() * (words.Count - 1)) + 1;
                        for (int i = 0; i < times; i++)
                        {
                            indicesOfCurrentPassToExecute.Add((int)(rand.NextDouble() * words.Count));
                        }
                    }
                }while (indicesOfCurrentPassToExecute.Count != 0);
            }