using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor { /// <summary> /// 此类用于表示某道试题 /// </summary> public class BaseQuestion { /// <summary> /// 这是一道选择题的文本,也是最初的原型: /// 试题>>【意大利】【资本主义萌芽】产生于【14、15】世纪。 /// 答案>>意大利 /// 解析>>也可说“西欧”。 /// 错项>>中国 /// 解析>>中国资本主义萌芽产生于明朝中后期。明朝14世纪才建立。 /// 答案>>资本主义萌芽 /// 解析>> /// 错项>>文艺复兴 /// 解析>>文艺复兴的时间是14~17世纪。从语义上来说应是“开始于”而不是“产生于”。 /// 答案>>14、15 /// 解析>> /// 错项>>14~17 /// 解析>>这是文艺复兴的时间 /// 错项>>16~18 /// 解析>>这是工场手工业时期。 /// 错项>>1500年前后 /// 解析>>这是新航路开辟的时间段。 /// 〓〓〓〓〓〓 /// </summary> /// <param name="baseQuestionText">表示一个包含一对或多对括弧的题干,一组或多组答案。</param> /// <param name="multiFillBlankQuestions">表示填空题是复合填空项还是单一填空项。</param> public static List<Question> BuildQuestionList(string baseQuestionText, bool multiFillBlankQuestions = true) { List<Question> questions = new List<Question>(); #region 处理主观题 if (baseQuestionText.Contains("<<材料>>")) { int indexOfQuestion = baseQuestionText.IndexOf("<<问题>>"); if (indexOfQuestion < 0) return questions;//光材料,没有问题。以后可以考虑做成提纲。现在直接跳过。 List<string> questionPieces = new List<string>(); string[] textPieces = baseQuestionText.Split(new string[1] { "\n<<材料" }, StringSplitOptions.RemoveEmptyEntries); StringBuilder sb = null; foreach (var s in textPieces) { if (sb == null) sb = new StringBuilder(); if (s.StartsWith(">>")) { string text = sb.ToString(); if (text.Contains("答案>>")) { questionPieces.Add(text);//如果已经有了答案部分,再碰到“材料”,说明这则材料开始了新试题。 sb = null; sb = new StringBuilder(); sb.Append("\n<<材料" + s); } else { sb.Append("\n<<材料" + s); } } else { sb.Append(s.Substring(4)); } } string stText = sb.ToString(); if (string.IsNullOrEmpty(stText) == false) { questionPieces.Add(stText); } foreach (var s in questionPieces) { if (s.Contains("\n<<材料>>") == false || s.Contains("\n<<问题>>") == false || s.Contains("答案>>") == false) continue; int titleEndIndex = s.IndexOf("\n<<材料>>"); string title = string.Empty; if (titleEndIndex >= 0) title = s.Substring(0, titleEndIndex); Question newQuestion = new Question(title); string[] tts = s.Split(new string[1] { "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (var st in tts) { if (st.StartsWith("<<材料>>")) { newQuestion.Materials.Add(st.Substring(6)); } else if (st.StartsWith("<<出处>>")) { string cl = newQuestion.Materials[newQuestion.Materials.Count - 1]; cl += st; newQuestion.Materials[newQuestion.Materials.Count - 1] = cl; } else if (st.StartsWith("<<问题>>")) { newQuestion.AsksList.Add(st.Substring(6)); } else if (st.StartsWith(" 答案>>")) { newQuestion.Answers.Add(st.Substring(6)); } } questions.Add(newQuestion); } return questions; } #endregion 处理材料题 if (baseQuestionText == null || baseQuestionText.Length == 0) return questions; // baseQuestionText=baseQuestionText.replace("\n", "").replace("\r", // ""); // 不能在此处替换,否则不便找出哪些是答案文本了。 string[] titleAndAnswers = baseQuestionText.Split(new string[1] { "答案>>" }, StringSplitOptions.None); if (titleAndAnswers.Length == 1) { //填空题,不专门提供“答案>>”项 if (titleAndAnswers[0].StartsWith("试题>>")) { titleAndAnswers[0] = titleAndAnswers[0].Substring(4); } var title = titleAndAnswers[0].Trim(new char[] { ' ', ' ', '\t' }).Replace("〓", ""); if (multiFillBlankQuestions) { Question question = new Question(title, title); questions.Add(question); return questions;//填空题哪怕有多项,也只返回一个试题。这样便于课堂演示。2013年9月5日 } else { //分解每一个填空项为一道试题。且最后用混淆顺序。 List<String> questionTitlesList = BaseQuestion.BuildQuestionTitles(titleAndAnswers[0]); List<Question> fillBlankQuestions = new List<Question>(); for (int i = 0; i < questionTitlesList.Count; i++) { Question question = new Question(questionTitlesList[i], string.Empty); fillBlankQuestions.Add(question); } // 使用随机数混淆顺序。 int[] random = L.GetRandomIntArray(fillBlankQuestions.Count); foreach (int i in random) { fillBlankQuestions[i].OrderNumber = random[i]; } fillBlankQuestions.Sort(new CmparsionQuestion()); questions.AddRange(fillBlankQuestions); return questions; } } if (titleAndAnswers.Length > 1) { BaseQuestion baseQuestion = new BaseQuestion(); if (titleAndAnswers[0].StartsWith("试题>>")) { titleAndAnswers[0] = titleAndAnswers[0].Substring(4); } baseQuestion.BaseQuestionTitle = titleAndAnswers[0].Replace(" ", "").Replace("\t", "").Replace(" ", "").Replace("〓", ""); // 第一个片段是试题题干(Title),其余每段是一个“答案组”,每个“答案组”中包括一个答案、一个或多个“错项”。 // 源文本中一个选择题如果存在多个填充项,则会被拆解为多个试题。每个填充项对应一个答案及一到多个错项。 List<String> questionTitlesList = BaseQuestion.BuildQuestionTitles(titleAndAnswers[0]); if (questionTitlesList.Count == titleAndAnswers.Length - 1) { for (int i = 0; i < titleAndAnswers.Length - 1; i++) { Question question = new Question(questionTitlesList[i], titleAndAnswers[i + 1]); questions.Add(question); } return questions; } else { //不等要么是填空题,要么是主观题。判断题是一种特殊的选择题,按选择题来。 if (titleAndAnswers.Length == 1)//只有title,填空 { for (int i = 0; i < questionTitlesList.Count; i++) { Question question = new Question(questionTitlesList[i], string.Empty); questions.Add(question); } } else { //如果是主观题(有答案无填充项),则questionTitlesList的值只有一个。 //一个主观题可以有多个答案 for (int i = 0; i < questionTitlesList.Count; i++) { Question question = new Question(questionTitlesList[i], titleAndAnswers); questions.Add(question); } } } } return questions; } private string baseQuestionTitle; /// <summary> /// 试题标题(题干)文本。 /// </summary> public string BaseQuestionTitle { get { return this.baseQuestionTitle; } set { this.baseQuestionTitle = value; } } /// <summary> /// 这是真正使用的试题题干。只包括一个填充项。因为会产生多个题干,所以放在BaseQuestion类中而不是Question类中。 /// </summary> /// <param name="baseQuestionTitleString">题干文本。</param> /// <returns></returns> private static List<string> BuildQuestionTitles(string baseQuestionTitleString) { if (baseQuestionTitleString == null || baseQuestionTitleString.Length <= 0) return null; List<String> list = new List<String>(); int startBracket = -1; int endBracket = -1; startBracket = baseQuestionTitleString.IndexOf('【'); endBracket = baseQuestionTitleString.IndexOf('】'); if (startBracket < 0 || endBracket < 0) { //主观题没有填充项。 list.Add(baseQuestionTitleString.Replace("【", "").Replace("】", "")//.Replace("\r", "").Replace("\n", "") .Trim(new char[] { ' ', ' ', '\t' })); return list; } while (startBracket >= 0 && endBracket >= 0 && startBracket < endBracket) { StringBuilder sBuilder = new StringBuilder(); sBuilder.Append(baseQuestionTitleString.Substring(0, startBracket).Replace("【", "").Replace("】", "")//.Replace("\r", "").Replace("\n", "") .Trim(new char[] { ' ', ' ', '\t' })); //string fillBlankText = baseQuestionHeaderString.Substring(startBracket + 1, endBracket - startBracket - 1);//+1-1是为了去除首尾的方括弧。【】 //StringBuilder sBuilder2 = new StringBuilder(); //sBuilder2.Append("<Span Tag=\"FillBlank\">"); //sBuilder2.Append(fillBlankText); //sBuilder2.Append("</Span>"); string fillBlankText = baseQuestionTitleString.Substring(startBracket, endBracket - startBracket + 1);//+1-1是为了去除首尾的方括弧。【】 StringBuilder sBuilder2 = new StringBuilder(); sBuilder2.Append(fillBlankText); sBuilder.Append(sBuilder2.ToString()); sBuilder.Append(baseQuestionTitleString.Substring(endBracket).Replace("【", "").Replace("】", "")//.Replace("\r", "").Replace("\n", "") .Replace(" ", "").Replace("\t", "").Replace(" ", "")); list.Add(sBuilder.ToString()); startBracket = baseQuestionTitleString.IndexOf('【', endBracket); endBracket = baseQuestionTitleString.IndexOf('】', endBracket + 1); } StringBuilder stringBuilder = new StringBuilder(); foreach (string text in list) { stringBuilder.Append(text); } return list; } } }