/// <summary> /// Initialize test /// </summary> /// <param name="subjectIds">Subject ids in which questions taking</param> /// <param name="testType">Test type</param> /// <param name="sourceType">See TestSourceTypes class</param> /// <param name="source">Nullable id of source</param> /// <returns></returns> private ActionResult StartTest(IEnumerable <int> subjectIds, TestType testType, int sourceType, int?source) { if (subjectIds == null || !subjectIds.Any()) { return(RedirectToAction("Index", "Home")); } var questionBank = new QuestionBank(); var questions = _db.Questions.Where( x => subjectIds.Contains(x.SubjectID) && x.IsPublished && x.Answers.Any()); if (!questions.Any()) { return(RedirectToAction("Error", new { message = "Для теста не найдено ни одного вопроса. Обратитесь к администратору." })); } for (int i = 1; i <= 10; i++) { questionBank.Questions.Add(new List <int>(questions.Where(x => x.Difficulty == i).Select(x => x.ID))); } var testData = new TestData { TestCompleted = false, TrueDifficultyLevel = 5, SubjectsIds = subjectIds.ToList(), QuestionBank = questionBank, Started = TimeManager.GetCurrentTime(), TestType = testType, MaxAmountOfQuestions = _db.Questions.Count(x => subjectIds.Contains(x.SubjectID) && x.IsPublished), SourceType = sourceType, Source = source, }; Question selectedQuestion = GetQuestion(testData); testData.TestSeed = TemplateManager.GetRandomSeed(); testData.CurrentQuestionDifficulty = selectedQuestion.Difficulty; testData.CurrentQuestionId = selectedQuestion.ID; SetTestData(testData); return(RedirectToAction("Index")); }
/// <summary> /// Calculate best difficulty level based on pass/fail attempts /// </summary> /// <param name="question">Question</param> public static int GetQuestionBestDifficultyLevel(Question question) { var result = (question.TotalAttempts == 0) ? 5 : 10 - (int)(Math.Round((float)question.RightAttempts * 10 / question.TotalAttempts)); return (result == 0) ? 1 : result; }
public ActionResult CreateAndContinue(Question question) { return Create(question, "Question"); }
public ActionResult CreateAndBack(Question question) { return Create(question, "Subject"); }
/// <summary> /// Creates question /// </summary> /// <param name="question"></param> /// <param name="controller">Controller name for redirection</param> /// <returns></returns> private ActionResult Create(Question question, string controller) { if (ModelState.IsValid) { _db.Questions.AddObject(question); _db.SaveChanges(); return RedirectToAction("Edit", controller, new { id = question.ID }); } ViewBag.Types = GetQuestionTypes(); return View("Create"); }
public ActionResult Edit(Question question) { if (ModelState.IsValid) { _db.Questions.Attach(question); _db.ObjectStateManager.ChangeObjectState(question,EntityState.Modified); _db.SaveChanges(); } ViewBag.Types = GetQuestionTypes(); return View(question); }
/// <summary> /// Deprecated Method for adding a new object to the Questions EntitySet. Consider using the .Add method of the associated ObjectSet<T> property instead. /// </summary> public void AddToQuestions(Question question) { base.AddObject("Questions", question); }
/// <summary> /// Create a new Question object. /// </summary> /// <param name="id">Initial value of the ID property.</param> /// <param name="body">Initial value of the Body property.</param> /// <param name="difficulty">Initial value of the Difficulty property.</param> /// <param name="subjectID">Initial value of the SubjectID property.</param> /// <param name="questionTypeID">Initial value of the QuestionTypeID property.</param> /// <param name="isPublished">Initial value of the IsPublished property.</param> /// <param name="totalAttempts">Initial value of the TotalAttempts property.</param> /// <param name="rightAttempts">Initial value of the RightAttempts property.</param> public static Question CreateQuestion(global::System.Int32 id, global::System.String body, global::System.Int32 difficulty, global::System.Int32 subjectID, global::System.Int32 questionTypeID, global::System.Boolean isPublished, global::System.Int32 totalAttempts, global::System.Int32 rightAttempts) { Question question = new Question(); question.ID = id; question.Body = body; question.Difficulty = difficulty; question.SubjectID = subjectID; question.QuestionTypeID = questionTypeID; question.IsPublished = isPublished; question.TotalAttempts = totalAttempts; question.RightAttempts = rightAttempts; return question; }
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); }