/// <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); }