/// <summary>
        /// Validate user Answer
        /// </summary>
        /// <param name="question">Question that user answered</param>
        /// <param name="userAnswer">String representation of user answer</param>
        /// <returns></returns>
        private bool CheckAnswerIsCorrect(GeneratedQuestion question,
                                          string userAnswer)
        {
            bool result = false;

            if (string.IsNullOrWhiteSpace(userAnswer))
            {
                return(false);
            }

            if (question.QuestionType == 1)
            {
                int rightAnswer = int.Parse(userAnswer);
                if (question.Answers[rightAnswer].IsCorrect)
                {
                    result = true;
                }
            }

            if (question.QuestionType == 2)
            {
                result = true;
                var answerArray = userAnswer.Split(',');
                for (int i = 0; i < question.Answers.Count; i++)
                {
                    if (question.Answers[i].IsCorrect != answerArray.Contains(i.ToString()))
                    {
                        result = false;
                    }
                }
            }

            if (question.QuestionType == 3)
            {
                foreach (var ans in question.Answers)
                {
                    if (ans.Body == userAnswer)
                    {
                        result = true;
                    }
                }
            }

            return(result);
        }
        public ActionResult Process(FormCollection collection)
        {
            // Geting session information
            int      sessionId = 0;
            TestData testData  = GetTestData(out sessionId);


            // If test data is bad ending survey
            if (testData == null)
            {
                return(RedirectToAction("End"));
            }

            // If bad question token (for example student are trying to answer question previously cached in browser) redirecting to Index (will show last generated question)
            if (collection["QuestionToken"] != testData.GetQuestionHash())
            {
                return(RedirectToAction("Index"));
            }

            // Get previous question to check asnwer is correct
            GeneratedQuestion question =
                TemplateManager.Generate(testData.CurrentQuestionId,
                                         testData.TestSeed);

            // Remembering some nessasary data
            testData.ItemsTaken++;
            testData.TotalDifficultiesUsed += testData.CurrentQuestionDifficulty;



            // Calculating the amount that will change the difficulty
            double difficultyShift = 0.2 + (float)2 / testData.ItemsTaken;

            // Checking answer is correct
            bool answerIsCorrect = CheckAnswerIsCorrect(question, collection["Answers"]);

            // Saving to question information about its own statistic
            QuestionController.AddAttempt(testData.CurrentQuestionId, answerIsCorrect);

            // Adding data to 'ResultGraph'
            testData.AddPointToResultGraph(answerIsCorrect);
            // TODO: Temperory method for statistics. (Re)move
            testData.AddPointToRDF();

            // Correcting difficulty
            if (answerIsCorrect)
            {
                testData.TrueDifficultyLevel += difficultyShift;
                if (testData.TrueDifficultyLevel > 10)
                {
                    testData.TrueDifficultyLevel = 10;
                }

                testData.RightAnswersCount++;
            }
            else
            {
                testData.TrueDifficultyLevel -= difficultyShift;
                if (testData.TrueDifficultyLevel < 1)
                {
                    testData.TrueDifficultyLevel = 1;
                }
            }



            // TODO: Make CONST optional. For the next programmers' generation
            // Checking if measurement error lower than CONST
            var error   = testData.CalculateError();
            var measure = testData.CalculateMeasure();

            if (error <= 0.5)
            {
                testData.TestCompleted = true;
            }
            if (measure + error <= 1 || measure - error >= 10)
            {
                testData.TestCompleted = true;
            }

            //Check for test min length
            // TODO: Add some behaviors. For the next programmers' generation. For example different options for different test types.
            // If amount of taken question equals amount of total questions in test, mark test as completed.
            if (testData.ItemsTaken >= testData.MaxAmountOfQuestions)
            {
                testData.TestCompleted = true;
            }
            // TODO: Add min length to test data
            else if (testData.ItemsTaken < 10)
            {
                testData.TestCompleted = false;
            }

            // Selecting next question
            Question selectedQuestion = GetQuestion(testData);

            // Generates random seed, which helps to generate the same question from tamplate, if needed
            testData.TestSeed = TemplateManager.GetRandomSeed();

            // Remembering next question parameters
            testData.CurrentQuestionDifficulty = selectedQuestion.Difficulty;
            testData.CurrentQuestionId         = selectedQuestion.ID;

            // Saving test session
            SetTestData(testData, sessionId);

            // Continue test or end it depending on TestCompleted flag
            return((testData.TestCompleted) ? RedirectToAction("End") : RedirectToAction("Index"));
        }
        /// <summary>
        /// Returns GeneratedQuestion
        /// </summary>
        /// <param name = "templateId">Template id</param>
        /// <param name = "seed">Random seed</param>
        /// <returns></returns>
        public static GeneratedQuestion Generate(int templateId, int seed)
        {
            var result = new GeneratedQuestion();
            var rnd    = new Random(seed);

            // Get template from _db
            Question question =
                Db.Questions.FirstOrDefault(q => q.ID == templateId);

            if (question == null)
            {
                throw new Exception("Template not found");
            }

            result.Body         = question.Body;
            result.QuestionType = 1;
            result.Answers      = new List <GeneratedAnswer>();

            // Insert definitions to Body
            int tagsLength = TagStartInsert.Length + TagEndInsert.Length;

            for (int i = 0; i < result.Body.Length - tagsLength; i++)
            {
                if (result.Body.Substring(i, TagStartInsert.Length) !=
                    TagStartInsert)
                {
                    continue;
                }

                // We found start insert tag
                int tagStartInsertPosition = i;
                int definitionNamePosition = i + TagStartInsert.Length;
                for (i = definitionNamePosition;
                     i < result.Body.Length - TagEndInsert.Length;
                     i++)
                {
                    if (result.Body.Substring(i, TagEndInsert.Length) !=
                        TagEndInsert)
                    {
                        continue;
                    }

                    // We found end insert tag
                    string definitionName =
                        result.Body.Substring(definitionNamePosition,
                                              i - definitionNamePosition);
                    if (!string.IsNullOrEmpty(definitionName))
                    {
                        // Get definition from _db
                        Definition definition =
                            Db.Definitions.FirstOrDefault(
                                d => d.Name == definitionName);
                        if (definition != null)
                        {
                            // Get examples to definition from _db
                            List <Example> examples =
                                definition.Examples.Where(e => !e.IsAntiExample)
                                .ToList();
                            if (examples.Count == 0)
                            {
                                throw new Exception("Definition has no examples");
                            }

                            Example example =
                                examples[rnd.Next(0, examples.Count)];

                            // Replacing
                            string oldSubstr = TagStartInsert + definitionName +
                                               TagEndInsert;
                            result.Body = result.Body.Replace(oldSubstr,
                                                              example.Value.Trim
                                                                  ());
                            i = tagStartInsertPosition + example.Value.Length -
                                1;
                        }
                    }

                    break;
                }
            }

            // Get answers from _db
            List <Answer> answers = question.Answers.ToList();

            if (answers.Count == 0)
            {
                throw new Exception("Question has no answers");
            }
            foreach (Answer answer in answers)
            {
                var newAnswer = new GeneratedAnswer
                {
                    Body      = answer.Body,
                    IsCorrect = answer.IsCorrect
                };

                result.Answers.Add(newAnswer);
            }

            result.QuestionType = question.QuestionTypeID;
            return(result);
        }