MockDataController.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. using Microsoft.AspNetCore.Mvc;
  2. using System.Text.Json;
  3. using TEAMModelOS.SDK.Extension;
  4. using TEAMModelOS.SDK.Models;
  5. using System;
  6. using OfficeOpenXml;
  7. using System.Reflection;
  8. using System.Xml;
  9. using System.Text.RegularExpressions;
  10. using HTEX.Lib.ETL.Lesson;
  11. using OfficeOpenXml.Style;
  12. using DocumentFormat.OpenXml.Spreadsheet;
  13. using OpenXmlPowerTools;
  14. namespace HTEX.Test.Controllers
  15. {
  16. public static class MockDataController
  17. {
  18. public static async Task MockData()
  19. {
  20. #region 数据模拟
  21. //学生人数
  22. int scount = Random.Shared.Next(40, 45);
  23. //互动次数
  24. int icount = Random.Shared.Next(21,22);
  25. //评测次数
  26. int ecount = Random.Shared.Next(1, 3);
  27. //题目个数
  28. int qcount = Random.Shared.Next(8, 15);
  29. //任务次数
  30. int tcount = Random.Shared.Next(2, 3);
  31. //评价次数
  32. int pcount = Random.Shared.Next(3, 4);
  33. //协作次数
  34. int xcount = Random.Shared.Next(1, 3);
  35. //挑人次数
  36. int kcount = Random.Shared.Next(2, 4);
  37. string type = "hd";
  38. int count = 0;
  39. switch (true)
  40. {
  41. case bool when type.Equals("hd"):
  42. count=icount;
  43. break;
  44. case bool when type.Equals("pc"):
  45. count=ecount;
  46. break;
  47. case bool when type.Equals("rw"):
  48. count=tcount;
  49. break;
  50. case bool when type.Equals("pj"):
  51. count=pcount;
  52. break;
  53. case bool when type.Equals("xz"):
  54. count=xcount;
  55. break;
  56. }
  57. for (var i = 1; i < count; i++)
  58. {
  59. await StudentLesson(scount,ecount,qcount,i,tcount,pcount,xcount,kcount);
  60. }
  61. }
  62. //[HttpPost("student-lesson")]
  63. public static async Task StudentLesson(int scount, int ecount, int qcount, int icount, int tcount, int pcount, int xcount, int kcount)
  64. {
  65. List<StudentLessonData> students = new List<StudentLessonData>();
  66. //个人计分,小组计分
  67. List<WeightedItem> gpitems = new List<WeightedItem>
  68. {
  69. new WeightedItem { Value = 0, Weight = 0.1 },
  70. new WeightedItem { Value = 2, Weight = 0.2 },
  71. new WeightedItem { Value = 5, Weight = 0.2 },
  72. new WeightedItem { Value = 8, Weight = 0.02 },
  73. new WeightedItem { Value = 3, Weight = 0.2 },
  74. new WeightedItem { Value = 4, Weight = 0.2 },
  75. new WeightedItem { Value = 6, Weight = 0.04 },
  76. new WeightedItem { Value = 7, Weight = 0.04 }
  77. };
  78. //互动积分
  79. List<WeightedItem> titems = new List<WeightedItem>
  80. {
  81. new WeightedItem { Value = 0, Weight = 0.4 },
  82. new WeightedItem { Value = 25, Weight = 0.1 },
  83. new WeightedItem { Value = 15, Weight = 0.1 },
  84. new WeightedItem { Value = 10, Weight = 0.05 },
  85. new WeightedItem { Value = 30, Weight = 0.05 },
  86. new WeightedItem { Value = 20, Weight = 0.02 },
  87. new WeightedItem { Value = 40, Weight = 0.03 },
  88. new WeightedItem { Value = 50, Weight = 0.05 },
  89. new WeightedItem { Value = 5, Weight = 0.05 },
  90. new WeightedItem { Value = 35, Weight = 0.05 },
  91. new WeightedItem { Value = 45, Weight = 0.05 },
  92. new WeightedItem { Value = 55, Weight = 0.05 }
  93. };
  94. //for (var i = 0; i<100; i++)
  95. //{
  96. // int randomValue = GetRandomValueByWeight(items);
  97. // Console.WriteLine(randomValue);
  98. //}
  99. //被评价的目标索引
  100. List<List<int>> cworkDist = new List<List<int>>(xcount);
  101. //被评价目标的次数或分数
  102. // List<List<int>> cworkCount = new List<List<int>>(xcount);
  103. for (int i = 0; i < xcount; i++)
  104. {
  105. //乱序取10-20人作为评价目标
  106. var vt = Enumerable.Range(0, scount).OrderBy(x => Random.Shared.Next()).Take(Random.Shared.Next(10, 21));
  107. cworkDist.Add(vt.ToList());
  108. //var counts = new List<int>();
  109. //foreach (var v in vt)
  110. //{
  111. // counts.Add(0);
  112. //}
  113. //cworkCount.Add(counts);
  114. }
  115. //被评价的目标索引
  116. List<List<int>> rateDist = new List<List<int>>(pcount);
  117. //被评价目标的次数或分数
  118. //List<List<int>> rateCount = new List<List<int>>(pcount);
  119. List<string> types = new List<string>();
  120. for (int i = 0; i < pcount; i++)
  121. {
  122. //乱序取10-20人作为评价目标
  123. var vt = Enumerable.Range(0, scount).OrderBy(x => Random.Shared.Next()).Take(Random.Shared.Next(10, 21));
  124. rateDist.Add(vt.ToList());
  125. // var counts = new List<int>();
  126. //foreach (var v in vt)
  127. //{
  128. // counts.Add(0);
  129. //}
  130. //rateCount.Add(counts);
  131. var t = Random.Shared.Next(0, 1);
  132. switch (true)
  133. {
  134. case bool when i==0:
  135. types.Add("Voting");
  136. break;
  137. case bool when i==1:
  138. types.Add("GrandRating");
  139. break;
  140. case bool when i==2:
  141. types.Add("PeerAssessment");
  142. break;
  143. }
  144. }
  145. string[] grouppick = new string[] { "PickupNthGrp", "PickupGrp", "PickupEachGrp" };
  146. string[] pickupAll = new string[] { "PickupNameLst", "PickupOption", "PickupNthGrp", "PickupGrp",
  147. "PickupRange", "PickupEachGrp", "PickupDiff", "PickupWrong", "PickupNoDiff", "PickupRight",
  148. "PickupGener", "PickupWtoW", "PickupWtoR", "PickupLSA_WordFreq", "PickupLSA_Classify", "Pickup0_49" };
  149. for (var s = 0; s<scount; s++)
  150. {
  151. StudentLessonData student = new StudentLessonData()
  152. {
  153. index=s,
  154. seatID=$"{s+1}",
  155. id=$"2024{(s+1).ToString("D3")}",
  156. groupId=$"{Random.Shared.Next(1, 5)}",
  157. attend=1,
  158. gscore= GetRandomValueByWeight(gpitems),
  159. pscore= GetRandomValueByWeight(gpitems),
  160. tscore= GetRandomValueByWeight(titems),
  161. };
  162. for (var p = 0; p<pcount; p++)
  163. {
  164. student.rateingRecord.itemRecords.Add(new ItemRecord());
  165. }
  166. students.Add(student);
  167. }
  168. for (var s = 0; s<scount; s++)
  169. {
  170. var student = students[s];
  171. //挑人
  172. for (var i = 0; i<kcount; i++)
  173. {
  174. var rd= Random.Shared.Next(0, 4);
  175. if (rd==1)
  176. {
  177. student.pickups.Add($"1--{grouppick[Random.Shared.Next(0, grouppick.Length)]}");
  178. }
  179. else {
  180. student.pickups.Add($"1--{pickupAll[Random.Shared.Next(0, pickupAll.Length)]}");
  181. }
  182. }
  183. //互动
  184. for (var i = 0; i<icount; i++)
  185. {
  186. int criterion = 10;
  187. var item = new ItemRecord { criterion=criterion };
  188. var w = Random.Shared.Next(0, 4);
  189. switch (true)
  190. {
  191. //未参与
  192. case bool when w==0:
  193. item.resultWeight= InteractWeight.T0;
  194. item.resultType= InteractReultType.T0;
  195. item.itemScore=0;
  196. break;
  197. //参与了
  198. case bool when w==1:
  199. item.resultWeight= InteractWeight.T1;
  200. item.resultType= InteractReultType.T1;
  201. item.itemScore=0;
  202. break;
  203. //部分正确
  204. case bool when w==2:
  205. var score = Random.Shared.Next(1, criterion);
  206. item.resultWeight= MinMaxNormalization(1, criterion, score, InteractWeight.T1, InteractWeight.TT);
  207. item.resultType= InteractReultType.TP;
  208. item.itemScore=0;
  209. break;
  210. //完全正确
  211. case bool when w==3:
  212. item.resultWeight= InteractWeight.TT;
  213. item.resultType= InteractReultType.TT;
  214. item.itemScore=criterion;
  215. break;
  216. }
  217. student.interactRecord.interactRecords.Add(item);
  218. }
  219. //任务
  220. for (var t = 0; t<tcount; t++)
  221. {
  222. var w = Random.Shared.Next(0, 5);
  223. var item = new ItemRecord { };
  224. switch (true)
  225. {
  226. //未参与
  227. case bool when w==0:
  228. item.resultWeight= InteractWeight.T0;
  229. item.resultType= InteractReultType.T0;
  230. item.itemScore=0;
  231. item.optCount=0;
  232. break;
  233. //参加
  234. case bool when w==1:
  235. item.resultWeight= InteractWeight.TT;
  236. item.resultType= InteractReultType.TT;
  237. item.optCount= Random.Shared.Next(1, 4);
  238. item.itemScore=item.optCount*10;
  239. item.isGroup= Random.Shared.Next(0,4)!=1;
  240. break;
  241. }
  242. student.taskRecord.taskRate= student.taskRecord.itemRecords.Where(x => x.resultWeight>0).Count()*1.0/tcount;
  243. student.taskRecord.itemRecords.Add(item);
  244. }
  245. //评价
  246. for (var p = 0; p<pcount; p++)
  247. {
  248. var item = student.rateingRecord.itemRecords[p];
  249. var subtype = string.Empty;
  250. item.itemType=types[p];
  251. if (types[p].Equals("PeerAssessment"))
  252. {
  253. var sub = Random.Shared.Next(0, 3);
  254. subtype= sub==0 ? "ALL" : sub==1 ? "Two" : "Self";
  255. }
  256. var w = Random.Shared.Next(0, 3);
  257. switch (true)
  258. {
  259. //未参与
  260. case bool when w==0:
  261. item.resultWeight= InteractWeight.T0;
  262. item.resultType= InteractReultType.T0;
  263. item.itemScore=0;
  264. break;
  265. //参与
  266. case bool when w==1||w==2:
  267. item.resultWeight= InteractWeight.T1;
  268. item.resultType= InteractReultType.T1;
  269. if (item.itemType!.Equals("Voting"))
  270. {
  271. var index = Random.Shared.Next(0, rateDist[p].Count);
  272. //rateCount[p][index]+=1;
  273. students[rateDist[p][index]].rateingRecord.itemRecords[p].itemScore+=1;
  274. }
  275. else
  276. {
  277. if (item.itemType.Equals("PeerAssessment"))
  278. {
  279. var index = Random.Shared.Next(0, rateDist[p].Count);
  280. //操作次数
  281. int opt_count = Random.Shared.Next(1, 2);
  282. for (var count = 0; count<opt_count; count++)
  283. {
  284. var score = Random.Shared.Next(3, 10);
  285. // rateCount[p][index]+=score;
  286. students[rateDist[p][index]].rateingRecord.itemRecords[p].itemScore+=score;
  287. item.optCount+= 1;
  288. }
  289. }
  290. else
  291. {
  292. var index = Random.Shared.Next(0, rateDist[p].Count);
  293. var score = Random.Shared.Next(3, 10);
  294. // rateCount[p][index]+=score;
  295. students[rateDist[p][index]].rateingRecord.itemRecords[p].itemScore+=score;
  296. }
  297. }
  298. break;
  299. }
  300. // student.rateingRecord.itemRecords.Add(item);
  301. }
  302. //个人协作
  303. {
  304. for (var x = 0; x<xcount; x++)
  305. {
  306. int[] r = new int[] { 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1 };
  307. var w = r[Random.Shared.Next(0, r.Length)];
  308. var item = new ItemRecord { };
  309. switch (true)
  310. {
  311. //未参与
  312. case bool when w==0:
  313. item.resultWeight= InteractWeight.T0;
  314. item.resultType= InteractReultType.T0;
  315. item.itemScore=0;
  316. break;
  317. //
  318. case bool when w==1:
  319. item.resultWeight= InteractWeight.TP;
  320. item.resultType= InteractReultType.TP;
  321. int[] q = new int[] { 10, 5, 5, 20, 30, 10, 25, 10, 15, 15, 30, 5, 10, 20, 15, 25, 10, 5, 15, 20, 20, 25, 5, 5 };
  322. item.itemScore=q[Random.Shared.Next(0, q.Count())];
  323. break;
  324. }
  325. student.coworkRecord.itemRecords.Add(item);
  326. }
  327. }
  328. //小组协作
  329. {
  330. int[] r = new int[] { 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1 };
  331. var w = r[Random.Shared.Next(0, r.Length)];
  332. var item = new ItemRecord { };
  333. double grpcoworkScore = 0;
  334. switch (true)
  335. {
  336. //未参与
  337. case bool when w==0:
  338. break;
  339. //
  340. case bool when w==1:
  341. int[] q = new int[] { 10, 5, 5, 20, 30, 10, 25, 10, 15, 15, 30, 5, 10, 20, 15, 25, 10, 5, 15, 20, 20, 25, 5, 5 };
  342. grpcoworkScore= q[Random.Shared.Next(0, q.Count())]* Random.Shared.Next(2,4 );
  343. student.group_coworkScore.Add(grpcoworkScore);
  344. break;
  345. }
  346. }
  347. //评测
  348. for (var e = 0; e<ecount; e++)
  349. {
  350. StudentExamRecord examRecord = new();
  351. double allocation = 0;
  352. for (var q = 0; q<qcount; q++)
  353. {
  354. var criterion = Random.Shared.Next(5, 10);
  355. allocation+=criterion;
  356. var item = new ItemRecord { criterion =criterion };
  357. var w = Random.Shared.Next(0, 4);
  358. switch (true)
  359. {
  360. //未作答
  361. case bool when w==0:
  362. item.resultWeight= InteractWeight.T0;
  363. item.resultType= InteractReultType.T0;
  364. item.itemScore=0;
  365. break;
  366. //作答错误
  367. case bool when w==1:
  368. item.resultWeight= InteractWeight.T1;
  369. item.resultType= InteractReultType.T1;
  370. item.itemScore=0;
  371. break;
  372. //部分正确
  373. case bool when w==2:
  374. var score = Random.Shared.Next(1, criterion);
  375. item.resultWeight= MinMaxNormalization(1, criterion, score, InteractWeight.T1, InteractWeight.TT); // score * 1.0 / criterion* (InteractWeight.TT-InteractWeight.T1);
  376. item.resultType= InteractReultType.TP;
  377. item.itemScore=score;
  378. break;
  379. //完全正确
  380. case bool when w==3:
  381. item.resultWeight= InteractWeight.TT;
  382. item.resultType= InteractReultType.TT;
  383. item.itemScore=criterion;
  384. break;
  385. }
  386. examRecord.itemRecords.Add(item);
  387. }
  388. examRecord.qcount=qcount;
  389. examRecord.workCount= examRecord.itemRecords.Where(x => x.resultWeight>0).Count();
  390. examRecord.allocation=allocation;
  391. examRecord.score= examRecord.itemRecords.Where(x => x.itemScore>=0).Select(x => x.itemScore).Sum();//得分
  392. examRecord.scoreRate = Math.Round(examRecord.score * 1.0 / allocation, 4);//得分率
  393. examRecord.answerRate= Math.Round(examRecord.itemRecords.Where(x => x.resultWeight>0).Count()*1.0/qcount, 4);//作答率
  394. student.examRecords.Add(examRecord);
  395. }
  396. }
  397. for (var p = 0; p<pcount; p++)
  398. {
  399. var order = students.OrderByDescending(x => x.rateingRecord.itemRecords[p].itemScore);
  400. var maxItems = students.FindAll(x => x.rateingRecord.itemRecords[p].itemScore==order.First().rateingRecord.itemRecords[p].itemScore);
  401. var max = students.FindAll(x => x.rateingRecord.itemRecords[p].itemScore==order.First().rateingRecord.itemRecords[p].itemScore).First().rateingRecord.itemRecords[p].itemScore;
  402. var min = students.FindAll(x => x.rateingRecord.itemRecords[p].itemScore==order.Last().rateingRecord.itemRecords[p].itemScore).First().rateingRecord.itemRecords[p].itemScore;
  403. var sum = students.Sum(x => x.rateingRecord.itemRecords[p].itemScore);
  404. foreach (var student in students)
  405. {
  406. if (student.rateingRecord.itemRecords[p].itemScore>0 && student.rateingRecord.itemRecords[p].optCount>0)
  407. {
  408. student.rateingRecord.itemRecords[p].resultType=InteractReultType.TP;
  409. var data = MinMaxNormalization(min, max, student.rateingRecord.itemRecords[p].itemScore);
  410. student.rateingRecord.itemRecords[p].resultWeight=Math.Round(InteractWeight.T1+ data * 1.0 / 100 * (InteractWeight.TT-InteractWeight.T1), 4);
  411. if (maxItems.Select(x => x.seatID).Contains(student.seatID))
  412. {
  413. student.rateingRecord.itemRecords[p].resultType= InteractReultType.TT;
  414. student.rateingRecord.itemRecords[p].resultWeight= InteractWeight.TT;
  415. }
  416. }
  417. }
  418. }
  419. //个人协作
  420. for (var p = 0; p<xcount; p++)
  421. {
  422. var order = students.OrderByDescending(x => x.coworkRecord.itemRecords[p].itemScore);
  423. var maxItems = students.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore);
  424. var max = students.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
  425. var min = students.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.Last().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
  426. var sum = students.Sum(x => x.coworkRecord.itemRecords[p].itemScore);
  427. foreach (var student in students)
  428. {
  429. if (student.coworkRecord.itemRecords[p].itemScore>0)
  430. {
  431. student.coworkRecord.itemRecords[p].resultType=InteractReultType.TP;
  432. var data = MinMaxNormalization(min, max, student.coworkRecord.itemRecords[p].itemScore);
  433. student.coworkRecord.itemRecords[p].resultWeight=Math.Round(InteractWeight.T1+ data * 1.0 / 100 * (InteractWeight.TT-InteractWeight.T1), 4);
  434. if (maxItems.Select(x => x.seatID).Contains(student.seatID))
  435. {
  436. student.coworkRecord.itemRecords[p].resultType= InteractReultType.TT;
  437. student.coworkRecord.itemRecords[p].resultWeight= InteractWeight.TT;
  438. }
  439. }
  440. }
  441. }
  442. #endregion 数据模拟
  443. string jsons = await System.IO.File.ReadAllTextAsync("F:\\lesson-local\\analysis\\analysis.json");
  444. long time = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
  445. LessonDataAnalysisCluster lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisCluster>();
  446. var lessonItems= LessonETLService. ProcessStudentDataV2(students, lessonDataAnalysis);
  447. var excleFile = $"F:\\mock-data\\{time}.xlsx";
  448. var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  449. XmlDocument xmlDocument = new XmlDocument();
  450. xmlDocument.Load($"{runtimePath}\\summary.xml");
  451. List<string> noStujson = new List<string>();
  452. await LessonETLService.ExportToExcelLocal(lessonItems, excleFile, xmlDocument);
  453. try {
  454. await System.IO.File.WriteAllTextAsync($"F:\\mock-data\\{time}.json", new { scount, ecount, qcount, icount, tcount, pcount, xcount, students }.ToJsonString());
  455. } catch (Exception ex) {
  456. Console.WriteLine(scount);
  457. }
  458. //return Ok(new { scount, ecount, qcount, icount, tcount, pcount, xcount, students });
  459. }
  460. private static int GetRandomValueByWeight(List<WeightedItem> items)
  461. {
  462. Random random = new Random();
  463. double randomWeight = random.NextDouble();
  464. double cumulativeWeight = 0.0;
  465. foreach (var item in items)
  466. {
  467. cumulativeWeight += item.Weight;
  468. if (randomWeight <= cumulativeWeight)
  469. {
  470. return item.Value;
  471. }
  472. }
  473. // This should not happen if all weights sum up to 1
  474. return items[items.Count - 1].Value;
  475. }
  476. private static double MinMaxNormalization(double min, double max, double x, double minRank = 1, double maxRank = 100)
  477. {
  478. //排名指数计算=( 当前值分数- 298) / (9992 - 298) * (99 - 60) + 60
  479. //将每个人的积分转化为60-100
  480. //排名 = (积分 - 最低积分) / (最高积分 - 最低积分) * (最大排名 - 最小排名) + 最小排名
  481. return Math.Round(x==0 ? 0 : max-min!=0 ? (x - min)*1.0 / (max - min) * (maxRank - minRank) + minRank : (x)*1.0 / (max) * (maxRank - minRank) + minRank,4);
  482. }
  483. }
  484. class WeightedItem
  485. {
  486. public int Value { get; set; }
  487. public double Weight { get; set; }
  488. }
  489. }