HTML2ITEMV3Translator.cs 39 KB

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