HTML2ITEMV3Translator.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. using HTEXLib.COMM.Helpers;
  2. using HTEXLib.DOCX.Models;
  3. using HTEXLib.Helpers.ShapeHelpers;
  4. using HtmlAgilityPack;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Text.Json;
  11. using System.Text.RegularExpressions;
  12. using System.Threading.Tasks;
  13. namespace HTEXLib.Translator
  14. {
  15. public class HTML2ITEMV3Translator
  16. {
  17. /// <summary>
  18. /// 全角
  19. /// </summary>
  20. string[] aza = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
  21. /// <summary>
  22. /// 半角
  23. /// </summary>
  24. string[] azh = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
  25. public const string Answer = "Answer";
  26. public const string Analysis = "Analysis";
  27. public const string Ended = "Ended";
  28. public const string Point = "Point";
  29. public const string Score = "Score";
  30. public const string Summary = "Summary";
  31. public const string Filed = "Filed";
  32. public const string Level = "Level";
  33. public const string Count = "Count";
  34. public const string Taxonomy = "Taxonomy";
  35. // public LangConfig langConfig { get; set; }
  36. // public HtmlDocument doc { get; set; } = new HtmlDocument();
  37. public List<List<string>> optionsKeys { get; set; } = new List<List<string>>();
  38. public Dictionary<string, string[]> dict { get; set; }
  39. // public string[] Fileds { get; set; }
  40. public TagConfig? _TagConfig { get; set; }
  41. public HTML2ITEMV3Translator(string configPath)
  42. {
  43. FileStream fs = new FileStream(configPath+ "/LangConfigV3.json", System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  44. StreamReader sr = new StreamReader(fs, System.Text.Encoding.UTF8);
  45. string line;
  46. StringBuilder builder = new StringBuilder();
  47. while ((line = sr.ReadLine()) != null)
  48. {
  49. builder.Append(line.ToString());
  50. }
  51. sr.Close();
  52. string text = builder.ToString();
  53. _TagConfig=JsonSerializer.Deserialize<TagConfig>(text);
  54. //_TagConfig = text.FromJson<TagConfig>();
  55. dict = new Dictionary<string, string[]>();
  56. foreach (var _langConfig in _TagConfig.LangConfig)
  57. {
  58. string[] Fileds = _langConfig.Item.Filed.Split('|');
  59. foreach (var filed in Fileds)
  60. {
  61. dict[filed] = new string[] { _langConfig.Lang, Filed, $"{Array.IndexOf(Fileds, filed)}" };
  62. }
  63. string[] Judges = _langConfig.Item.Judge.Split('|');
  64. foreach (var Judge in Judges)
  65. {
  66. dict[Judge] = new string[] { _langConfig.Lang, Judge, $"{Array.IndexOf(Judges, Judge)}" };
  67. }
  68. dict[_langConfig.Item.Answer] = new string[] { _langConfig.Lang, Answer };
  69. dict[_langConfig.Item.Analysis] = new string[] { _langConfig.Lang, Analysis };
  70. dict[_langConfig.Item.Taxonomy] = new string[] { _langConfig.Lang, Taxonomy };
  71. dict[_langConfig.Item.Ended] = new string[] { _langConfig.Lang, Ended };
  72. dict[_langConfig.Item.Point] = new string[] { _langConfig.Lang, Point };
  73. dict[_langConfig.Item.Score] = new string[] { _langConfig.Lang, Score };
  74. dict[_langConfig.Item.Level] = new string[] { _langConfig.Lang, Level };
  75. dict[_langConfig.Item.Count] = new string[] { _langConfig.Lang, Count };
  76. foreach (string key in _langConfig.Item.Type.Keys)
  77. {
  78. dict[_langConfig.Item.Type[key]] = new string[] { _langConfig.Lang, Summary, key };
  79. }
  80. }
  81. string [] ops= _TagConfig.Options.Split('-');
  82. foreach (string op in ops)
  83. {
  84. if (!string.IsNullOrWhiteSpace(op))
  85. {
  86. var data = op.Select(z => z.ToString()).ToList();
  87. optionsKeys.Add(data);
  88. }
  89. }
  90. // optionsKeys = .Select(s => s.ToString()).ToArray();
  91. }
  92. /// <summary>
  93. /// 处理标签中以及题型标签中包含的空格字符
  94. /// </summary>
  95. /// <param name="html"></param>
  96. /// <returns></returns>
  97. public string BlankProcess(string html)
  98. {
  99. foreach (var _langConfig in _TagConfig.LangConfig) {
  100. string ans = _TagConfig.Start + _langConfig.Item.Answer + _TagConfig.End;
  101. string als = _TagConfig.Start + _langConfig.Item.Analysis + _TagConfig.End;
  102. string tax = _TagConfig.Start + _langConfig.Item.Taxonomy + _TagConfig.End;
  103. string end = _TagConfig.Start + _langConfig.Item.Ended + _TagConfig.End;
  104. string pot = _TagConfig.Start + _langConfig.Item.Point + _TagConfig.End;
  105. string scr = _TagConfig.Start + _langConfig.Item.Score + _TagConfig.End;
  106. string lvl = _TagConfig.Start + _langConfig.Item.Level + _TagConfig.End;
  107. string cut = _TagConfig.Start + _langConfig.Item.Count + _TagConfig.End;
  108. string[] Fileds = _langConfig.Item.Filed.Split('|');
  109. foreach (var filed in Fileds)
  110. {
  111. var fld = _TagConfig.Start + filed + _TagConfig.End;
  112. string[] fldarry = fld.Select(s => s.ToString()).ToArray();
  113. string fldReg = string.Join("\\s*", fldarry);
  114. html = Regex.Replace(html, fldReg, fld);
  115. }
  116. string[] ansarry = ans.Select(s => s.ToString()).ToArray();
  117. string[] alsarry = als.Select(s => s.ToString()).ToArray();
  118. string[] taxarry = tax.Select(s => s.ToString()).ToArray();
  119. string[] endarry = end.Select(s => s.ToString()).ToArray();
  120. string[] potarry = pot.Select(s => s.ToString()).ToArray();
  121. string[] scrarry = scr.Select(s => s.ToString()).ToArray();
  122. string[] lvlarry = lvl.Select(s => s.ToString()).ToArray();
  123. string[] cutarry = cut.Select(s => s.ToString()).ToArray();
  124. string ansReg = string.Join("\\s*", ansarry);
  125. string alsReg = string.Join("\\s*", alsarry);
  126. string taxReg = string.Join("\\s*", taxarry);
  127. string endReg = string.Join("\\s*", endarry);
  128. string potReg = string.Join("\\s*", potarry);
  129. string scrReg = string.Join("\\s*", scrarry);
  130. string lvlReg = string.Join("\\s*", lvlarry);
  131. string cutReg = string.Join("\\s*", cutarry);
  132. html = Regex.Replace(html, ansReg, ans);
  133. html = Regex.Replace(html, alsReg, als);
  134. html = Regex.Replace(html, taxReg, tax);
  135. html = Regex.Replace(html, endReg, end);
  136. html = Regex.Replace(html, potReg, pot);
  137. html = Regex.Replace(html, scrReg, scr);
  138. html = Regex.Replace(html, lvlReg, lvl);
  139. html = Regex.Replace(html, cutReg, cut);
  140. string blankReg = "\\s*";
  141. foreach (string value in _langConfig.Item.Type.Values)
  142. {
  143. string tag = $"{_TagConfig.Start}\\s*\\d+\\s*{string.Join("\\s*", value.Select(s => s.ToString()).ToArray())}\\s*{_TagConfig.End}";
  144. var m = Regex.Match(html, tag);
  145. while (m.Success)
  146. {
  147. string blankStr = Regex.Replace(m.Value, blankReg, "");
  148. html = html.Replace(m.Value, blankStr);
  149. m = m.NextMatch();
  150. }
  151. }
  152. }
  153. return html;
  154. }
  155. public (List<DOCX.Models.ItemInfo> tests, List<string> error) Translate(string html )
  156. {
  157. List<string> emferror = new List<string>();
  158. string mathjax = "<script type=\"text/javascript\" src=\"http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML\"></script>";
  159. html = html.Replace(mathjax, "");
  160. //去除class 以及span标签"
  161. string classpattern = "class=\"([^\"]*)\"";
  162. html = Regex.Replace(html, classpattern, "");
  163. string pattern = "<span([^>]{0,})>";
  164. html = Regex.Replace(html, pattern, "");
  165. string apattern = "<a([^>]{0,})></a>";
  166. html = Regex.Replace(html, apattern, "");
  167. //<a id="OP2_89937270DA164EFF8650A3FB645B678A" ></a>B<a id="OPTG2_89937270DA164EFF8650A3FB645B678A" ></a>
  168. html = html.Replace(" close=\"\" separators=\" | \">", "");
  169. html = html.Replace("\t", " ").Replace("<span>", "").Replace("</span>", "").Replace("dir=\"ltr\"", "");
  170. HtmlDocument doc = new HtmlDocument();
  171. doc.LoadHtml(html);
  172. //处理 标签中包含的空格字符
  173. html = BlankProcess(html);
  174. var array = Regex.Split(html, "{([\\S]*?)}");
  175. List<KeyValuePair<int[], List<string>>> composeKeys = new List<KeyValuePair<int[], List<string>>>();
  176. //List<string>
  177. //处理综合题
  178. for (int index = 1; index < array.Length; index++)
  179. {
  180. var tagValue = BlankTag(array[index]);
  181. tagValue = Regex.Replace(tagValue, @"\d", "");
  182. if (dict.TryGetValue(tagValue, out string[] keyInfo))
  183. {
  184. if (keyInfo[1] == Summary && keyInfo[2].Equals("compose"))
  185. {
  186. var curr = index;
  187. List<string> comsArray = new List<string>() ;
  188. bool hasEndFlage = false;
  189. int allIndex=0;
  190. for (int composeIndex = index + 1; composeIndex < array.Length; composeIndex++) {
  191. var conIndex = BlankTag(array[composeIndex]);
  192. conIndex = Regex.Replace(conIndex, @"\d", "");
  193. var langStr = keyInfo[0];
  194. var langfig= _TagConfig.LangConfig.Where(x => x.Lang == langStr).FirstOrDefault();
  195. allIndex = composeIndex;
  196. //当没有综合题结束时,又遇到新的综合题
  197. bool isNewCompose = false;
  198. if (dict.TryGetValue(conIndex, out string[] newTagKeyInfo)) {
  199. if (newTagKeyInfo[1] == Summary && newTagKeyInfo[2].Equals("compose")) {
  200. isNewCompose = true;
  201. }
  202. }
  203. if (conIndex.Equals(langfig.Item.Ended) || conIndex.Equals(tagValue + langfig.Item.Ended) )
  204. {
  205. comsArray.AddRange(array.ToList().GetRange(index + 1, composeIndex - index - 1));
  206. index = composeIndex + 1;
  207. hasEndFlage = true;
  208. break;
  209. }
  210. if ( isNewCompose)
  211. {
  212. comsArray.AddRange(array.ToList().GetRange(index + 1, composeIndex - index - 1));
  213. index = composeIndex-1;
  214. hasEndFlage = true;
  215. break;
  216. }
  217. }
  218. //当没有综合题结束时,并且没有遇到新的综合题
  219. if (hasEndFlage == false && allIndex>0) {
  220. comsArray.AddRange(array.ToList().GetRange(index + 1, allIndex - index ));
  221. index = allIndex+1;
  222. }
  223. //int[0]综合题开始标签位置,int[1]综合题结束标签位置,int[2]综合题第一个小题的开始标签位置
  224. KeyValuePair<int[], List<string>> coms = new KeyValuePair<int[], List<string>>(new int[] { curr, index }, comsArray);
  225. composeKeys.Add(coms);
  226. }
  227. }
  228. }
  229. List<KeyValuePair<int[], List<ItemInfo>>> composeList = new List<KeyValuePair<int[], List<ItemInfo>>>();
  230. foreach(var conskey in composeKeys) {
  231. (List<DOCX.Models.ItemInfo> consInner, List<string> eferror)= ConvertTest(conskey.Value.ToArray(), null);
  232. if (eferror.IsNotEmpty())
  233. {
  234. emferror.AddRange(eferror);
  235. }
  236. int stIndex = conskey.Key[0]+1;
  237. if (consInner.IsNotEmpty())
  238. {
  239. stIndex = consInner[0].order<=0? conskey.Key[0]+consInner[0].order:stIndex;
  240. }
  241. KeyValuePair<int[], List<ItemInfo>> innerComposeItem = new KeyValuePair<int[], List<ItemInfo>>(new int[] { conskey.Key[0], conskey.Key[1], stIndex }, consInner);
  242. composeList.Add(innerComposeItem);
  243. }
  244. (List < DOCX.Models.ItemInfo > tests,List<string> error) = ConvertTest(array, composeList);
  245. if (error.IsNotEmpty()) {
  246. emferror.AddRange(error);
  247. }
  248. return (tests, emferror);
  249. }
  250. private string BlankTag(string tagHtml) {
  251. //去掉标签中的Html
  252. HtmlDocument doc = new HtmlDocument();
  253. doc.LoadHtml(tagHtml);
  254. var tagValue = doc.DocumentNode.InnerText.Replace("{", "").Replace("}", "")
  255. .Replace("\n", "").Replace(" ", "").Replace("\t", "").Replace("\r", "")
  256. .Replace("&nbsp;", "").Replace("&emsp;", "").Replace("&emsp;", "");
  257. // tagValue = Regex.Replace(tagValue, @"\d", "");
  258. tagValue = Regex.Replace(tagValue, @"\s", "");
  259. return tagValue;
  260. }
  261. private string BlankPointTag(string tagHtml)
  262. {
  263. //去掉标签中的Html
  264. HtmlDocument doc = new HtmlDocument();
  265. doc.LoadHtml(tagHtml);
  266. var tagValue = doc.DocumentNode.InnerText.Replace("{", "").Replace("}", "")
  267. .Replace("\n", " ").Replace("\t", " ").Replace("\r", " ")
  268. .Replace("&nbsp;", " ").Replace("&emsp;", " ").Replace("&emsp;", " ");
  269. // tagValue = Regex.Replace(tagValue, @"\d", "");
  270. tagValue = Regex.Replace(tagValue, @"\s", " ");
  271. return tagValue;
  272. }
  273. public (List<DOCX.Models.ItemInfo> ItemInfo, List<string> error) ConvertTest(string[] array, List<KeyValuePair<int[], List<ItemInfo>>> composeList) {
  274. List<DOCX.Models.ItemInfo> tests = new List<DOCX.Models.ItemInfo>();
  275. List<string> error = new List<string>();
  276. //内容零时变量,追加完成后重新实例化 new StringBuilder()
  277. StringBuilder content = new StringBuilder();
  278. //告知遇到新标签,内容需要重新初始化实例
  279. DOCX.Models.ItemInfo test=null;
  280. string openTag = "";
  281. string openTagVal = "";
  282. bool openFlag = false;
  283. string openTagLang = "";
  284. if (array[0].Contains("EmfBase64ConvertError"))
  285. {
  286. error.Add(array[0]);
  287. }
  288. for (int index = 1; index < array.Length; index++) {
  289. if (index % 2 == 1)
  290. {
  291. //去掉标签中的{} 空格换行制表符及Html空格数字等
  292. var tagValue = BlankTag(array[index]);
  293. tagValue = Regex.Replace(tagValue, @"\d", "");
  294. Console.WriteLine(index);
  295. if (index==157) {
  296. Console.WriteLine(index);
  297. }
  298. if (dict.TryGetValue(tagValue, out string[] keyInfo))
  299. {
  300. switch ( keyInfo[1] ) {
  301. case Summary:
  302. if (!string.IsNullOrEmpty(openTag) && openFlag && test != null)
  303. {
  304. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  305. content = new StringBuilder();
  306. }
  307. if (test != null)
  308. {
  309. tests.Add(test);
  310. }
  311. //下列代码不能调整顺序
  312. if (keyInfo[2].Equals("compose"))
  313. {
  314. var id = System.Guid.NewGuid().ToString();
  315. var compose = new ItemInfo { type = keyInfo[2],objective=false,order=index,id=id };
  316. if (composeList.IsNotEmpty())
  317. {
  318. var childItem = composeList.Where(x => x.Key[0] == index).FirstOrDefault();
  319. childItem.Value.ForEach(x => x.pid = id);
  320. compose.children = childItem.Value;
  321. var ques= array.ToList().GetRange(childItem.Key[0]+1, childItem.Key[2]- childItem.Key[0]);
  322. compose.question= string.Join("", ques);
  323. index = childItem.Key[1] - 1;
  324. }
  325. tests.Add(compose);
  326. openTag = "";
  327. openTagVal = "";
  328. openFlag = false;
  329. openTagLang = keyInfo[0];
  330. test = null;
  331. }
  332. else {
  333. var id = System.Guid.NewGuid().ToString();
  334. test = new ItemInfo() { type = keyInfo[2], order = index, id = id };
  335. if (keyInfo[2].Equals("single") || keyInfo[2].Equals("multiple") || keyInfo[2].Equals("judge")||keyInfo[2].Equals("sortmultiple"))
  336. {
  337. test.objective = true;
  338. }
  339. else
  340. {
  341. test.objective = false;
  342. }
  343. //处理填空题默认填空数量为1
  344. if (keyInfo[2].Equals("complete"))
  345. {
  346. test.blankCount = 1;
  347. }
  348. //不是填空题 的填空数量为0
  349. else {
  350. test.blankCount = 0;
  351. }
  352. openTag = Summary;
  353. openTagVal = tagValue;
  354. openFlag = true;
  355. openTagLang = keyInfo[0];
  356. }
  357. break;
  358. case Answer:
  359. //下列代码不能调整顺序
  360. if (!string.IsNullOrEmpty(openTag) && openFlag)
  361. {
  362. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  363. content = new StringBuilder();
  364. }
  365. openTag = Answer;
  366. openTagVal = tagValue;
  367. openFlag = true;
  368. openTagLang = keyInfo[0];
  369. break;
  370. case Analysis:
  371. //下列代码不能调整顺序
  372. if (!string.IsNullOrEmpty(openTag) && openFlag)
  373. {
  374. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  375. content = new StringBuilder();
  376. }
  377. openTag = Analysis;
  378. openTagVal = tagValue;
  379. openFlag = true;
  380. openTagLang = keyInfo[0];
  381. break;
  382. case Taxonomy:
  383. //下列代码不能调整顺序
  384. if (!string.IsNullOrEmpty(openTag) && openFlag)
  385. {
  386. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  387. content = new StringBuilder();
  388. }
  389. openTag = Taxonomy;
  390. openTagVal = tagValue;
  391. openFlag = true;
  392. openTagLang = keyInfo[0];
  393. break;
  394. case Ended:
  395. break;
  396. case Point:
  397. //下列代码不能调整顺序
  398. if (!string.IsNullOrEmpty(openTag) && openFlag)
  399. {
  400. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  401. content = new StringBuilder();
  402. }
  403. openTag = Point;
  404. openTagVal = tagValue;
  405. openFlag = true;
  406. openTagLang = keyInfo[0];
  407. break;
  408. case Score:
  409. //下列代码不能调整顺序
  410. if (!string.IsNullOrEmpty(openTag) && openFlag)
  411. {
  412. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  413. content = new StringBuilder();
  414. }
  415. openTag = Score;
  416. openTagVal = tagValue;
  417. openFlag = true;
  418. openTagLang = keyInfo[0];
  419. break;
  420. case Level:
  421. //下列代码不能调整顺序
  422. if (!string.IsNullOrEmpty(openTag) && openFlag)
  423. {
  424. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  425. content = new StringBuilder();
  426. }
  427. openTag = Level;
  428. openTagVal = tagValue;
  429. openFlag = true;
  430. openTagLang = keyInfo[0];
  431. break;
  432. case Filed:
  433. //下列代码不能调整顺序
  434. if (!string.IsNullOrEmpty(openTag) && openFlag)
  435. {
  436. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  437. content = new StringBuilder();
  438. }
  439. openTag = Filed;
  440. openTagVal = tagValue;
  441. openFlag = true;
  442. openTagLang = keyInfo[0];
  443. break;
  444. case Count:
  445. //下列代码不能调整顺序
  446. if (!string.IsNullOrEmpty(openTag) && openFlag)
  447. {
  448. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  449. content = new StringBuilder();
  450. }
  451. openTag = Count;
  452. openTagVal = tagValue;
  453. openFlag = true;
  454. openTagLang = keyInfo[0];
  455. break;
  456. }
  457. }
  458. //如果不是标签内的则累加到内容上
  459. else {
  460. content.Append(array[index]);
  461. if (array[index].Contains("EmfBase64ConvertError"))
  462. {
  463. error.Add(array[index]);
  464. }
  465. }
  466. }
  467. else {
  468. //偶数序列为内容
  469. content.Append(array[index]);
  470. if (array[index].Contains("EmfBase64ConvertError"))
  471. {
  472. error.Add(array[index]);
  473. }
  474. }
  475. }
  476. if (test != null)
  477. {
  478. DoOpenTag(openTag, openTagVal, openFlag, openTagLang, content, test);
  479. tests.Add(test);
  480. }
  481. return (tests,error);
  482. }
  483. public (List<CodeValue> options,string question) OptionProcess(string question) {
  484. for (int idx = 0; idx < 26; idx++)
  485. {
  486. question = question.Replace(aza[idx], azh[idx]);
  487. }
  488. List<CodeValue> options = new List<CodeValue>();
  489. int index = 0;
  490. string optsRgex = optionsKeys[0][0] + "\\s*(\\.|\\.|\\、|\\:|\\:)([\\s\\S]*?).*";
  491. string optsHtml = Regex.Match(question, optsRgex).Value;
  492. if (string.IsNullOrWhiteSpace(optsHtml) && optionsKeys.Count>1) {
  493. optsRgex = optionsKeys[1][0] + "\\s*(\\.|\\.|\\、|\\:|\\:)([\\s\\S]*?).*";
  494. index=1;
  495. optsHtml = Regex.Match(question, optsRgex).Value;
  496. }
  497. // StringBuilder textImg = new StringBuilder();
  498. for (int i = 0; i < optionsKeys[index].Count - 1; i++)
  499. {
  500. string optRgex = optionsKeys[index][i] + "\\s*(\\.|\\.|\\、|\\:|\\:)([\\s\\S]*?)" + optionsKeys[index][i + 1] + "\\s*(\\.|\\.|\\、|\\:|\\:)";
  501. string optHtml = Regex.Match(optsHtml, optRgex).Value;
  502. if (string.IsNullOrWhiteSpace(optHtml)) {
  503. optRgex = optionsKeys[index][i] + "\\s*(\\.|\\.|\\、|\\:|\\:).*";
  504. optHtml = Regex.Match(optsHtml, optRgex).Value;
  505. }
  506. if (!string.IsNullOrEmpty(optHtml))
  507. {
  508. optHtml = Regex.Replace(optHtml, optionsKeys[index][i + 1] + "\\s*(\\.|\\.|\\、|\\:|\\:)", "");
  509. optHtml = optHtml.Substring(2, optHtml.Length - 2);
  510. optHtml = HtmlHelper.DoUselessTag(optHtml);
  511. optHtml = optHtml.TrimStart().TrimEnd();
  512. // textImg.Append(HtmlHelper.DoTextImg(optHtml));
  513. if (index==1)
  514. {
  515. var code = optionsKeys[0][int.Parse(optionsKeys[index][i])-1];
  516. options.Add(new CodeValue { code = code, value = optHtml });
  517. }
  518. else {
  519. options.Add(new CodeValue { code = optionsKeys[index][i], value = optHtml });
  520. }
  521. }
  522. }
  523. if (!string.IsNullOrWhiteSpace(optsHtml))
  524. {
  525. return (options, question.Replace(optsHtml, ""));
  526. }
  527. else {
  528. return (new List<CodeValue>(), question) ;
  529. }
  530. }
  531. public void DoOpenTag (string openTag,string openTagVal, bool openFlag, string openTagLang , StringBuilder content , DOCX.Models.ItemInfo test) {
  532. if (test != null) {
  533. switch (openTag) {
  534. case Summary:
  535. if (test.type.Equals("single") || test.type.Equals("multiple")|| test.type.Equals("judge")||test.type.Equals("sortmultiple"))
  536. {
  537. (List<CodeValue> options, string question) = OptionProcess(content.ToString());
  538. test.option = options;
  539. test.question = HtmlHelper.DoUselessTag(question) ;
  540. }
  541. else {
  542. test.question = HtmlHelper.DoUselessTag(content.ToString());
  543. }
  544. break;
  545. case Answer:
  546. if (test.type.Equals("single") || test.type.Equals("multiple")|| test.type.Equals("judge")||test.type.Equals("sortmultiple"))
  547. {
  548. HashSet<string> ans = new HashSet<string>();
  549. var anstr = BlankTag(content.ToString());
  550. for (int idx = 0; idx < 26; idx++)
  551. {
  552. anstr = anstr.Replace(aza[idx], azh[idx]);
  553. }
  554. if (!test.type.Equals("judge"))
  555. {
  556. anstr.Select(s => s.ToString()).ToList().ForEach(x =>
  557. {
  558. ans.Add(x);
  559. });
  560. }
  561. else {
  562. ans.Add(anstr);
  563. }
  564. if (test.option.IsNotEmpty())
  565. {
  566. List<string> codes= test.option.Select(x => x.code).ToList();
  567. var notin = ans.Except(codes).ToList();
  568. List<string> ansd= ans.ToList();
  569. ansd.RemoveAll(x => notin.Contains(x));
  570. if (!ansd.IsNotEmpty()) {
  571. ansd=new List<string>();
  572. foreach (var an in ans) {
  573. if (int.TryParse(an, out int op) && op>=1) {
  574. ansd.Add(optionsKeys[0][op-1]);
  575. }
  576. }
  577. ansd.RemoveAll(x => notin.Contains(x));
  578. }
  579. test.answer = ansd;
  580. }
  581. else {
  582. test.answer = ans.ToList();
  583. }
  584. if (test.type.Equals("judge")) {
  585. if (test.answer != null && test.answer.Count > 0)
  586. {
  587. test.answer = new List<string>() { ans.ToList().First() };
  588. if (dict.TryGetValue(test.answer[0], out string[] keyInfoas))
  589. {
  590. var lang = keyInfoas[0];
  591. var LangConfigAs =_TagConfig.LangConfig.Where(x => x.Lang == lang).FirstOrDefault();
  592. string[] Judge = LangConfigAs.Item.Judge.Split('|');
  593. List<CodeValue> option = new List<CodeValue>() { new CodeValue { code = "A", value = Judge[0] }, new CodeValue { code = "B", value = Judge[1] } };
  594. int index = 0;
  595. foreach (var j in Judge)
  596. {
  597. if (String.Equals(test.answer[0], j, StringComparison.CurrentCultureIgnoreCase))
  598. {
  599. test.answer[0] = option[index].code;
  600. test.option = option;
  601. break;
  602. }
  603. index += 1;
  604. }
  605. }
  606. }
  607. }
  608. }
  609. else {
  610. test.answer = new List<string>() { HtmlHelper.DoUselessTag(content.ToString()) };
  611. }
  612. break;
  613. case Analysis:
  614. test.explain = HtmlHelper.DoUselessTag(content.ToString());
  615. break;
  616. case Taxonomy:
  617. {
  618. string taxonomy = HtmlHelper.DoUselessTag(content.ToString());
  619. taxonomy= BlankTag(taxonomy);
  620. if ( !string.IsNullOrWhiteSpace(taxonomy) && dict.TryGetValue(taxonomy, out string[] keyInfo))
  621. {
  622. var LangConfigfd = _TagConfig.LangConfig.Where(x => x.Lang ==keyInfo[0]).FirstOrDefault();
  623. var Fileds = LangConfigfd.Item.Filed.Split('|');
  624. int fld = Array.IndexOf(Fileds, taxonomy) + 1;
  625. if (fld>0) {
  626. test.field =fld;
  627. }
  628. }
  629. break;
  630. }
  631. case Ended: break;
  632. case Point:
  633. string Points = BlankPointTag(content.ToString());
  634. if (!string.IsNullOrWhiteSpace(Points))
  635. {
  636. string[] ps = Regex.Split(Points, "\\.|\\.|\\。|\\;|\\;");
  637. // string[] ps = Regex.Split(Points, "\\.|\\.|\\、|\\:|\\:|\\,|\\,|\\;|\\;");
  638. if (ps != null && ps.Length > 0)
  639. {
  640. test.knowledge = ps.Distinct().ToList();
  641. }
  642. }
  643. break;
  644. case Score:
  645. //单选或多选,判断答案 脱html标签
  646. string Scores = BlankTag(content.ToString());
  647. //正则匹配数字 整数和小数点
  648. var reg = "^[0-9]+(\\.?[0-9]+)?";
  649. Match m1t = Regex.Match(Scores, reg);
  650. double.TryParse(m1t.Value, out double sc);
  651. test.score = sc;
  652. break;
  653. case Level:
  654. //单选或多选,判断答案 脱html标签
  655. string Levels = BlankTag(content.ToString());
  656. //正则匹配数字 整数和小数点
  657. var lelreg = "^[0-9]+(\\.?[0-9]+)?";
  658. Match lelm1t = Regex.Match(Levels, lelreg);
  659. int.TryParse(lelm1t.Value, out int lvl);
  660. test.level = lvl;
  661. break;
  662. case Filed:
  663. {
  664. if (dict.TryGetValue(openTagVal, out string[] keyInfo))
  665. {
  666. var LangConfigfd = _TagConfig.LangConfig.Where(x => x.Lang == keyInfo[0]).FirstOrDefault();
  667. var Fileds = LangConfigfd.Item.Filed.Split('|');
  668. int fld = Array.IndexOf(Fileds, openTagVal) + 1;
  669. if (fld>0)
  670. {
  671. test.field =fld;
  672. }
  673. }
  674. break;
  675. }
  676. case Count:
  677. //只有填空题才配置填空数量
  678. if (test.type.Equals("complete")) {
  679. //单选或多选,判断答案 脱html标签
  680. string Counts = BlankTag(content.ToString());
  681. //正则匹配数字 整数和小数点
  682. var ctreg = "^[0-9]+(\\.?[0-9]+)?";
  683. Match ctm1t = Regex.Match(Counts, ctreg);
  684. int.TryParse(ctm1t.Value, out int ct);
  685. test.blankCount = ct;
  686. }
  687. break;
  688. }
  689. }
  690. }
  691. }
  692. }