public void TestAnswerRangeTime1() { #region Arrange var qAndA = new QuestionAnswerParameter { QuestionId = 11, Answer = null, AnswerRange = null }; #endregion Arrange #region Act var result = ScoreService.ScoreQuestion(QuestionRepository.Queryable, qAndA); #endregion Act #region Assert Assert.IsNotNull(result); Assert.IsTrue(result.Invalid); Assert.AreEqual("Answer is required", result.Message); Assert.AreEqual(0, result.Score); Assert.AreEqual(0, result.ResponseId); #endregion Assert }
public void TestAnswerRangeTime11() { #region Arrange var qAndA = new QuestionAnswerParameter { QuestionId = 11, Answer = "12.34 PM", AnswerRange = "12:00 PM" }; #endregion Arrange #region Act var result = ScoreService.ScoreQuestion(QuestionRepository.Queryable, qAndA); #endregion Act #region Assert Assert.IsNotNull(result); Assert.IsTrue(result.Invalid); Assert.AreEqual("Answers must be a Time (hh:mm AM/PM)", result.Message); Assert.AreEqual(0, result.Score); Assert.AreEqual(0, result.ResponseId); #endregion Assert }
public void TestWhenQuestionHasCorrectAnswer3() { #region Arrange var qAndA = new QuestionAnswerParameter { QuestionId = 2, ResponseId = 4 }; #endregion Arrange #region Act var result = ScoreService.ScoreQuestion(QuestionRepository.Queryable, qAndA); #endregion Act #region Assert Assert.IsNotNull(result); Assert.IsFalse(result.Invalid); Assert.AreEqual(string.Empty, result.Message); Assert.AreEqual(0, result.Score); #endregion Assert }
public void TestTimeAmPmValueRangeOfNumbersNotScored() { #region Arrange var qAndA = new QuestionAnswerParameter { QuestionId = 10 }; var dict = new Dictionary<string, int>(); //answer, expected score dict.Add("12:00 AM", 9); dict.Add("12:44 AM", 9); dict.Add("12:45 AM", 9); dict.Add("12:46 AM", 1); dict.Add("1:30 AM", 1); dict.Add("1:37 AM", 1); dict.Add("1:38 AM", 2); dict.Add("1:45 AM", 2); dict.Add("1:52 AM", 2); dict.Add("01:53 AM", 3); dict.Add("2:00 AM", 3); dict.Add("2:29 AM", 3); dict.Add("2:30 AM", 4); dict.Add("03:00 AM", 4); dict.Add("3:59 AM", 4); dict.Add("4:00 AM", 5); dict.Add("4:59 AM", 5); dict.Add("5:00 AM", 5); dict.Add("6:29 AM", 5); dict.Add("6:30 AM", 6); dict.Add("8:00 AM", 6); dict.Add("9:00 AM", 6); dict.Add("9:59 AM", 6); dict.Add("10:00 AM", 7); dict.Add("11:59 AM", 7); dict.Add("12:00 PM", 7); dict.Add("03:14 PM", 7); dict.Add("3:15 PM", 8); dict.Add("6:30 PM", 8); dict.Add("9:14 PM", 8); dict.Add("9:15 PM", 12); dict.Add("10:00 PM", 12); dict.Add("11:59 PM", 12); #endregion Arrange #region Act foreach (var i in dict) { qAndA.Answer = i.Key; var result = ScoreService.ScoreQuestion(QuestionRepository.Queryable, qAndA); Assert.IsNotNull(result, string.Format("Unexpected value for {0}", i.Key)); Assert.AreEqual(0, result.Score, string.Format("Unexpected score for {0}", i.Key)); Assert.IsFalse(result.Invalid, string.Format("Unexpected value for invalid for {0}", i.Key)); Assert.AreEqual(string.Empty, result.Message); Assert.IsTrue(result.ResponseId > 0); } #endregion Act }
public void TestAnswerNotTimeAmPm9NotScored() { #region Arrange var qAndA = new QuestionAnswerParameter { QuestionId = 10, Answer = "03::0 AM" }; #endregion Arrange #region Act var result = ScoreService.ScoreQuestion(QuestionRepository.Queryable, qAndA); #endregion Act #region Assert Assert.IsNotNull(result); Assert.IsTrue(result.Invalid); Assert.AreEqual("Answer must be a Time (hh:mm AM/PM)", result.Message); Assert.AreEqual(0, result.Score); Assert.AreEqual(0, result.ResponseId); #endregion Assert }
public void TestTimeRangeValueRangeOfNumbersNotScored() { #region Arrange var qAndA = new QuestionAnswerParameter { QuestionId = 12 }; var dict = new Dictionary<int, TestScoreParameters>(); //answer, expected score #region Range of zero to .49 Hours dict.Add(1, new TestScoreParameters { Score = 1, StartTime = "12:00 AM", EndTime = "12:00 AM" }); dict.Add(2, new TestScoreParameters { Score = 1, StartTime = "12:00 AM", EndTime = "12:01 AM" }); dict.Add(3, new TestScoreParameters { Score = 1, StartTime = "12:00 AM", EndTime = "12:29 AM" }); dict.Add(4, new TestScoreParameters { Score = 1, StartTime = "2:01 PM", EndTime = "2:30 PM" }); dict.Add(5, new TestScoreParameters { Score = 1, StartTime = "3:30 PM", EndTime = "3:59 PM" }); dict.Add(6, new TestScoreParameters { Score = 1, StartTime = "1:25 PM", EndTime = "1:30 PM" }); dict.Add(7, new TestScoreParameters { Score = 1, StartTime = "11:59 PM", EndTime = "12:28 AM" }); dict.Add(8, new TestScoreParameters { Score = 1, StartTime = "11:31 PM", EndTime = "12:00 AM" }); #endregion Range of zero to .49 Hours #region Range of 0.5 to 1.24 Hours (:30 to 1:14) dict.Add(9, new TestScoreParameters { Score = 2, StartTime = "12:00 AM", EndTime = "12:30 AM" }); dict.Add(10, new TestScoreParameters { Score = 2, StartTime = "12:00 AM", EndTime = "1:14 AM" }); dict.Add(11, new TestScoreParameters { Score = 2, StartTime = "8:16 AM", EndTime = "8:46 AM" }); dict.Add(12, new TestScoreParameters { Score = 2, StartTime = "11:59 PM", EndTime = "1:13 AM" }); #endregion Range of 0.5 to 1.24 Hours #region Range of 1.25 to 1.74 dict.Add(13, new TestScoreParameters { Score = 3, StartTime = "12:00 AM", EndTime = "1:15 AM" }); dict.Add(14, new TestScoreParameters { Score = 3, StartTime = "12:00 AM", EndTime = "1:44 AM" }); dict.Add(15, new TestScoreParameters { Score = 3, StartTime = "11:59 PM", EndTime = "1:43 AM" }); #endregion Range of 1.25 to 1.74 #region Range of 1.75 to 2.49 dict.Add(16, new TestScoreParameters { Score = 4, StartTime = "12:00 AM", EndTime = "1:45 AM" }); dict.Add(17, new TestScoreParameters { Score = 4, StartTime = "12:00 AM", EndTime = "2:29 AM" }); dict.Add(18, new TestScoreParameters { Score = 4, StartTime = "11:59 PM", EndTime = "2:28 AM" }); #endregion Range of 1.75 to 2.49 #region Range of 3.50 to 3.99 dict.Add(19, new TestScoreParameters { Score = 5, StartTime = "12:00 AM", EndTime = "2:30 AM" }); dict.Add(20, new TestScoreParameters { Score = 5, StartTime = "12:00 AM", EndTime = "3:59 AM" }); dict.Add(21, new TestScoreParameters { Score = 5, StartTime = "11:59 PM", EndTime = "2:29 AM" }); dict.Add(22, new TestScoreParameters { Score = 5, StartTime = "11:59 PM", EndTime = "3:58 AM" }); #endregion Range of 3.50 to 3.99 #region Range of 4 to 5 to 8.49 dict.Add(23, new TestScoreParameters { Score = 7, StartTime = "12:00 AM", EndTime = "4:00 AM" }); dict.Add(24, new TestScoreParameters { Score = 7, StartTime = "12:00 AM", EndTime = "5:00 AM" }); dict.Add(25, new TestScoreParameters { Score = 7, StartTime = "12:00 AM", EndTime = "8:29 AM" }); dict.Add(26, new TestScoreParameters { Score = 7, StartTime = "11:59 PM", EndTime = "3:59 AM" }); dict.Add(27, new TestScoreParameters { Score = 7, StartTime = "11:59 PM", EndTime = "8:28 AM" }); #endregion Range of 4 to 8.49 #region Range of 8.5 to 14.99 dict.Add(28, new TestScoreParameters { Score = 8, StartTime = "12:00 AM", EndTime = "8:30 AM" }); dict.Add(29, new TestScoreParameters { Score = 8, StartTime = "12:00 AM", EndTime = "2:59 PM" }); dict.Add(30, new TestScoreParameters { Score = 8, StartTime = "12:00 AM", EndTime = "12:00 PM" }); dict.Add(31, new TestScoreParameters { Score = 8, StartTime = "12:00 PM", EndTime = "1:00 AM" }); dict.Add(32, new TestScoreParameters { Score = 8, StartTime = "11:59 PM", EndTime = "8:29 AM" }); dict.Add(33, new TestScoreParameters { Score = 8, StartTime = "11:59 PM", EndTime = "2:58 PM" }); #endregion Range of 8.5 to 14.99 #region Range of 14.5 to 19.99 dict.Add(34, new TestScoreParameters { Score = 9, StartTime = "12:00 AM", EndTime = "3:00 PM" }); dict.Add(35, new TestScoreParameters { Score = 9, StartTime = "12:00 AM", EndTime = "7:59 PM" }); dict.Add(36, new TestScoreParameters { Score = 9, StartTime = "12:00 PM", EndTime = "7:59 AM" }); dict.Add(38, new TestScoreParameters { Score = 9, StartTime = "11:59 PM", EndTime = "2:59 PM" }); dict.Add(39, new TestScoreParameters { Score = 9, StartTime = "11:59 PM", EndTime = "7:58 PM" }); #endregion Range of 14.5 to 19.99 #region Range of 20 to 22.99 dict.Add(40, new TestScoreParameters { Score = 10, StartTime = "12:00 AM", EndTime = "8:00 PM" }); dict.Add(41, new TestScoreParameters { Score = 10, StartTime = "12:00 AM", EndTime = "10:59 PM" }); dict.Add(42, new TestScoreParameters { Score = 10, StartTime = "12:00 PM", EndTime = "10:59 AM" }); dict.Add(43, new TestScoreParameters { Score = 10, StartTime = "11:59 PM", EndTime = "7:59 PM" }); #endregion Range of 20 to 22.99 #region Range of 22.99 to 23.99 dict.Add(44, new TestScoreParameters { Score = 12, StartTime = "12:00 AM", EndTime = "11:00 PM" }); dict.Add(45, new TestScoreParameters { Score = 12, StartTime = "12:00 AM", EndTime = "11:58 PM" }); dict.Add(46, new TestScoreParameters { Score = 12, StartTime = "12:00 AM", EndTime = "11:59 PM" }); dict.Add(47, new TestScoreParameters { Score = 12, StartTime = "12:00 PM", EndTime = "11:59 AM" }); #endregion Range of 22.99 to 23.99 #endregion Arrange #region Act foreach (var i in dict) { qAndA.Answer = i.Value.StartTime; qAndA.AnswerRange = i.Value.EndTime; var result = ScoreService.ScoreQuestion(QuestionRepository.Queryable, qAndA); Assert.IsNotNull(result, string.Format("Unexpected value for {0}", i.Key)); Assert.AreEqual(0, result.Score, string.Format("Unexpected score for {0}", i.Key)); Assert.IsFalse(result.Invalid, string.Format("Unexpected value for invalid for {0}", i.Key)); Assert.AreEqual(string.Empty, result.Message); Assert.IsTrue(result.ResponseId > 0); } #endregion Act }
public void TestCreatePostWhenQuestionsAnswered3() { #region Arrange new FakeResponses(3, ResponseRepository); Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { "" }); var qAndA = new QuestionAnswerParameter[1]; qAndA[0] = new QuestionAnswerParameter(); qAndA[0].QuestionId = 1; qAndA[0].BypassQuestion = false; var questions = new List<Question>(); questions.Add(CreateValidEntities.Question(1)); questions[0].Category = CreateValidEntities.Category(1); questions[0].Survey = CreateValidEntities.Survey(2); questions[0].Survey.SetIdTo(2); questions[0].Category.IsActive = true; questions[0].IsOpenEnded = true; questions[0].OpenEndedQuestionType = (int) QuestionType.TimeRange; new FakeQuestions(0, QuestionRepository, questions); var surveys = new List<Survey>(); for (int i = 0; i < 3; i++) { surveys.Add(CreateValidEntities.Survey(i + 1)); } surveys[1].Questions.Add(QuestionRepository.GetNullableById(1)); new FakeSurveys(0, SurveyRepository, surveys); var qAndAWithError = new QuestionAnswerParameter[1]; qAndAWithError[0] = new QuestionAnswerParameter(); qAndAWithError[0].QuestionId = 1; qAndAWithError[0].BypassQuestion = false; qAndAWithError[0].Invalid = false; qAndAWithError[0].Message = null; qAndAWithError[0].OpenEndedNumericAnswer = null; qAndAWithError[0].ResponseId = 2; qAndAWithError[0].Score = 99; qAndAWithError[0].Answer = "Now"; qAndAWithError[0].AnswerRange = "Then"; ScoreService.Expect(a => a.ScoreQuestion(Arg<IQueryable<Question>>.Is.Anything, Arg<QuestionAnswerParameter>.Is.Anything)).Return(qAndAWithError[0]).Repeat.Any(); #endregion Arrange #region Act Controller.Create(2, CreateValidEntities.SurveyResponse(1), qAndA) .AssertActionRedirect() .ToAction<SurveyResponseController>(a => a.Results(1)); #endregion Act #region Assert Assert.AreEqual("SurveyResponse Created Successfully", Controller.Message); ScoreService.AssertWasCalled(a => a.ScoreQuestion(Arg<IQueryable<Question>>.Is.Anything, Arg<QuestionAnswerParameter>.Is.Anything)); ScoreService.AssertWasCalled(a => a.CalculateScores(Arg<IRepository>.Is.Anything, Arg<SurveyResponse>.Is.Anything)); SurveyResponseRepository.AssertWasCalled(a => a.EnsurePersistent(Arg<SurveyResponse>.Is.Anything)); var args = (SurveyResponse)SurveyResponseRepository.GetArgumentsForCallsMadeOn(a => a.EnsurePersistent(Arg<SurveyResponse>.Is.Anything))[0][0]; Assert.AreEqual("SID1", args.StudentId); Assert.AreEqual("username", args.UserId); Assert.AreEqual(1, args.Answers.Count); Assert.AreEqual(null, args.Answers[0].OpenEndedAnswer); Assert.AreEqual(2, args.Answers[0].Response.Id); Assert.AreEqual(99, args.Answers[0].Score); Assert.AreEqual(false, args.Answers[0].BypassScore); Assert.AreEqual("Now_Then", args.Answers[0].OpenEndedStringAnswer); #endregion Assert }
public void TestCreatePostThrowsExceptionIfPassedQuestionIdNotFound() { var thisFar = false; try { #region Arrange Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { "" }); var qAndA = new QuestionAnswerParameter[1]; qAndA[0] = new QuestionAnswerParameter(); qAndA[0].QuestionId = 99; new FakeSurveys(3, SurveyRepository); #endregion Arrange #region Act thisFar = true; Controller.Create(2, CreateValidEntities.SurveyResponse(1), qAndA); #endregion Act } catch (Exception ex) { Assert.IsTrue(thisFar); Assert.IsNotNull(ex); Assert.AreEqual("Question not found.\n SurveyId: 2\n QuestionId: 99\n Question #: 0", ex.Message); throw; } }
public void TestCreatePostThrowsExceptionIfRelatedSurveyDoesNotMatch() { var thisFar = false; try { #region Arrange Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { "" }); var qAndA = new QuestionAnswerParameter[1]; qAndA[0] = new QuestionAnswerParameter(); qAndA[0].QuestionId = 1; new FakeSurveys(3, SurveyRepository); var questions = new List<Question>(); questions.Add(CreateValidEntities.Question(1)); questions[0].Category = CreateValidEntities.Category(1); questions[0].Survey = SurveyRepository.GetNullableById(3); questions[0].Category.IsActive = true; new FakeQuestions(0, QuestionRepository, questions); #endregion Arrange #region Act thisFar = true; Controller.Create(2, CreateValidEntities.SurveyResponse(1), qAndA); #endregion Act } catch (Exception ex) { Assert.IsTrue(thisFar); Assert.IsNotNull(ex); Assert.AreEqual("Related Survey does not match passed survey 3--2", ex.Message); throw; } }
public void TestCreatePostServiceParameterCheck() { #region Arrange Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { "" }); var qAndA = new QuestionAnswerParameter[1]; qAndA[0] = new QuestionAnswerParameter(); qAndA[0].QuestionId = 1; qAndA[0].BypassQuestion = false; var questions = new List<Question>(); questions.Add(CreateValidEntities.Question(1)); questions[0].Category = CreateValidEntities.Category(1); questions[0].Survey = CreateValidEntities.Survey(2); questions[0].Survey.SetIdTo(2); questions[0].Category.IsActive = true; questions[0].IsOpenEnded = false; questions.Add(CreateValidEntities.Question(2)); questions[1].Category = CreateValidEntities.Category(1); questions[1].Survey = CreateValidEntities.Survey(2); questions[1].Survey.SetIdTo(2); questions[1].Category.IsActive = true; questions[1].IsOpenEnded = false; new FakeQuestions(0, QuestionRepository, questions); var surveys = new List<Survey>(); for (int i = 0; i < 3; i++) { surveys.Add(CreateValidEntities.Survey(i + 1)); } surveys[1].Questions.Add(QuestionRepository.GetNullableById(1)); surveys[1].Questions.Add(QuestionRepository.GetNullableById(2)); new FakeSurveys(0, SurveyRepository, surveys); var qAndAWithError = new QuestionAnswerParameter[1]; qAndAWithError[0] = new QuestionAnswerParameter(); qAndAWithError[0].QuestionId = 1; qAndAWithError[0].BypassQuestion = false; qAndAWithError[0].Invalid = false; ScoreService.Expect(a => a.ScoreQuestion(Arg<IQueryable<Question>>.Is.Anything, Arg<QuestionAnswerParameter>.Is.Anything)).Return(qAndAWithError[0]).Repeat.Any(); #endregion Arrange #region Act var result = Controller.Create(2, CreateValidEntities.SurveyResponse(1), qAndA) .AssertViewRendered() .WithViewData<SurveyResponseViewModel>(); #endregion Act #region Assert Controller.ModelState.AssertErrorsAre("You must answer all survey questions."); Assert.AreEqual("You must answer all survey questions.", Controller.Message); var args = ScoreService.GetArgumentsForCallsMadeOn( a => a.ScoreQuestion(Arg<IQueryable<Question>>.Is.Anything, Arg<QuestionAnswerParameter>.Is.Anything))[0]; Assert.IsNotNull(args); Assert.AreEqual(2, (args[0] as IQueryable<Question>).Count()); Assert.AreEqual("Name1", (args[0] as IQueryable<Question>).ElementAt(0).Name); Assert.AreEqual("Name2", (args[0] as IQueryable<Question>).ElementAt(1).Name); Assert.IsNotNull(result); #endregion Assert }
public void TestCreatePostReturnsViewWhenAnswerIsInvalid() { #region Arrange Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { "" }); var qAndA = new QuestionAnswerParameter[1]; qAndA[0] = new QuestionAnswerParameter(); qAndA[0].QuestionId = 1; qAndA[0].BypassQuestion = false; var questions = new List<Question>(); questions.Add(CreateValidEntities.Question(1)); questions[0].Category = CreateValidEntities.Category(1); questions[0].Survey = CreateValidEntities.Survey(2); questions[0].Survey.SetIdTo(2); questions[0].Category.IsActive = true; questions[0].IsOpenEnded = false; new FakeQuestions(0, QuestionRepository, questions); var surveys = new List<Survey>(); for (int i = 0; i < 3; i++) { surveys.Add(CreateValidEntities.Survey(i+1)); } surveys[1].Questions.Add(QuestionRepository.GetNullableById(1)); new FakeSurveys(0, SurveyRepository, surveys); var qAndAWithError = new QuestionAnswerParameter[1]; qAndAWithError[0] = new QuestionAnswerParameter(); qAndAWithError[0].QuestionId = 1; qAndAWithError[0].BypassQuestion = false; qAndAWithError[0].Invalid = true; qAndAWithError[0].Message = "Faked Error"; ScoreService.Expect(a => a.ScoreQuestion(Arg<IQueryable<Question>>.Is.Anything, Arg<QuestionAnswerParameter>.Is.Anything)).Return(qAndAWithError[0]).Repeat.Any(); #endregion Arrange #region Act var result = Controller.Create(2, CreateValidEntities.SurveyResponse(1), qAndA) .AssertViewRendered() .WithViewData<SurveyResponseViewModel>(); #endregion Act #region Assert Controller.ModelState.AssertErrorsAre("Faked Error"); Assert.AreEqual("Please correct all errors and submit.", Controller.Message); Assert.IsNotNull(result); #endregion Assert }
public ActionResult Create(int id, SurveyResponse surveyResponse, QuestionAnswerParameter[] questions) { var survey = Repository.OfType<Survey>().GetNullableById(id); if (survey == null || !survey.IsActive) { Message = "Survey not found or not active."; return this.RedirectToAction<ErrorController>(a => a.Index()); } var surveyResponseToCreate = new SurveyResponse(survey); if (questions == null) { questions = new QuestionAnswerParameter[0]; } ModelState.Clear(); //Set non-dynamic surveyResponse values surveyResponseToCreate.StudentId = surveyResponse.StudentId; surveyResponseToCreate.UserId = CurrentUser.Identity.Name.ToLower(); //Check each question, create an answer for it if there isn't one. var length = questions.Length; for (int i = 0; i < length; i++) { var question = Repository.OfType<Question>().GetNullableById(questions[i].QuestionId); Check.Require(question != null, string.Format("Question not found.\n SurveyId: {0}\n QuestionId: {1}\n Question #: {2}", id, questions[i].QuestionId, i)); Check.Require(question.Category.IsActive, string.Format("Related Category is not active for question Id {0}", questions[i].QuestionId)); Check.Require(question.Category.IsCurrentVersion, string.Format("Related Category is not current version for question Id {0}", questions[i].QuestionId)); Check.Require(question.Survey.Id == survey.Id, string.Format("Related Survey does not match passed survey {0}--{1}", question.Survey.Id, survey.Id)); Answer answer; if (surveyResponseToCreate.Answers.Where(a => a.Question.Id == question.Id).Any()) { answer = surveyResponseToCreate.Answers.Where(a => a.Question.Id == question.Id).First(); } else { answer = new Answer(); } //Score question and specify any errors questions[i] = _scoreService.ScoreQuestion(surveyResponseToCreate.Survey.Questions.AsQueryable(), questions[i]); if (questions[i].Invalid && !questions[i].BypassQuestion) { ModelState.AddModelError(string.Format("Questions[{0}]", i), questions[i].Message); } if (questions[i].BypassQuestion) { answer.OpenEndedAnswer = null; answer.Response = null; answer.Score = 0; answer.BypassScore = true; questions[i].Answer = string.Empty; questions[i].ResponseId = 0; } else { answer.OpenEndedAnswer = questions[i].OpenEndedNumericAnswer; if (question.IsOpenEnded && question.OpenEndedQuestionType == (int)QuestionType.TimeRange) { answer.OpenEndedStringAnswer = string.Format("{0}_{1}", questions[i].Answer, questions[i].AnswerRange); } else { answer.OpenEndedStringAnswer = questions[i].Answer; // The actual answer they gave. } answer.Response = Repository.OfType<Response>().GetNullableById(questions[i].ResponseId); answer.Score = questions[i].Score; answer.BypassScore = false; } answer.Question = question; answer.Category = question.Category; surveyResponseToCreate.AddAnswers(answer); } surveyResponseToCreate.TransferValidationMessagesTo(ModelState); if (survey.Questions.Where(a => a.IsActive && a.Category.IsActive && a.Category.IsCurrentVersion).Count() != questions.Count()) { Message = "You must answer all survey questions."; ModelState.AddModelError("Question", "You must answer all survey questions."); } if (ModelState.IsValid) { _scoreService.CalculateScores(Repository, surveyResponseToCreate); _surveyResponseRepository.EnsurePersistent(surveyResponseToCreate); Message = "Below are the customized goals for the survey you entered. You can use the \"Print Results\" link below to print this individual goal sheet. If you would like to print a text-only version or goal sheets for multiple participants at one time go to the Educators Dashboard and select the Review & Print section for the survey you are working with."; return this.RedirectToAction(a => a.Results(surveyResponseToCreate.Id, null)); } else { //foreach (var modelState in ModelState.Values.Where(a => a.Errors.Count() > 0)) //{ // var x = modelState; //} if (string.IsNullOrWhiteSpace(Message)) { Message = "Please correct all errors and submit."; } var viewModel = SurveyResponseViewModel.Create(Repository, survey); viewModel.SurveyResponse = surveyResponse; viewModel.SurveyAnswers = questions; return View(viewModel); } }
public ActionResult AnswerNext(int id, QuestionAnswerParameter questions, string byPassAnswer, Guid? publicGuid) { var surveyResponse = _surveyResponseRepository.GetNullableById(id); if (string.IsNullOrWhiteSpace(CurrentUser.Identity.Name)) { surveyResponse = (SurveyResponse)Session[publicGuid.ToString()]; } if (surveyResponse == null || !surveyResponse.IsPending) { Message = "Pending survey not found"; return this.RedirectToAction<ErrorController>(a => a.Index()); } if (!string.IsNullOrWhiteSpace(CurrentUser.Identity.Name)) { if (surveyResponse.UserId.ToLower() != CurrentUser.Identity.Name.ToLower()) { Message = "Not your survey"; return this.RedirectToAction<ErrorController>(a => a.NotAuthorized()); } } else { if (surveyResponse.UserId.ToLower() != publicGuid.ToString().ToLower()) { Message = "Not your survey"; return this.RedirectToAction<ErrorController>(a => a.NotAuthorized()); } } ViewBag.surveyimage = string.Format("{0}-survey", surveyResponse.Survey.ShortName.ToLower().Trim()); var question = Repository.OfType<Question>().GetNullableById(questions.QuestionId); if (question == null) { Message = "Question survey not found"; return this.RedirectToAction<ErrorController>(a => a.Index()); } Answer answer; if (surveyResponse.Answers.Where(a => a.Question.Id == question.Id).Any()) { answer = surveyResponse.Answers.Where(a => a.Question.Id == question.Id).First(); } else { answer = new Answer(); } if (!string.IsNullOrEmpty(byPassAnswer) && question.AllowBypass) { answer.OpenEndedAnswer = null; answer.Response = null; answer.Score = 0; answer.BypassScore = true; answer.OpenEndedStringAnswer = byPassAnswer; answer.Question = question; answer.Category = question.Category; surveyResponse.AddAnswers(answer); if (!string.IsNullOrWhiteSpace(CurrentUser.Identity.Name)) { _surveyResponseRepository.EnsurePersistent(surveyResponse); } else { Session[publicGuid.ToString()] = surveyResponse; } return this.RedirectToAction(a => a.AnswerNext(surveyResponse.Id, publicGuid)); } else { questions = _scoreService.ScoreQuestion(surveyResponse.Survey.Questions.AsQueryable(), questions); } if (questions.Invalid) { ModelState.AddModelError("Questions", questions.Message); } else { //It is valid, add the answer. answer.Question = question; answer.Category = question.Category; answer.OpenEndedAnswer = questions.OpenEndedNumericAnswer; if (question.IsOpenEnded && question.OpenEndedQuestionType == (int)QuestionType.TimeRange) { answer.OpenEndedStringAnswer = string.Format("{0}_{1}", questions.Answer, questions.AnswerRange); } else { answer.OpenEndedStringAnswer = questions.Answer; // The actual answer they gave. } answer.Response = Repository.OfType<Response>().GetNullableById(questions.ResponseId); answer.Score = questions.Score; surveyResponse.AddAnswers(answer); } if (ModelState.IsValid) { if (!string.IsNullOrWhiteSpace(CurrentUser.Identity.Name)) { _surveyResponseRepository.EnsurePersistent(surveyResponse); } else { Session[publicGuid.ToString()] = surveyResponse; } return this.RedirectToAction(a => a.AnswerNext(surveyResponse.Id, publicGuid)); } var viewModel = SingleAnswerSurveyResponseViewModel.Create(Repository, surveyResponse.Survey, surveyResponse); viewModel.PublicGuid = publicGuid; if(question.AllowBypass) { viewModel.DisplayBypass = true; } return View(viewModel); }
/// <summary> /// Score question and check for validity /// If an answer is invalid, the Value QuestionAnswerParameter.Invalid will be true and the QuestionAnswerParameter.Message will have the error. /// </summary> /// <param name="questions"></param> /// <param name="questionAnswerParameter"></param> /// <returns></returns> public QuestionAnswerParameter ScoreQuestion(IQueryable<Question> questions, QuestionAnswerParameter questionAnswerParameter) { questionAnswerParameter.Score = 0; questionAnswerParameter.Invalid = false; questionAnswerParameter.Message = string.Empty; questionAnswerParameter.OpenEndedNumericAnswer = null; var question = questions.Where(a => a.Id == questionAnswerParameter.QuestionId).Single(); if (question.IsOpenEnded) { #region Open Ended Question if (string.IsNullOrWhiteSpace(questionAnswerParameter.Answer)) { questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Answer is required"; questionAnswerParameter.Score = 0; } else { int? responseId = null; switch ((QuestionType)question.OpenEndedQuestionType) { case QuestionType.WholeNumber: #region Old Way Open Ended Int Question //int number; //if (int.TryParse(questionAnswerParameter.Answer, out number)) //{ // questionAnswerParameter.OpenEndedNumericAnswer = number; // #region Exact Match // var response = question.Responses.Where(a => a.IsActive && a.Value == number.ToString()).FirstOrDefault(); // if (response != null) // { // responseId = response.Id; // } // #endregion Exact Match // #region High Value // if (responseId == null) // { // //Check For High Value // response = // question.Responses.Where(a => a.IsActive && a.Value.Contains("+")).FirstOrDefault(); // if (response != null) // { // int highValue; // if (Int32.TryParse(response.Value, out highValue)) // { // if (number >= highValue) // { // responseId = response.Id; // } // } // } // } // #endregion High Value // #region Low Value // if (responseId == null) // { // //Check for low value // response = question.Responses.Where(a => a.IsActive && a.Value.Contains("-")).FirstOrDefault(); // if (response != null) // { // int lowValue; // if (Int32.TryParse(response.Value, out lowValue)) // { // if (number <= Math.Abs(lowValue)) // { // responseId = response.Id; // } // } // } // } // #endregion Low Value // //Found an exact match, or a high/low score // if (responseId != null) // { // questionAnswerParameter.ResponseId = responseId.Value; // questionAnswerParameter.Score = question.Responses.Where(a => a.Id == responseId.Value).Single().Score; // } // else // { // //questionAnswerParameter.Invalid = true; // questionAnswerParameter.Message = "Matching Value to score not found"; // questionAnswerParameter.Score = 0; // } //} //else //{ // questionAnswerParameter.Invalid = true; // questionAnswerParameter.Message = "Answer must be a whole number"; // questionAnswerParameter.Score = 0; //} #endregion Old Way Open Ended Int Question //If it finds an exact match it uses that. //If the passed value is less than smallest response, it uses the smallest response //if the passed value is greater than the largest response, it uses the largest response //If the passed value is between two responses, it uses the one that it is closer to //... if exactly in the middle, it chooses the one with the higher score. #region Open Ended Int Question int number; if (int.TryParse(questionAnswerParameter.Answer, out number)) { var intDict = new Dictionary<int, int>(); int? high = null; //Get a list of all active responses don't use any that can't be changed into a float. foreach (var response in question.Responses.Where(a => a.IsActive)) { int tempInt; if (int.TryParse(response.Value, out tempInt)) { intDict.Add(tempInt, response.Id); } } //Sort the valid responses. var sortedIntDict = intDict.OrderBy(a => a.Key); for (int i = 0; i < sortedIntDict.Count(); i++) { if (number == sortedIntDict.ElementAt(i).Key) { responseId = sortedIntDict.ElementAt(i).Value; break; } if (number < sortedIntDict.ElementAt(i).Key) { high = i; break; } } //Didn't find an exact match if (responseId == null) { if (high != null) { if (high.Value == 0) //Use the lowest value { responseId = sortedIntDict.ElementAt(high.Value).Value; } else //Somewhere inbetween. pick closest one, or one with highest score { var lowDiff = number - sortedIntDict.ElementAt(high.Value - 1).Key; var highDiff = sortedIntDict.ElementAt(high.Value).Key - number; if (lowDiff == highDiff) { if (question.Responses.Where(a => a.Id == sortedIntDict.ElementAt(high.Value - 1).Value).Single().Score > question.Responses.Where(a => a.Id == sortedIntDict.ElementAt(high.Value).Value).Single().Score) { responseId = sortedIntDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedIntDict.ElementAt(high.Value).Value; } } else if (lowDiff < highDiff) { responseId = sortedIntDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedIntDict.ElementAt(high.Value).Value; } } } else if (sortedIntDict.Count() > 0) //Use the highest value { responseId = sortedIntDict.ElementAt(sortedIntDict.Count() - 1).Value; } } //Found an exact match, or a high/low score if (responseId != null) { questionAnswerParameter.ResponseId = responseId.Value; questionAnswerParameter.Score = question.Responses.Where(a => a.Id == responseId.Value).Single().Score; } else { //questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Matching Value to score not found"; questionAnswerParameter.Score = 0; } } else { questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Answer must be a whole number"; questionAnswerParameter.Score = 0; } #endregion Open Ended Int Question break; case QuestionType.Decimal: //If it finds an exact match it uses that. //If the passed value is less than smallest response, it uses the smallest response //if the passed value is greater than the largest response, it uses the largest response //If the passed value is between two responses, it uses the one that it is closer to //... if exactly in the middle, it chooses the one with the higher score. #region Open Ended Decimal Question float floatNumber; if (float.TryParse(questionAnswerParameter.Answer, out floatNumber)) { var floatDict = new Dictionary<float, int>(); int? high = null; //Get a list of all active responses don't use any that can't be changed into a float. foreach (var response in question.Responses.Where(a => a.IsActive)) { float tempFloat; if (float.TryParse(response.Value, out tempFloat)) { floatDict.Add(tempFloat, response.Id); } } //Sort the valid responses. var sortedDict = floatDict.OrderBy(a => a.Key); for (int i = 0; i < sortedDict.Count(); i++) { if (floatNumber == sortedDict.ElementAt(i).Key) { responseId = sortedDict.ElementAt(i).Value; break; } if (floatNumber < sortedDict.ElementAt(i).Key) { high = i; break; } } //Didn't find an exact match if (responseId == null) { if (high != null) { if (high.Value == 0) //Use the lowest value { responseId = sortedDict.ElementAt(high.Value).Value; } else //Somewhere inbetween. pick closest one, or one with highest score { var lowDiff = floatNumber - sortedDict.ElementAt(high.Value - 1).Key; var highDiff = sortedDict.ElementAt(high.Value).Key - floatNumber; if (lowDiff == highDiff) { if (question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value - 1).Value).Single().Score > question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value).Value).Single().Score) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } else if (lowDiff < highDiff) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } } else if (sortedDict.Count() > 0) //Use the highest value { responseId = sortedDict.ElementAt(sortedDict.Count()-1).Value; } } //Found an exact match, or a high/low score if (responseId != null) { questionAnswerParameter.ResponseId = responseId.Value; questionAnswerParameter.Score = question.Responses.Where(a => a.Id == responseId.Value).Single().Score; } else { //questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Matching Value to score not found"; questionAnswerParameter.Score = 0; } } else { questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Answer must be a number (decimal ok)"; questionAnswerParameter.Score = 0; } #endregion Open Ended Decimal Question break; case QuestionType.Time: //Works the same way as the Decimal above by first converting the time into a float. #region Open Ended Time Question float floatTime; if (questionAnswerParameter.Answer.TimeTryParse(out floatTime)) { var floatDict = new Dictionary<float, int>(); int? high = null; //Get a list of all active responses don't use any that can't be changed into a float. foreach (var response in question.Responses.Where(a => a.IsActive)) { float tempFloat; if (response.Value.TimeTryParse(out tempFloat)) { floatDict.Add(tempFloat, response.Id); } } //Sort the valid responses. var sortedDict = floatDict.OrderBy(a => a.Key); for (int i = 0; i < sortedDict.Count(); i++) { if (floatTime == sortedDict.ElementAt(i).Key) { responseId = sortedDict.ElementAt(i).Value; break; } if (floatTime < sortedDict.ElementAt(i).Key) { high = i; break; } } //Didn't find an exact match if (responseId == null) { if (high != null) { if (high.Value == 0) //Use the lowest value { responseId = sortedDict.ElementAt(high.Value).Value; } else //Somewhere inbetween. pick closest one, or one with highest score { var lowDiff = floatTime - sortedDict.ElementAt(high.Value - 1).Key; var highDiff = sortedDict.ElementAt(high.Value).Key - floatTime; if (lowDiff == highDiff) { if (question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value - 1).Value).Single().Score > question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value).Value).Single().Score) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } else if (lowDiff < highDiff) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } } else if (sortedDict.Count() > 0) //Use the highest value { responseId = sortedDict.ElementAt(sortedDict.Count()-1).Value; } } //Found an exact match, or a high/low score if (responseId != null) { questionAnswerParameter.ResponseId = responseId.Value; questionAnswerParameter.Score = question.Responses.Where(a => a.Id == responseId.Value).Single().Score; } else { //questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Matching Value to score not found"; questionAnswerParameter.Score = 0; } } else { questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Answer must be a Time (hh:mm)"; questionAnswerParameter.Score = 0; } #endregion Open Ended Time Question break; case QuestionType.TimeAmPm: //Works the same way as the Decimal above by first converting the time into a float. #region Open Ended Time AM/PM Question float floatTimeAmPm; if (questionAnswerParameter.Answer.TimeTryParseAmPm(out floatTimeAmPm)) { var floatDict = new Dictionary<float, int>(); int? high = null; //Get a list of all active responses don't use any that can't be changed into a float. foreach (var response in question.Responses.Where(a => a.IsActive)) { float tempFloat; if (response.Value.TimeTryParseAmPm(out tempFloat)) { floatDict.Add(tempFloat, response.Id); } } //Sort the valid responses. var sortedDict = floatDict.OrderBy(a => a.Key); for (int i = 0; i < sortedDict.Count(); i++) { if (floatTimeAmPm == sortedDict.ElementAt(i).Key) { responseId = sortedDict.ElementAt(i).Value; break; } if (floatTimeAmPm < sortedDict.ElementAt(i).Key) { high = i; break; } } //Didn't find an exact match if (responseId == null) { if (high != null) { if (high.Value == 0) //Use the lowest value { responseId = sortedDict.ElementAt(high.Value).Value; } else //Somewhere inbetween. pick closest one, or one with highest score { var lowDiff = floatTimeAmPm - sortedDict.ElementAt(high.Value - 1).Key; var highDiff = sortedDict.ElementAt(high.Value).Key - floatTimeAmPm; if (lowDiff == highDiff) { if (question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value - 1).Value).Single().Score > question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value).Value).Single().Score) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } else if (lowDiff < highDiff) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } } else if (sortedDict.Count() > 0) //Use the highest value { responseId = sortedDict.ElementAt(sortedDict.Count() - 1).Value; } } //Found an exact match, or a high/low score if (responseId != null) { questionAnswerParameter.ResponseId = responseId.Value; questionAnswerParameter.Score = question.Responses.Where(a => a.Id == responseId.Value).Single().Score; } else { //questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Matching Value to score not found"; questionAnswerParameter.Score = 0; } } else { questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Answer must be a Time (hh:mm AM/PM)"; questionAnswerParameter.Score = 0; } #endregion Open Ended Time AM/PM Question break; case QuestionType.TimeRange: //Works the same way as the Decimal above by first converting the time into a float. #region Open Ended Time Range Question var timeRangeValid = true; float startTime; float endTime; float ajustedDifference; if (!questionAnswerParameter.Answer.TimeTryParseAmPm(out startTime)) { timeRangeValid = false; } if (!questionAnswerParameter.AnswerRange.TimeTryParseAmPm(out endTime)) { timeRangeValid = false; } if(timeRangeValid) { if(startTime > endTime) { endTime += 24; //Add a day. } ajustedDifference = endTime - startTime; var floatDict = new Dictionary<float, int>(); int? high = null; //Get a list of all active responses don't use any that can't be changed into a float. foreach (var response in question.Responses.Where(a => a.IsActive)) { float tempFloat; if (float.TryParse(response.Value, out tempFloat)) { floatDict.Add(tempFloat, response.Id); } } //Sort the valid responses. var sortedDict = floatDict.OrderBy(a => a.Key); for (int i = 0; i < sortedDict.Count(); i++) { if (ajustedDifference == sortedDict.ElementAt(i).Key) { responseId = sortedDict.ElementAt(i).Value; break; } if (ajustedDifference < sortedDict.ElementAt(i).Key) { high = i; break; } } //Didn't find an exact match if (responseId == null) { if (high != null) { if (high.Value == 0) //Use the lowest value { responseId = sortedDict.ElementAt(high.Value).Value; } else //Somewhere inbetween. pick closest one, or one with highest score { var lowDiff = ajustedDifference - sortedDict.ElementAt(high.Value - 1).Key; var highDiff = sortedDict.ElementAt(high.Value).Key - ajustedDifference; if (lowDiff == highDiff) { if (question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value - 1).Value).Single().Score > question.Responses.Where(a => a.Id == sortedDict.ElementAt(high.Value).Value).Single().Score) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } else if (lowDiff < highDiff) { responseId = sortedDict.ElementAt(high.Value - 1).Value; } else { responseId = sortedDict.ElementAt(high.Value).Value; } } } else if (sortedDict.Count() > 0) //Use the highest value { responseId = sortedDict.ElementAt(sortedDict.Count() - 1).Value; } } //Found an exact match, or a high/low score if (responseId != null) { questionAnswerParameter.ResponseId = responseId.Value; questionAnswerParameter.Score = question.Responses.Where(a => a.Id == responseId.Value).Single().Score; } else { //questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Matching Value to score not found"; questionAnswerParameter.Score = 0; } } else { questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Answers must be a Time (hh:mm AM/PM)"; questionAnswerParameter.Score = 0; } #endregion Open Ended Time Range Question break; default: Check.Require(false, string.Format("Unknown QuestionType encountered: '{0}'", question.OpenEndedQuestionType)); break; } } #endregion Open Ended Question } else { #region Radio Button Question var response = question.Responses.Where(a => a.Id == questionAnswerParameter.ResponseId && a.IsActive).FirstOrDefault(); if (response == null) { questionAnswerParameter.Invalid = true; questionAnswerParameter.Message = "Answer is required"; questionAnswerParameter.Score = 0; } else { questionAnswerParameter.Score = response.Score; } #endregion Radio Button Question } if (question.Category.DoNotUseForCalculations) { questionAnswerParameter.Score = 0; } return questionAnswerParameter; }