internal string RenderText(TaskText text, TaskRandom random, string[] settingLevel)
        {
            if (text == null)
            {
                return("");
            }
            string str = text.Text;

            var localVariables = new Dictionary <string, object>();

            // Random elements
            if (text.Randoms != null)
            {
                foreach (var rnd in text.Randoms)
                {
                    str = str.Replace($"%{rnd.Id}%", LevelCheck(rnd.Level, settingLevel)
                        ? GetRndValue(rnd, localVariables, random)?.ToString() : "");
                }
            }
            // Switches
            if (text.Switches != null)
            {
                foreach (var sw in text.Switches)
                {
                    str = str.Replace($"%{sw.Id}%", LevelCheck(sw.Level, settingLevel)
                        ? GetSwitchValue(sw, localVariables, random)?.ToString() : "");
                }
            }
            // Variables
            if (text.Variables != null)
            {
                foreach (var vr in text.Variables)
                {
                    str = str.Replace($"%{vr}%", GetVariable(vr, localVariables)?.ToString());
                }
            }

            // Check level for subelements
            if (str.Contains('<') && str.Contains(" level=\""))
            {
                var eText       = XElement.Parse($"<text>{str}</text>");
                var subElements = eText.Descendants().ToList();
                foreach (XElement el in subElements)
                {
                    if (el.Attribute("level") != null)
                    {
                        if (!LevelCheck(TaskLoader.ReadLevel(el), settingLevel))
                        {
                            el.Remove();
                        }
                    }
                }
                str = eText.InnerText();
            }

            // Hidden HTML tags (starts with '\', e.g. '\&lt;')
            str = str.EncodeEscapedHtmlTags();

            return(str);
        }
        string[] selectedIds;                                // For Log

        private TaskRender(Tasks tasks, TaskSetting setting)
        {
            this.tasks      = tasks;
            this.Setting    = TaskLoader.MergeSettings(tasks.Setting, setting);
            random          = new TaskRandom(setting.Seed);
            output          = new StringBuilder();
            globalVariables = new Dictionary <string, object>();
            countOfTaskPreviousleyChoosed = new Dictionary <int, int>();
            previousChoosedCombinations   = new List <List <TaskItem> >();
        }