/// <summary> /// 驗證問卷填答規則 /// </summary> /// <param name="answer">問卷填答資料</param> /// <param name="questionEntity">問卷資料</param> /// <returns>驗證結果</returns> public Dictionary <string, string> ValidateRule(QuestionnaireAnswerEntity answer, QuestionnaireEntity questionEntity) { Dictionary <string, string> validateResult = new Dictionary <string, string>(); IEnumerable <AnswerDetailEntity> answerDetailList = null; string errorMsg = null; foreach (QuestDefineEntity questDefineEntity in questionEntity.QuestDefineEntities) { errorMsg = null; answerDetailList = null; answerDetailList = answer.AnswerDetailEntities. Where(x => x.QuestionId == questDefineEntity.QuestionId); if (!ValidateNeedAnswer(questDefineEntity, answerDetailList, answer.AnswerDetailEntities)) { errorMsg = $"此題必須填答!"; } else if (!ValidateMinMultipleAnswers(questDefineEntity, answerDetailList)) { errorMsg = $"此題至少須勾選{questDefineEntity.MinMultipleAnswers}個項目!"; } else if (!ValidateMaxMultipleAnswers(questDefineEntity, answerDetailList)) { errorMsg = $"此題至多僅能勾選{questDefineEntity.MaxMultipleAnswers}個項目!"; } else if (!ValidateSingleAnswerCondition(questDefineEntity, answerDetailList, answer.AnswerDetailEntities)) { errorMsg = $"此題僅能勾選1個項目!"; } else if (!ValidateOtherAnswer(questDefineEntity, answerDetailList)) { errorMsg = $"請輸入其他說明文字!"; } if (!String.IsNullOrEmpty(errorMsg)) { validateResult.Add(questDefineEntity.QuestionId, errorMsg); } } return(validateResult); }
public void ValidateRule_When_OtherAnswer_Then_Fail() { //Arrange var answer = new QuestionnaireAnswerEntity() { AnswerDetailEntities = new List <AnswerDetailEntity>() { new AnswerDetailEntity() { QuestionId = "Q1", AnswerCode = "A", OtherAnswer = "", Score = null, }, new AnswerDetailEntity() { QuestionId = "Q2", AnswerCode = "A", OtherAnswer = "", Score = null, }, new AnswerDetailEntity() { QuestionId = "Q3", AnswerCode = "A", OtherAnswer = "", Score = null, }, new AnswerDetailEntity() { QuestionId = "Q3", AnswerCode = "E", OtherAnswer = "", Score = null, }, new AnswerDetailEntity() { QuestionId = "Q4", AnswerCode = "A", OtherAnswer = "", Score = null, }, new AnswerDetailEntity() { QuestionId = "Q5", AnswerCode = "A", OtherAnswer = "", Score = null, }, }, }; var question = new QuestionnaireEntity() { ScoreKind = "", QuestScore = null, NeedScore = "N", QuestDefineEntities = new List <QuestDefineEntity>() { new QuestDefineEntity() { Uid = Guid.Empty, QuestUid = Guid.Empty, QuestionId = "Q1", QuestionContent = "請輸入您的手機號碼(格式為0912345678,將作為活動通知使用)", NeedAnswer = "Y", AllowNaCondition = "", AnswerType = "F", MinMultipleAnswers = null, MaxMultipleAnswers = null, SingleAnswerCondition = "", CountScoreType = "", Memo = "", OrderSn = 10, CreateUserId = "", CreateTime = null, ModifyUserId = "", ModifyTime = null, AnswerDefineEntities = new List <AnswerDefineEntity>() { new AnswerDefineEntity() { AnswerCode = " ", AnswerContent = "旅遊行程(例如:來回機票、住宿券)", Memo = "", HaveOtherAnswer = "Y", NeedOtherAnswer = "Y", Score = null, OrderSn = 10, }, } }, new QuestDefineEntity() { Uid = Guid.Empty, QuestUid = Guid.Empty, QuestionId = "Q2", QuestionContent = "下列哪種活動贈品最吸引您參加活動?", NeedAnswer = "Y", AllowNaCondition = "", AnswerType = "M", MinMultipleAnswers = 1, MaxMultipleAnswers = null, SingleAnswerCondition = "", CountScoreType = "", Memo = "", OrderSn = 20, CreateUserId = "", CreateTime = null, ModifyUserId = "", ModifyTime = null, AnswerDefineEntities = new List <AnswerDefineEntity>() { new AnswerDefineEntity() { AnswerCode = "A", AnswerContent = "3C產品(例如:手機、平板電腦、相機)", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 10, }, new AnswerDefineEntity() { AnswerCode = "B", AnswerContent = "禮券(例如:知名百貨、量販店、便利商店禮券)", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 20, }, new AnswerDefineEntity() { AnswerCode = "C", AnswerContent = "簡訊", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 30, } } }, new QuestDefineEntity() { Uid = Guid.Empty, QuestUid = Guid.Empty, QuestionId = "Q3", QuestionContent = "您最喜歡透過下列何種方式收到行銷優惠資訊?", NeedAnswer = "Y", AllowNaCondition = "", AnswerType = "M", MinMultipleAnswers = 1, MaxMultipleAnswers = null, SingleAnswerCondition = "", CountScoreType = "", Memo = "", OrderSn = 30, CreateUserId = "", CreateTime = null, ModifyUserId = "", ModifyTime = null, AnswerDefineEntities = new List <AnswerDefineEntity>() { new AnswerDefineEntity() { AnswerCode = "A", AnswerContent = "電子DM", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 10, }, new AnswerDefineEntity() { AnswerCode = "B", AnswerContent = "實體DM", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 20, }, new AnswerDefineEntity() { AnswerCode = "C", AnswerContent = "即時通訊軟體(例如:LINE、what’s app)", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 30, }, new AnswerDefineEntity() { AnswerCode = "D", AnswerContent = "其他", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 40, }, new AnswerDefineEntity() { AnswerCode = "E", AnswerContent = "臨櫃", Memo = "", HaveOtherAnswer = "Y", NeedOtherAnswer = "Y", Score = null, OrderSn = 50, }, } }, new QuestDefineEntity() { Uid = Guid.Empty, QuestUid = Guid.Empty, QuestionId = "Q4", QuestionContent = "下列哪一項通路服務是您最常使用的?(一個月至少使用3次以上)", NeedAnswer = "Y", AllowNaCondition = "", AnswerType = "S", MinMultipleAnswers = null, MaxMultipleAnswers = null, SingleAnswerCondition = "", CountScoreType = "", Memo = "", OrderSn = 40, CreateUserId = "", CreateTime = null, ModifyUserId = "", ModifyTime = null, AnswerDefineEntities = new List <AnswerDefineEntity>() { new AnswerDefineEntity() { AnswerCode = "A", AnswerContent = "ATM", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 10, }, new AnswerDefineEntity() { AnswerCode = "B", AnswerContent = "網站", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 20, }, new AnswerDefineEntity() { AnswerCode = "C", AnswerContent = "行動APP", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 30, }, new AnswerDefineEntity() { AnswerCode = "D", AnswerContent = "都沒有", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 40, }, new AnswerDefineEntity() { AnswerCode = "E", AnswerContent = "1分", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 50, }, } }, new QuestDefineEntity() { Uid = Guid.Empty, QuestUid = Guid.Empty, QuestionId = "Q5", QuestionContent = "您對我們的服務滿意度1至5分是?", NeedAnswer = "Y", AllowNaCondition = "{\"Conditions\":[{\"QuestionId\": \"Q4\", \"AnswerCode\": [\"E\"]}]}", AnswerType = "S", MinMultipleAnswers = null, MaxMultipleAnswers = null, SingleAnswerCondition = "", CountScoreType = "", Memo = "", OrderSn = 50, CreateUserId = "", CreateTime = null, ModifyUserId = "", ModifyTime = null, AnswerDefineEntities = new List <AnswerDefineEntity>() { new AnswerDefineEntity() { AnswerCode = "A", AnswerContent = "2分", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 10, }, new AnswerDefineEntity() { AnswerCode = "B", AnswerContent = "3分", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 20, }, new AnswerDefineEntity() { AnswerCode = "C", AnswerContent = "4分", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 30, }, new AnswerDefineEntity() { AnswerCode = "D", AnswerContent = "5分", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 40, }, new AnswerDefineEntity() { AnswerCode = "E", AnswerContent = "", Memo = "", HaveOtherAnswer = "N", NeedOtherAnswer = "N", Score = null, OrderSn = 50, }, } }, new QuestDefineEntity() { Uid = Guid.Parse("F9DD6938-2DBD-48AF-9D44-428DCB2AC5D6"), QuestionId = "Q001", CountScoreType = "2", NeedAnswer = "N", AnswerType = "S", MinMultipleAnswers = null, MaxMultipleAnswers = null, SingleAnswerCondition = "", AllowNaCondition = "", AnswerDefineEntities = new List <AnswerDefineEntity>() { new AnswerDefineEntity() { AnswerCode = "1", Score = 1, }, new AnswerDefineEntity() { AnswerCode = "2", Score = 2, }, new AnswerDefineEntity() { AnswerCode = "3", Score = 3, }, new AnswerDefineEntity() { AnswerCode = "4", Score = 4, }, new AnswerDefineEntity() { AnswerCode = "5", Score = 5, }, } }, } }; Dictionary <string, string> expected = new Dictionary <string, string>() { { "Q3", "請輸入其他說明文字!" }, }; //Actual Dictionary <string, string> actual = new QuestionnaireService().ValidateRule(answer, question); //Assert CollectionAssert.AreEqual(expected, actual); }
/// <summary> /// 計算問卷得分,回傳問卷得分類別 /// </summary> /// <param name="answer">問卷填答資料</param> /// <param name="questionEntity">問卷定義資料</param> /// <returns>問卷得分類別</returns> public CalculateScoreEntity CalculateScore(QuestionnaireAnswerEntity answer, QuestionnaireEntity questionEntity) { List <AnswerDetailEntity> answerFullDetailList = new List <AnswerDetailEntity>(); int actualScore = 0; List <int> questionScoreList = new List <int>(); IEnumerable <AnswerDetailEntity> answerDetailList = null; AnswerDetailEntity answerDetail = null; AnswerDefineEntity answerDefine = null; IEnumerable <int> answerScoreList = null; foreach (QuestDefineEntity questDefine in questionEntity.QuestDefineEntities) { answerDetailList = null; answerDetail = null; answerDefine = null; answerScoreList = null; answerDetailList = answer.AnswerDetailEntities. Where(x => (x.QuestionId == questDefine.QuestionId) && !String.IsNullOrEmpty(x.AnswerCode)); if (questDefine.AnswerType == "S") { if (answerDetailList.Count() == 0) { continue; } else if (answerDetailList.Count() > 1) { var ex = new InvalidOperationException("answerCode not the only"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; ex.Data["answerCodeList"] = String.Join(",", answerDetailList); throw ex; } answerDetail = answerDetailList.First(); answerDefine = questDefine.AnswerDefineEntities. FirstOrDefault(x => x.AnswerCode == answerDetail.AnswerCode); if (answerDefine == null) { var ex = new InvalidOperationException("answerDefine not found"); ex.Data["answerDetail.AnswerCode"] = answerDetail.AnswerCode; throw ex; } answerFullDetailList.Add(new AnswerDetailEntity { QuestionUid = questDefine.Uid, Score = answerDefine.Score, QuestionId = answerDetail.QuestionId, AnswerCode = answerDetail.AnswerCode, OtherAnswer = answerDetail.OtherAnswer, }); } else if (questDefine.AnswerType == "M") { foreach (AnswerDetailEntity answerDetailEntity in answerDetailList) { answerDefine = null; answerDefine = questDefine.AnswerDefineEntities. FirstOrDefault(x => x.AnswerCode == answerDetailEntity.AnswerCode); if (answerDefine == null) { var ex = new InvalidOperationException("answerDefine not found"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; ex.Data["answerDetailEntity.AnswerCode"] = answerDetailEntity.AnswerCode; throw ex; } answerFullDetailList.Add(new AnswerDetailEntity { QuestionUid = questDefine.Uid, Score = answerDefine.Score, QuestionId = answerDetailEntity.QuestionId, AnswerCode = answerDetailEntity.AnswerCode, OtherAnswer = answerDetailEntity.OtherAnswer, }); } } else if (questDefine.AnswerType == "F") { if (answerDetailList.Count() == 0) { var ex = new InvalidOperationException("answerCode not the only"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; throw ex; } else if (answerDetailList.Count() != 1) { var ex = new InvalidOperationException("answerCode not the only"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; ex.Data["answerCodeList"] = String.Join(",", answerDetailList); throw ex; } answerDetail = answerDetailList.First(); IEnumerable <AnswerDefineEntity> answerDefineList = questDefine.AnswerDefineEntities. Where(x => x.AnswerCode == String.Empty); if (answerDefineList.Count() == 0) { var ex = new InvalidOperationException("answerDefineList not found"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; throw ex; } else if (answerDefineList.Count() != 1) { var ex = new InvalidOperationException("answerDefineList not the only"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; throw ex; } answerDefine = answerDefineList.First(); answerFullDetailList.Add(new AnswerDetailEntity { QuestionUid = questDefine.Uid, Score = answerDefine.Score, QuestionId = answerDetail.QuestionId, AnswerCode = null, OtherAnswer = answerDetail.AnswerCode, }); } if (questionEntity.NeedScore == "Y") { answerScoreList = answerFullDetailList. Where(x => (x.QuestionId == questDefine.QuestionId) && (x.Score != null)). Select(x => x.Score.Value); if ((answerScoreList == null) || (answerScoreList.Count() == 0)) { var ex = new InvalidOperationException("answerScoreList not found"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; throw ex; } switch (questDefine.CountScoreType) { case "1": questionScoreList.Add(answerScoreList.Sum()); break; case "2": questionScoreList.Add(answerScoreList.Max()); break; case "3": questionScoreList.Add(answerScoreList.Min()); break; case "4": questionScoreList.Add(Convert.ToInt32(Math. Round(answerScoreList.Average(), 0, MidpointRounding.AwayFromZero))); break; default: var ex = new InvalidOperationException("countScoreType not found"); ex.Data["questDefine.QuestionId"] = questDefine.QuestionId; ex.Data["questDefine.CountScoreType"] = questDefine.CountScoreType; throw ex; } } } if (questionEntity.NeedScore == "Y") { if (questionEntity.ScoreKind == "1") { actualScore = questionScoreList.Sum(); } if ((questionEntity.QuestScore != null) && (actualScore > questionEntity.QuestScore.Value)) { actualScore = questionEntity.QuestScore.Value; } } return(new CalculateScoreEntity() { ActualScore = actualScore, FullAnswerDetailList = answerFullDetailList, }); }
/// <summary> /// 計算問卷填答得分 /// </summary> /// <param name="answer">問卷填答資料</param> /// <returns>問卷填答評分結果</returns> public QuestionnaireResultEntity Calculate(QuestionnaireAnswerEntity answer) { QuestionnaireResultEntity questionResultEntity = null; QuestionnaireAnswerDO questionAnswerDO = null; if (answer == null) { throw new ArgumentNullException("沒有提供問卷填答資料"); } QuestionnaireEntity questionEntity = GetQuestionnaire(answer.QuestUid); DateTime currentTime = DateTime.Now; if ((questionEntity == null) || (questionEntity.Ondate >= currentTime) || (questionEntity.Offdate != null) && (questionEntity.Offdate <= currentTime)) { var ex = new InvalidOperationException("問卷資料不存在或沒有有效的問卷資料"); ex.Data["QuestionUis"] = answer.QuestUid; throw ex; } Dictionary <string, string> validateResult = ValidateRule(answer, questionEntity); if (validateResult == null) { throw new InvalidOperationException("validateResult not found"); } Dictionary <string, string> riskResult = null; string dialogMsg = null; if (validateResult.Count == 0) { CalculateScoreEntity calculateResult = CalculateScore(answer, questionEntity); if (calculateResult == null) { throw new InvalidOperationException("calculateResult not found"); } riskResult = calculateResult.FullAnswerDetailList. Where(x => !String.IsNullOrEmpty(x.AnswerCode)). GroupBy(x => x.QuestionId). Select(group => new { group.Key, Value = String.Join(",", group.Select(item => item.AnswerCode)) }).ToDictionary(x => x.Key, x => x.Value); if (riskResult == null) { throw new InvalidOperationException("riskResult not found"); } questionAnswerDO = SaveQuestionAnswer(questionEntity, calculateResult, answer.UserId); if (questionAnswerDO == null) { throw new InvalidOperationException("questionAnswerDO not found"); } if (questionEntity.NeedScore != "Y") { dialogMsg = "您的問卷己填答完畢,謝謝您的參與"; } } questionResultEntity = new QuestionnaireResultEntity() { QuestionnaireEntity = questionEntity, AnswerDetailEntities = answer.AnswerDetailEntities, ValidateFailInfo = validateResult, RiskResult = riskResult, QuestionnaireMessage = dialogMsg, }; if (questionAnswerDO != null) { questionResultEntity.Uid = questionAnswerDO.Uid; questionResultEntity.QuestUid = questionAnswerDO.QuestUid; questionResultEntity.QuestAnswerId = questionAnswerDO.QuestAnswerId; questionResultEntity.TesteeId = questionAnswerDO.TesteeId; questionResultEntity.QuestScore = questionAnswerDO.QuestScore; questionResultEntity.ActualScore = questionAnswerDO.ActualScore; questionResultEntity.TesteeSource = questionAnswerDO.TesteeSource; questionResultEntity.CreateUserId = questionAnswerDO.CreateUserId; questionResultEntity.CreateTime = questionAnswerDO.CreateTime; questionResultEntity.ModifyUserId = questionAnswerDO.ModifyUserId; questionResultEntity.ModifyTime = questionAnswerDO.ModifyTime; } return(questionResultEntity); }