/// <summary> /// Retrieves object containing an Assessment Category and an optional currently selected question (will choose first question if null) to be filled out by user. /// </summary> /// <param name="userid">hashed userid</param> /// <param name="id">ID of Assessment Category</param> /// <param name="questionID">Currently selected question (defaults to first question if null)</param> /// <returns></returns> public ConductAssessmentViewModel ConductAssessment(string userid, int id, int?questionID) { var ViewModel = new ConductAssessmentViewModel { CategoryID = id, UserDetailID = db.UserDetails.Single(o => o.UserId == userid).ID }; //next unanswered question if any var nextQuestion = db.AssessmentQuestions.FirstOrDefault(o => o.AssessmentCategoryID == id && !o.UserAssessmentQuestions.Any(x => x.UserAssessmentCategory.UserAssessment.UserDetail.UserId == userid) ); if (nextQuestion == null) { nextQuestion = db.AssessmentQuestions.First(o => o.AssessmentCategoryID == id); } var levels = db.AssessmentLevels.ToList(); var Question = questionID == null ? nextQuestion : db.AssessmentQuestions.Single(o => o.ID == questionID); var AssessmentQuestion = db.AssessmentQuestions.Where(o => o.ID == Question.ID).Single(); ViewModel.CategoryName = Question.AssessmentCategory.Translation.EN; ViewModel.Question = new AnswerQuestonViewModel { ID = AssessmentQuestion.ID, QuestionHeading = AssessmentQuestion.Translation.EN, QuestionBody = AssessmentQuestion.Translation1.EN, Score = AssessmentQuestion.UserAssessmentQuestions.Any(x => x.UserAssessmentCategory.UserAssessment.UserDetail.UserId == userid) ? AssessmentQuestion.UserAssessmentQuestions.Single(x => x.UserAssessmentCategory.UserAssessment.UserDetail.UserId == userid).Score : null, QuestionCode = AssessmentQuestion.QuestionCode, Levels = levels.Select(o => new AnswerLevelListItem { ID = o.ID, Name = o.Translation.EN, LevelOrder = o.LevelOrder, CheckoffItems = AssessmentQuestion.AssessmentCheckoffItems.Where(x => x.AssessmentLevelID == o.ID).Select(x => new AnswerCheckoffItem { ID = x.ID, LevelID = o.ID, Wording = x.Translation.EN, Checked = x.UserAssessmentCheckoffItems.Any(y => y.AssessmentCheckoffItemID == x.ID && y.Checked) }).ToList() }).ToList() }; ViewModel.Questions = AssessmentQuestion.AssessmentCategory.AssessmentQuestions.Select(o => new AnswerQuestonViewModel { ID = o.ID, QuestionHeading = o.Translation.EN, QuestionBody = o.Translation1.EN, QuestionCode = o.QuestionCode, Score = o.UserAssessmentQuestions.Any(x => x.UserAssessmentCategory.UserAssessment.UserDetail.UserId == userid) ? o.UserAssessmentQuestions.Single(x => x.UserAssessmentCategory.UserAssessment.UserDetail.UserId == userid).Score : null } ).OrderBy(o => o.ID).ToList(); var Answer = AssessmentQuestion.UserAssessmentQuestions.SingleOrDefault(o => o.AssessmentQuestionID == Question.ID && o.UserAssessmentCategory.UserAssessment.UserDetail.UserId == userid ); ViewModel.Score = ViewModel.Questions.Any(o => o.Score != null) ? Math.Round((decimal)ViewModel.Questions.Sum(o => o.Score) / ViewModel.Questions.Count(o => o.Score != null), 1) : 0; if (Answer != null) { ViewModel.Question.Comment = Answer.Comments; } return(ViewModel); }
/// <summary> /// Save the response of an assessment including checked off Checkoff Items and Comment /// </summary> /// <param name="userid">hashed userid</param> /// <param name="ViewModel">Object containing Response data</param> /// <returns>ID of next Question in this Category (will loop to first Question at the end)</returns> public int SaveAnswer(string userid, ConductAssessmentViewModel ViewModel) { //Get the user's response to Question if exists (ie: they have answered this question already and are updating) var answer = db.UserAssessmentQuestions.SingleOrDefault(o => o.UserAssessmentCategory.UserAssessment.UserDetail.UserId == userid && o.AssessmentQuestionID == ViewModel.Question.ID); if (answer != null) //User has existing response { answer.Comments = ViewModel.Question.Comment; //Update the comment /* Get all the CheckoffItems for this user's previous response. * Most items will have (checked = true) because items not checked off are removed. */ var checkoffItems = answer.UserAssessmentCheckoffItems.ToList(); foreach (var item in ViewModel.Question.Levels.SelectMany(o => o.CheckoffItems)) //For each Checkoff Item in the NEW response { if (checkoffItems.Any(x => x.AssessmentCheckoffItemID == item.ID)) //User has checked this item off in previous response { if (item.Checked) //User has checked this item off in new response. Set Checked to true { db.UserAssessmentCheckoffItems.Single(o => o.AssessmentCheckoffItemID == item.ID).Checked = true; } else //User has not checked off this response item. Remove the record. { db.UserAssessmentCheckoffItems.Remove(checkoffItems.Single(o => o.AssessmentCheckoffItemID == item.ID)); } } else if (item.Checked) //Item did not exist in old response but is checked off in new response. Create new record. { db.UserAssessmentCheckoffItems.Add(new UserAssessmentCheckoffItem { AssessmentCheckoffItemID = item.ID, UserAssessmentQuestionID = answer.ID, Checked = true }); } } } else //User has not responded to this Question before { //Get a Checkoff Item ID to determine Question var checkoffitemid = ViewModel.Question.Levels.SelectMany(y => y.CheckoffItems).First().ID; //Find Question the CheckoffItem belongs to var question = db.AssessmentQuestions.Single(o => o.AssessmentCheckoffItems.Any(x => x.ID == checkoffitemid)); answer = new UserAssessmentQuestion { AssessmentQuestionID = question.ID, Comments = ViewModel.Question.Comment }; answer.UserAssessmentCheckoffItems = new List <UserAssessmentCheckoffItem>(); foreach (var item in ViewModel.Question.Levels.SelectMany(o => o.CheckoffItems)) { if (item.Checked) //Create record if Checkoff Item is checked. Skip if not checked. { answer.UserAssessmentCheckoffItems.Add(new UserAssessmentCheckoffItem { AssessmentCheckoffItemID = item.ID, Checked = true }); } } //Check if user this is the first Question the user has responded to in the Category (or Assessment) if (!question.AssessmentCategory.UserAssessmentCategories.Any(o => o.UserAssessment.UserDetail.UserId == userid)) //First time answering a Question in this Category { var AnswerAssessment = new UserAssessment(); var AnswerCategory = new UserAssessmentCategory { UserAssessmentQuestions = new List <UserAssessmentQuestion>(), AssessmentCategoryID = ViewModel.CategoryID }; answer.UserAssessmentCategoryID = AnswerCategory.ID; AnswerCategory.UserAssessmentQuestions.Add(answer); //Check if this is first Question answered in whole Assessment by this user if (!question.AssessmentCategory.AssessmentCollection.UserAssessments.Any(o => o.UserDetail.UserId == userid)) { //First Question answered in whole assessment. AnswerAssessment.UserDetailID = db.UserDetails.Single(o => o.UserId == userid).ID; AnswerAssessment.AssessmentID = question.AssessmentCategory.AssessmentCollectionID; AnswerAssessment.UserAssessmentCategories = new List <UserAssessmentCategory>(); AnswerAssessment.UserAssessmentCategories.Add(AnswerCategory); db.UserAssessments.Add(AnswerAssessment); } else { //First question in this category, but not the assessment AnswerAssessment = db.UserAssessments.Single(o => o.UserDetail.UserId == userid && o.AssessmentCollection.AssessmentCategories.Any(x => x.ID == ViewModel.CategoryID)); AnswerAssessment.UserAssessmentCategories.Add(AnswerCategory); } } else { //Not the first question responded to in this category. answer.UserAssessmentCategoryID = question.AssessmentCategory.UserAssessmentCategories.Single(o => o.UserAssessment.UserDetail.UserId == userid).ID; db.UserAssessmentQuestions.Add(answer); } } //Calculate score. See Documentation for how Score is calculated. answer.Score = ViewModel.Question.Levels.Any(o => o.LevelOrder == 1 && o.CheckoffItems.Any(x => x.Checked)) ? 1 : ViewModel.Question.Levels.Any(o => o.LevelOrder == 2 && o.CheckoffItems.Any(x => x.Checked)) ? 2 : (ViewModel.Question.Levels.Any(o => o.LevelOrder == 3 && o.CheckoffItems.Any(x => x.Checked)) && !ViewModel.Question.Levels.Any(y => y.LevelOrder == 4 && y.CheckoffItems.Any(z => z.Checked))) ? 3 : ViewModel.Question.Levels.Any(o => o.LevelOrder == 4 && o.CheckoffItems.Any(x => x.Checked)) ? 4 : 0; db.SaveChanges(); return(GetNextQuestionId(answer.AssessmentQuestionID)); }
public ActionResult ConductAssessment(int id, ConductAssessmentViewModel ViewModel) { var nextQuestionID = assessmentServices.SaveAnswer(UserId(), ViewModel); return(RedirectToAction("ConductAssessment", new { id = ViewModel.CategoryID, qid = nextQuestionID })); }