CrazyIter_Bin 7 miesięcy temu
rodzic
commit
bdaeecd401

+ 93 - 67
TEAMModelOS.Extension/HTEX.Test/Controllers/LessonRecordController.cs

@@ -157,11 +157,11 @@ namespace HTEX.Test.Controllers
             "timeCount":
              */
             bool  loadLocal = true;
-            LessonDataAnlysis lessonDataAnlysis = new LessonDataAnlysis();
-            var files_anlysis = files.Where(x => x.EndsWith("anlysis.json")).Take(1).FirstOrDefault();
+            LessonDataAnalysis lessonDataAnalysis = new LessonDataAnalysis();
+            var files_anlysis = files.Where(x => x.EndsWith("analysis.json")).Take(1).FirstOrDefault();
             if (files_anlysis!=null) {
                 string jsons = await System.IO.File.ReadAllTextAsync(files_anlysis);
-                lessonDataAnlysis= jsons.ToObject<LessonDataAnlysis>();
+                lessonDataAnalysis= jsons.ToObject<LessonDataAnalysis>();
                 loadLocal=false; 
             }
             if (loadLocal) {
@@ -203,106 +203,106 @@ namespace HTEX.Test.Controllers
                 Console.WriteLine($"techCounts:{techCounts.Count}");
                 //标准差偏差N倍,视为异常数据
                 int thresholdMultiplier = 2;
-                lessonDataAnlysis.pscore  = techCounts.SelectMany(x =>x.pscore);
-                lessonDataAnlysis.pscore= CleanDataBySDThreshold(lessonDataAnlysis.pscore, thresholdMultiplier).OrderBy(x => x);
+                lessonDataAnalysis.pscore  = techCounts.SelectMany(x =>x.pscore);
+                lessonDataAnalysis.pscore= CleanDataBySDThreshold(lessonDataAnalysis.pscore, thresholdMultiplier).OrderBy(x => x);
                 List<KeyValuePair<double, List<double>>> clustersDataPscore = new();
-                var clusterPscore = KMeansService.KMeans(lessonDataAnlysis.pscore.Select(x => x).OrderBy(x => x));
+                var clusterPscore = KMeansService.KMeans(lessonDataAnalysis.pscore.Select(x => x).OrderBy(x => x));
                 foreach (var item in clusterPscore)
                 {
                     Console.WriteLine($"dp:{item.Key} ,avg: {item.Value.Average()}, count: {item.Value.Count}, min:{item.Value.Min()}, max:{item.Value.Max()}");
                 }
-                Console.WriteLine($"avg: {lessonDataAnlysis.pscore.Average()}");
+                Console.WriteLine($"avg: {lessonDataAnalysis.pscore.Average()}");
 
                 foreach (var s in clusterPscore.OrderBy(x => x.Key))
                 {
                     clustersDataPscore.Add(s);
                 }
-                lessonDataAnlysis.clustersPscore=clustersDataPscore;
+                lessonDataAnalysis.clustersPscore=clustersDataPscore;
 
-                lessonDataAnlysis.gscore  = techCounts.SelectMany(x => x.gscore);
-                lessonDataAnlysis.gscore= CleanDataBySDThreshold(lessonDataAnlysis.gscore, thresholdMultiplier).OrderBy(x => x);
+                lessonDataAnalysis.gscore  = techCounts.SelectMany(x => x.gscore);
+                lessonDataAnalysis.gscore= CleanDataBySDThreshold(lessonDataAnalysis.gscore, thresholdMultiplier).OrderBy(x => x);
                 List<KeyValuePair<double, List<double>>> clustersDataGscore = new();
-                var clusterGscore = KMeansService.KMeans(lessonDataAnlysis.gscore.Select(x => x).OrderBy(x => x));
+                var clusterGscore = KMeansService.KMeans(lessonDataAnalysis.gscore.Select(x => x).OrderBy(x => x));
                 foreach (var item in clusterGscore)
                 {
                     Console.WriteLine($"dp:{item.Key} ,avg: {item.Value.Average()}, count: {item.Value.Count}, min:{item.Value.Min()}, max:{item.Value.Max()}");
                 }
-                Console.WriteLine($"avg: {lessonDataAnlysis.gscore.Average()}");
+                Console.WriteLine($"avg: {lessonDataAnalysis.gscore.Average()}");
 
                 foreach (var s in clusterGscore.OrderBy(x => x.Key))
                 {
                     clustersDataGscore.Add(s);
                 }
-                lessonDataAnlysis.clustersGscore=clustersDataGscore;
+                lessonDataAnalysis.clustersGscore=clustersDataGscore;
 
 
-                lessonDataAnlysis.tscore  = techCounts.SelectMany(x => x.tscore);
-                lessonDataAnlysis.tscore= CleanDataBySDThreshold(lessonDataAnlysis.tscore, thresholdMultiplier).OrderBy(x => x);
+                lessonDataAnalysis.tscore  = techCounts.SelectMany(x => x.tscore);
+                lessonDataAnalysis.tscore= CleanDataBySDThreshold(lessonDataAnalysis.tscore, thresholdMultiplier).OrderBy(x => x);
                 List<KeyValuePair<double, List<double>>> clustersDataTscore = new();
-                var clusterTscore = KMeansService.KMeans(lessonDataAnlysis.tscore.Select(x => x).OrderBy(x => x));
+                var clusterTscore = KMeansService.KMeans(lessonDataAnalysis.tscore.Select(x => x).OrderBy(x => x));
                 foreach (var item in clusterTscore)
                 {
                     Console.WriteLine($"dp:{item.Key} ,avg: {item.Value.Average()}, count: {item.Value.Count}, min:{item.Value.Min()}, max:{item.Value.Max()}");
                 }
-                Console.WriteLine($"avg: {lessonDataAnlysis.tscore.Average()}");
+                Console.WriteLine($"avg: {lessonDataAnalysis.tscore.Average()}");
                 foreach (var s in clusterTscore.OrderBy(x => x.Key))
                 {
                     clustersDataTscore.Add(s);
                 }
-                lessonDataAnlysis.clustersTscore=clustersDataTscore;
+                lessonDataAnalysis.clustersTscore=clustersDataTscore;
 
 
-                lessonDataAnlysis.cowork = techCounts.Where(x => x.coworkCount>0).Select(x => (double)x.coworkCount);
-                lessonDataAnlysis.cowork= CleanDataBySDThreshold(lessonDataAnlysis.cowork, thresholdMultiplier);
+                lessonDataAnalysis.cowork = techCounts.Where(x => x.coworkCount>0).Select(x => (double)x.coworkCount);
+                lessonDataAnalysis.cowork= CleanDataBySDThreshold(lessonDataAnalysis.cowork, thresholdMultiplier);
 
-                lessonDataAnlysis.coworkBase = techCounts.Where(x => x.coworkCountBase>0).Select(x => (double)x.coworkCountBase);
-                lessonDataAnlysis.coworkBase= CleanDataBySDThreshold(lessonDataAnlysis.coworkBase, thresholdMultiplier);
+                lessonDataAnalysis.coworkBase = techCounts.Where(x => x.coworkCountBase>0).Select(x => (double)x.coworkCountBase);
+                lessonDataAnalysis.coworkBase= CleanDataBySDThreshold(lessonDataAnalysis.coworkBase, thresholdMultiplier);
 
-                lessonDataAnlysis.task = techCounts.Where(x => x.taskCount > 0).Select(x => (double)x.taskCount);
-                lessonDataAnlysis.task= CleanDataBySDThreshold(lessonDataAnlysis.task, thresholdMultiplier);
+                lessonDataAnalysis.task = techCounts.Where(x => x.taskCount > 0).Select(x => (double)x.taskCount);
+                lessonDataAnalysis.task= CleanDataBySDThreshold(lessonDataAnalysis.task, thresholdMultiplier);
 
-                lessonDataAnlysis.taskBase = techCounts.Where(x => x.taskCountBase  > 0).Select(x => (double)x.taskCountBase);
-                lessonDataAnlysis.taskBase = CleanDataBySDThreshold(lessonDataAnlysis.taskBase, thresholdMultiplier);
+                lessonDataAnalysis.taskBase = techCounts.Where(x => x.taskCountBase  > 0).Select(x => (double)x.taskCountBase);
+                lessonDataAnalysis.taskBase = CleanDataBySDThreshold(lessonDataAnalysis.taskBase, thresholdMultiplier);
 
 
-                lessonDataAnlysis.exam  = techCounts.Where(x => x.examCount  > 0).Select(x => (double)x.examCount);
-                lessonDataAnlysis.exam = CleanDataBySDThreshold(lessonDataAnlysis.exam, thresholdMultiplier);
+                lessonDataAnalysis.exam  = techCounts.Where(x => x.examCount  > 0).Select(x => (double)x.examCount);
+                lessonDataAnalysis.exam = CleanDataBySDThreshold(lessonDataAnalysis.exam, thresholdMultiplier);
 
-                lessonDataAnlysis.examBase  = techCounts.Where(x => x.examCountBase  > 0).Select(x => (double)x.examCountBase);
-                lessonDataAnlysis.examBase = CleanDataBySDThreshold(lessonDataAnlysis.examBase, thresholdMultiplier);
+                lessonDataAnalysis.examBase  = techCounts.Where(x => x.examCountBase  > 0).Select(x => (double)x.examCountBase);
+                lessonDataAnalysis.examBase = CleanDataBySDThreshold(lessonDataAnalysis.examBase, thresholdMultiplier);
 
 
-                lessonDataAnlysis.smartRating  = techCounts.Where(x => x.smartRatingCount  > 0).Select(x => (double)x.smartRatingCount);
-                lessonDataAnlysis.smartRating = CleanDataBySDThreshold(lessonDataAnlysis.smartRating, thresholdMultiplier);
+                lessonDataAnalysis.smartRating  = techCounts.Where(x => x.smartRatingCount  > 0).Select(x => (double)x.smartRatingCount);
+                lessonDataAnalysis.smartRating = CleanDataBySDThreshold(lessonDataAnalysis.smartRating, thresholdMultiplier);
 
-                lessonDataAnlysis.smartRatingBase  = techCounts.Where(x => x.smartRatingCountBase  > 0).Select(x => (double)x.smartRatingCountBase);
-                lessonDataAnlysis.smartRatingBase = CleanDataBySDThreshold(lessonDataAnlysis.smartRatingBase, thresholdMultiplier);
+                lessonDataAnalysis.smartRatingBase  = techCounts.Where(x => x.smartRatingCountBase  > 0).Select(x => (double)x.smartRatingCountBase);
+                lessonDataAnalysis.smartRatingBase = CleanDataBySDThreshold(lessonDataAnalysis.smartRatingBase, thresholdMultiplier);
 
-                lessonDataAnlysis.irs = techCounts.Where(x => x.irsCount > 0).Select(x => (double)x.irsCount);
-                lessonDataAnlysis.irs = CleanDataBySDThreshold(lessonDataAnlysis.irs, thresholdMultiplier);
+                lessonDataAnalysis.irs = techCounts.Where(x => x.irsCount > 0).Select(x => (double)x.irsCount);
+                lessonDataAnalysis.irs = CleanDataBySDThreshold(lessonDataAnalysis.irs, thresholdMultiplier);
 
 
-                lessonDataAnlysis.interactNormal = techCounts.Where(x => x.interactNormalCount > 0).Select(x => (double)x.interactNormalCount);
+                lessonDataAnalysis.interactNormal = techCounts.Where(x => x.interactNormalCount > 0).Select(x => (double)x.interactNormalCount);
               
-                Console.WriteLine($"interactNormal{lessonDataAnlysis.interactNormal.Count()}");
-                lessonDataAnlysis.interactNormal= CleanDataBySDThreshold(lessonDataAnlysis.interactNormal, thresholdMultiplier).OrderBy(x => x);
-                Console.WriteLine($"interactNormal{lessonDataAnlysis.interactNormal.Count()}");
+                Console.WriteLine($"interactNormal{lessonDataAnalysis.interactNormal.Count()}");
+                lessonDataAnalysis.interactNormal= CleanDataBySDThreshold(lessonDataAnalysis.interactNormal, thresholdMultiplier).OrderBy(x => x);
+                Console.WriteLine($"interactNormal{lessonDataAnalysis.interactNormal.Count()}");
 
 
                 var tcount = techCounts.Where(x => x.coworkCount > 0  || x.taskCount>0  || x.interactNormalCount>0|| x.examCount>0  || x.smartRatingCount>0);
-                double coworkWeight = lessonDataAnlysis.cowork.Count()*1.0/tcount.Count();
-                lessonDataAnlysis.coworkWeight=coworkWeight;
-                double taskWeight = lessonDataAnlysis.task.Count()*1.0/tcount.Count();
-                lessonDataAnlysis.taskWeight=taskWeight;
-                double interactWeight = lessonDataAnlysis.interactNormal.Count()*1.0/tcount.Count();
-                lessonDataAnlysis.interactWeight=interactWeight;
-                double examWeight = lessonDataAnlysis. exam.Count()*1.0/tcount.Count();
-                lessonDataAnlysis.examWeight=examWeight;
-                double smartRatingWeight = lessonDataAnlysis. smartRating.Count()*1.0/tcount.Count();
-                lessonDataAnlysis.smartRatingWeight=smartRatingWeight;
+                double coworkWeight = lessonDataAnalysis.cowork.Count()*1.0/tcount.Count();
+                lessonDataAnalysis.coworkWeight=coworkWeight;
+                double taskWeight = lessonDataAnalysis.task.Count()*1.0/tcount.Count();
+                lessonDataAnalysis.taskWeight=taskWeight;
+                double interactWeight = lessonDataAnalysis.interactNormal.Count()*1.0/tcount.Count();
+                lessonDataAnalysis.interactWeight=interactWeight;
+                double examWeight = lessonDataAnalysis. exam.Count()*1.0/tcount.Count();
+                lessonDataAnalysis.examWeight=examWeight;
+                double smartRatingWeight = lessonDataAnalysis. smartRating.Count()*1.0/tcount.Count();
+                lessonDataAnalysis.smartRatingWeight=smartRatingWeight;
 
                 List<KeyValuePair<double, List<int>>> clustersDataInteract = new();
-                var clusterInteract = KMeansService.KMeans(lessonDataAnlysis.interactNormal.Select(x => (int)x).OrderBy(x => x));
+                var clusterInteract = KMeansService.KMeans(lessonDataAnalysis.interactNormal.Select(x => (int)x).OrderBy(x => x));
                 foreach (var item in clusterInteract)
                 {
                     Console.WriteLine($"dp:{item.Key} ,avg: {item.Value.Average()}, count: {item.Value.Count}, min:{item.Value.Min()}, max:{item.Value.Max()}");
@@ -311,7 +311,7 @@ namespace HTEX.Test.Controllers
                 {
                     clustersDataInteract.Add(s);
                 }
-                lessonDataAnlysis.clustersInteract=clustersDataInteract;
+                lessonDataAnalysis.clustersInteract=clustersDataInteract;
                 var groups = techCounts.SelectMany(x => x.timeCount).GroupBy(x => x.code).Select(x => new { key = x.Key, list = x.ToList() });
                 Dictionary<string, IEnumerable<double>> techDict = new Dictionary<string, IEnumerable<double>>();
                 foreach (var group in groups)
@@ -320,7 +320,7 @@ namespace HTEX.Test.Controllers
                     array = CleanDataBySDThreshold(array, thresholdMultiplier);
                     techDict.Add(group.key, array);
                 }
-                System.IO. File.WriteAllText(Path.Combine(path, "anlysis.json"), lessonDataAnlysis.ToJsonString());
+                System.IO. File.WriteAllText(Path.Combine(path, "analysis.json"), lessonDataAnalysis.ToJsonString());
             }
           
      
@@ -343,7 +343,7 @@ namespace HTEX.Test.Controllers
                     if (techCount != null)
                     {
                         
-                        IEnumerable<double> interact = lessonDataAnlysis.interactNormal;
+                        IEnumerable<double> interact = lessonDataAnalysis.interactNormal;
                         int interactCount = techCount.interactNormalCount;
                         //当前课例的互动次数在互动总列表超过N%;
                         //var persent = GetPersent(interact, interactCount);
@@ -370,21 +370,24 @@ namespace HTEX.Test.Controllers
                                 }
                             }
                             //个人计分最大值
-                            var q = lessonDataAnlysis.pscore.Max();
+                            var q = lessonDataAnalysis.pscore.Max();
                             //互动计分最大值
-                            var t = lessonDataAnlysis.tscore.Max();
+                            var t = lessonDataAnalysis.tscore.Max();
                             if (studentLessonData.interactRecord.interactRecords.Count==interactCount && interactCount>0)
                             {
                                 //互动次数
                                 var n = studentLessonData.interactRecord.interactRecords.Count()*1.0;
                                 //聚类分数量大和数量小的类群。判断当前出题数在两个类群的最大范围内,再取其质心。
-                                var m = n<=lessonDataAnlysis.clustersInteract.First().Value.Max() ? lessonDataAnlysis.clustersInteract.First().Key*1.0 : lessonDataAnlysis.clustersInteract.Last().Key *1.0;
+                                var m = n<=lessonDataAnalysis.clustersInteract.First().Value.Max() ? lessonDataAnalysis.clustersInteract.First().Key*1.0 : lessonDataAnalysis.clustersInteract.Last().Key *1.0;
                                 var w = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Count()*1.0;
-                                var r = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.TT).Count()*1.0;
-                                var p = InteractWeight.TT;
+                                var r = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.T1).Count()*1.0;
+                                var k = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Sum(x=> x.itemScore*1.0);
+                                var e = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.T1).Sum(x => x.itemScore*1.0);
                                 var j = InteractWeight.T1;
                                 //学习成效算法
-                                x=((i/t) + ((n/m)*(w*(w/n)+(p/j)* (r/n) *r)))/n;
+                                //x=((i/t) + ((n/m)*(w*(w/n)+(p/j)* (r/n) *r)))/n;
+                                x=((i/t) +(w*k)/(j*m) +(r*e)/(j*m) )/n;
+
                                 y=((n/m)*(w*(w/n)+  (r/n) *r))/n;
                                // var rate = w*100.0/interactCount;
                                // studentLessonData.interactRecord.interactScore=data;
@@ -419,10 +422,10 @@ namespace HTEX.Test.Controllers
             return Ok(new
             {
                 lessons,
-                interactNormal = lessonDataAnlysis.interactNormal.OrderByDescending(x=>x),
-                cowork = lessonDataAnlysis.cowork.OrderByDescending(x => x),
-                exam = lessonDataAnlysis.exam.OrderByDescending(x => x),
-                smartRating = lessonDataAnlysis.smartRating.OrderByDescending(x => x),
+                interactNormal = lessonDataAnalysis.interactNormal.OrderByDescending(x=>x),
+                cowork = lessonDataAnalysis.cowork.OrderByDescending(x => x),
+                exam = lessonDataAnalysis.exam.OrderByDescending(x => x),
+                smartRating = lessonDataAnalysis.smartRating.OrderByDescending(x => x),
             });
         }
 
@@ -491,7 +494,7 @@ namespace HTEX.Test.Controllers
             return filePaths;
         }
 
-        public class LessonDataAnlysis
+        public class LessonDataAnalysis
         {
             public long updateTime { get; set; }
             public IEnumerable<double> cowork { get; set; } = new List<double>();
@@ -1686,6 +1689,7 @@ namespace HTEX.Test.Controllers
         /// <returns></returns>
         private   List<StudentLessonData> GetCoworkData( LessonBase lessonBase, TimeLineData timeLineData, List<CoworkData> coworkDatas, List<StudentLessonData> studentLessonDatas)
         {
+            int p = 0;
             foreach (var coworkData in coworkDatas) 
             {
                 var keys = coworkData.participateLevelList.Keys;
@@ -1699,8 +1703,8 @@ namespace HTEX.Test.Controllers
                         //不能完全依赖 
                         if (score>0)
                         {
-                            itemRecord.resultWeight =  InteractWeight.T1;
-                            itemRecord.resultType = InteractReultType.T1;
+                            itemRecord.resultWeight =  InteractWeight.TP;
+                            itemRecord.resultType = InteractReultType.TP;
                         }
                         else {
                             itemRecord.resultWeight =  InteractWeight.T0;
@@ -1709,7 +1713,29 @@ namespace HTEX.Test.Controllers
                         student.coworkRecord.itemRecords.Add(itemRecord);
                     }
                 }
+
+                var order = studentLessonDatas.OrderByDescending(x => x.coworkRecord.itemRecords[p].itemScore);
+                var maxItems = studentLessonDatas.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore);
+                var max = studentLessonDatas.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
+                var min = studentLessonDatas.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.Last().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
+                var sum = studentLessonDatas.Sum(x => x.coworkRecord.itemRecords[p].itemScore);
+                foreach (var student in studentLessonDatas)
+                {
+                    if (student.attend==1  && student.coworkRecord.itemRecords.Count>=p+1 &&  student.coworkRecord.itemRecords[p].itemScore>0)
+                    {
+                        student.coworkRecord.itemRecords[p].resultType=InteractReultType.TP;
+                        var data = MinMaxNormalization(min, max, student.coworkRecord.itemRecords[p].itemScore);
+                        student.coworkRecord.itemRecords[p].resultWeight=InteractWeight.T1+  data * 1.0  / 100 * (InteractWeight.TT-InteractWeight.T1);
+                        if (maxItems.Select(x => x.seatID).Contains(student.seatID))
+                        {
+                            student.coworkRecord.itemRecords[p].resultType= InteractReultType.TT;
+                            student.coworkRecord.itemRecords[p].resultWeight= InteractWeight.TT;
+                        }
+                    }
+                }
+                p++;
             }
+            
             return studentLessonDatas;
         }
 

+ 468 - 0
TEAMModelOS.Extension/HTEX.Test/Controllers/MockDataController.cs

@@ -0,0 +1,468 @@
+using Microsoft.AspNetCore.Mvc;
+using System.Text.Json;
+using static HTEX.Test.Controllers.LessonRecordController;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
+
+namespace HTEX.Test.Controllers
+{
+    [ApiController]
+    [Route("mock-data")]
+    public class MockDataController : ControllerBase
+    {
+        [HttpPost("student-lesson")]
+        public async Task<IActionResult> StudentLesson(JsonElement json) 
+        {
+            #region 数据模拟
+            //学生人数
+            int scount = Random.Shared.Next(40, 45);
+            //评测次数
+            int ecount = Random.Shared.Next(1, 3);
+            //题目个数
+            int qcount = Random.Shared.Next(8, 15);
+            //互动次数
+            int icount = Random.Shared.Next(3, 20);
+            //任务次数
+            int tcount = Random.Shared.Next(1, 3);
+            //评价次数
+            int pcount = Random.Shared.Next(1, 3);
+            //协作次数
+            int xcount = Random.Shared.Next(1, 3);
+            List<StudentLessonData> students = new List<StudentLessonData>();
+            //个人计分,小组计分
+            List<WeightedItem> gpitems = new List<WeightedItem>
+            {
+                new WeightedItem { Value = 0, Weight = 0.3 },
+                new WeightedItem { Value = 2, Weight = 0.1 },
+                new WeightedItem { Value = 5, Weight = 0.2 },
+                new WeightedItem { Value = 8, Weight = 0.1 },
+                new WeightedItem { Value = 3, Weight = 0.05 },
+                new WeightedItem { Value = 4, Weight = 0.02 },
+                new WeightedItem { Value = 6, Weight = 0.03 },
+                new WeightedItem { Value = 7, Weight = 0.2 }
+            };
+            //个人计分,小组计分
+            List<WeightedItem> titems = new List<WeightedItem>
+            {
+                new WeightedItem { Value = 0, Weight = 0.4 },
+                new WeightedItem { Value = 25, Weight = 0.1 },
+                new WeightedItem { Value = 15, Weight = 0.1 },
+                new WeightedItem { Value = 10, Weight = 0.05 },
+                new WeightedItem { Value = 30, Weight = 0.05 },
+                new WeightedItem { Value = 20, Weight = 0.02 },
+                new WeightedItem { Value = 40, Weight = 0.03 },
+                new WeightedItem { Value = 50, Weight = 0.05 },
+                new WeightedItem { Value = 5, Weight = 0.05 },
+                new WeightedItem { Value = 35, Weight = 0.05 },
+                new WeightedItem { Value = 45, Weight = 0.05 },
+                new WeightedItem { Value = 55, Weight = 0.05 }
+            };
+            //for (var i = 0; i<100; i++)
+            //{
+            //    int randomValue = GetRandomValueByWeight(items);
+            //    Console.WriteLine(randomValue);
+            //}
+            //被评价的目标索引
+            List<List<int>> cworkDist = new List<List<int>>(xcount);
+            //被评价目标的次数或分数
+            //  List<List<int>> cworkCount = new List<List<int>>(xcount);
+            for (int i = 0; i < xcount; i++)
+            {
+                //乱序取10-20人作为评价目标
+                var vt = Enumerable.Range(0, scount).OrderBy(x => Random.Shared.Next()).Take(Random.Shared.Next(10, 21));
+                cworkDist.Add(vt.ToList());
+                //var counts = new List<int>();
+                //foreach (var v in vt)
+                //{
+                //    counts.Add(0);
+                //}
+                //cworkCount.Add(counts);
+            }
+
+            //被评价的目标索引
+            List<List<int>> rateDist = new List<List<int>>(pcount);
+            //被评价目标的次数或分数
+            //List<List<int>> rateCount = new List<List<int>>(pcount);
+            List<string> types = new List<string>();
+            for (int i = 0; i < pcount; i++)
+            {
+                //乱序取10-20人作为评价目标
+                var vt = Enumerable.Range(0, scount).OrderBy(x => Random.Shared.Next()).Take(Random.Shared.Next(10, 21));
+                rateDist.Add(vt.ToList());
+                // var counts  = new List<int>();
+                //foreach (var v in vt) 
+                //{
+                //    counts.Add(0);
+                //}
+                //rateCount.Add(counts);
+
+
+                var t = Random.Shared.Next(0, 3);
+                switch (true)
+                {
+                    case bool when t==0:
+                        types.Add("Voting");
+                        break;
+                    case bool when t==1:
+                        types.Add("GrandRating");
+                        break;
+                    case bool when t==2:
+                        types.Add("PeerAssessment");
+                        break;
+                }
+            }
+            for (var s = 0; s<scount; s++)
+            {
+                StudentLessonData student = new StudentLessonData()
+                {
+                    index=s,
+                    seatID=$"{s+1}",
+                    id=$"2024{(s+1).ToString("D3")}",
+                    groupId=$"{Random.Shared.Next(1, 5)}",
+                    attend=1,
+                    gscore= GetRandomValueByWeight(gpitems),
+                    pscore= GetRandomValueByWeight(gpitems),
+                    tscore= GetRandomValueByWeight(titems),
+                };
+                for (var p = 0; p<pcount; p++)
+                {
+                    student.rateingRecord.itemRecords.Add(new ItemRecord());
+                }
+                students.Add(student);
+            }
+            for (var s = 0; s<scount; s++)
+            {
+                var student = students[s];
+                //互动
+                for (var i = 0; i<icount; i++)
+                {
+                    int criterion = 10;
+                    var item = new ItemRecord { criterion=criterion };
+                    var w = Random.Shared.Next(0, 4);
+
+                    switch (true)
+                    {
+                        //未参与
+                        case bool when w==0:
+                            item.resultWeight= InteractWeight.T0;
+                            item.resultType= InteractReultType.T0;
+                            item.itemScore=0;
+                            break;
+                        //参与了
+                        case bool when w==1:
+                            item.resultWeight= InteractWeight.T1;
+                            item.resultType= InteractReultType.T1;
+                            item.itemScore=0;
+                            break;
+                        //部分正确
+                        case bool when w==2:
+                            var score = Random.Shared.Next(1, criterion);
+                            item.resultWeight= MinMaxNormalization(1, criterion, score, InteractWeight.T1, InteractWeight.TT);
+                            item.resultType= InteractReultType.TP;
+                            item.itemScore=0;
+                            break;
+                        //完全正确
+                        case bool when w==3:
+                            item.resultWeight= InteractWeight.TT;
+                            item.resultType= InteractReultType.TT;
+                            item.itemScore=criterion;
+                            break;
+                    }
+                    student.interactRecord.interactRecords.Add(item);
+                }
+                //任务
+                for (var t = 0; t<tcount; t++)
+                {
+                    var w = Random.Shared.Next(0, 2);
+                    var item = new ItemRecord { };
+                    switch (true)
+                    {
+                        //未参与
+                        case bool when w==0:
+                            item.resultWeight= InteractWeight.T0;
+                            item.resultType= InteractReultType.T0;
+                            item.itemScore=0;
+                            break;
+                        //参加
+                        case bool when w==1:
+                            item.resultWeight= InteractWeight.TT;
+                            item.resultType= InteractReultType.TT;
+                            item.itemScore=10;
+                            break;
+                    }
+                    student.taskRecord.taskRate= student.taskRecord.itemRecords.Where(x => x.resultWeight>0).Count()*1.0/tcount;
+                    student.taskRecord.itemRecords.Add(item);
+                }
+                //评价
+                for (var p = 0; p<pcount; p++)
+                {
+                    var item = student.rateingRecord.itemRecords[p];
+                    var subtype = string.Empty;
+                    item.itemType=types[p];
+                    if (types[p].Equals("PeerAssessment"))
+                    {
+                        var sub = Random.Shared.Next(0, 3);
+                        subtype=  sub==0 ? "ALL" : sub==1 ? "Two" : "Self";
+                    }
+                    var w = Random.Shared.Next(0, 3);
+                    switch (true)
+                    {
+                        //未参与
+                        case bool when w==0:
+                            item.resultWeight= InteractWeight.T0;
+                            item.resultType= InteractReultType.T0;
+                            item.itemScore=0;
+                            break;
+                        //参与
+                        case bool when w==1||w==2:
+                            item.resultWeight= InteractWeight.T1;
+                            item.resultType= InteractReultType.T1;
+
+                            if (item.itemType!.Equals("Voting"))
+                            {
+                                var index = Random.Shared.Next(0, rateDist[p].Count);
+                                //rateCount[p][index]+=1;
+                                students[rateDist[p][index]].rateingRecord.itemRecords[p].itemScore+=1;
+                            }
+                            else
+                            {
+                                if (item.itemType.Equals("PeerAssessment"))
+                                {
+                                    var index = Random.Shared.Next(0, rateDist[p].Count);
+                                    //操作次数
+                                    int opt_count = Random.Shared.Next(1, 2);
+                                    for (var count = 0; count<opt_count; count++)
+                                    {
+                                        var score = Random.Shared.Next(3, 10);
+                                        // rateCount[p][index]+=score;
+                                        students[rateDist[p][index]].rateingRecord.itemRecords[p].itemScore+=score;
+                                        item.optCount+= 1;
+                                    }
+                                }
+                                else
+                                {
+                                    var index = Random.Shared.Next(0, rateDist[p].Count);
+                                    var score = Random.Shared.Next(3, 10);
+                                    // rateCount[p][index]+=score;
+                                    students[rateDist[p][index]].rateingRecord.itemRecords[p].itemScore+=score;
+                                }
+                            }
+                            break;
+                    }
+                    // student.rateingRecord.itemRecords.Add(item);
+                }
+
+
+                //协作
+                for (var x = 0; x<xcount; x++)
+                {
+                    int[] r = new int[] { 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1 };
+                    var w = r[Random.Shared.Next(0, r.Length)];
+                    var item = new ItemRecord { };
+                    switch (true)
+                    {
+                        //未参与
+                        case bool when w==0:
+                            item.resultWeight= InteractWeight.T0;
+                            item.resultType= InteractReultType.T0;
+                            item.itemScore=0;
+                            break;
+                        //
+                        case bool when w==1:
+                            item.resultWeight= InteractWeight.TP;
+                            item.resultType= InteractReultType.TP;
+                            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 };
+                            item.itemScore=q[Random.Shared.Next(0, q.Count())];
+                            break;
+                    }
+                    student.coworkRecord.itemRecords.Add(item);
+                }
+                //评测
+                for (var e = 0; e<ecount; e++)
+                {
+                    StudentExamRecord examRecord = new();
+                    double allocation = 0;
+                    for (var q = 0; q<qcount; q++)
+                    {
+                        var criterion = Random.Shared.Next(2, 10);
+                        allocation+=criterion;
+                        var item = new ItemRecord { criterion =criterion };
+                        var w = Random.Shared.Next(0, 4);
+                        switch (true)
+                        {
+                            //未作答
+                            case bool when w==0:
+                                item.resultWeight= InteractWeight.T0;
+                                item.resultType= InteractReultType.T0;
+                                item.itemScore=0;
+                                break;
+                            //作答错误
+                            case bool when w==1:
+                                item.resultWeight= InteractWeight.T1;
+                                item.resultType= InteractReultType.T1;
+                                item.itemScore=0;
+                                break;
+                            //部分正确
+                            case bool when w==2:
+                                var score = Random.Shared.Next(1, criterion);
+                                item.resultWeight= MinMaxNormalization(1, criterion, score, InteractWeight.T1, InteractWeight.TT); // score * 1.0  / criterion* (InteractWeight.TT-InteractWeight.T1);
+                                item.resultType= InteractReultType.TP;
+                                item.itemScore=score;
+                                break;
+                            //完全正确
+                            case bool when w==3:
+                                item.resultWeight= InteractWeight.TT;
+                                item.resultType= InteractReultType.TT;
+                                item.itemScore=criterion;
+                                break;
+                        }
+                        examRecord.itemRecords.Add(item);
+                    }
+                    examRecord.qcount=qcount;
+                    examRecord.workCount= examRecord.itemRecords.Where(x => x.resultWeight>0).Count();
+                    examRecord.allocation=allocation;
+                    examRecord.score= examRecord.itemRecords.Where(x => x.itemScore>=0).Select(x => x.itemScore).Sum();//得分
+                    examRecord.scoreRate =  Math.Round(examRecord.score * 1.0 / allocation, 4);//得分率
+                    examRecord.answerRate= Math.Round(examRecord.itemRecords.Where(x => x.resultWeight>0).Count()*1.0/qcount, 4);//作答率
+                    student.examRecords.Add(examRecord);
+                }
+            }
+            for (var p = 0; p<pcount; p++)
+            {
+                var order = students.OrderByDescending(x => x.rateingRecord.itemRecords[p].itemScore);
+                var maxItems = students.FindAll(x => x.rateingRecord.itemRecords[p].itemScore==order.First().rateingRecord.itemRecords[p].itemScore);
+                var max = students.FindAll(x => x.rateingRecord.itemRecords[p].itemScore==order.First().rateingRecord.itemRecords[p].itemScore).First().rateingRecord.itemRecords[p].itemScore;
+                var min = students.FindAll(x => x.rateingRecord.itemRecords[p].itemScore==order.Last().rateingRecord.itemRecords[p].itemScore).First().rateingRecord.itemRecords[p].itemScore;
+                var sum = students.Sum(x => x.rateingRecord.itemRecords[p].itemScore);
+                foreach (var student in students)
+                {
+                    if (student.rateingRecord.itemRecords[p].itemScore>0  && student.rateingRecord.itemRecords[p].optCount>0)
+                    {
+                        student.rateingRecord.itemRecords[p].resultType=InteractReultType.TP;
+                        var data = MinMaxNormalization(min, max, student.rateingRecord.itemRecords[p].itemScore);
+                        student.rateingRecord.itemRecords[p].resultWeight=Math.Round(InteractWeight.T1+  data * 1.0  / 100 * (InteractWeight.TT-InteractWeight.T1), 4);
+                        if (maxItems.Select(x => x.seatID).Contains(student.seatID))
+                        {
+                            student.rateingRecord.itemRecords[p].resultType= InteractReultType.TT;
+                            student.rateingRecord.itemRecords[p].resultWeight= InteractWeight.TT;
+                        }
+                    }
+                }
+            }
+            for (var p = 0; p<xcount; p++)
+            {
+                var order = students.OrderByDescending(x => x.coworkRecord.itemRecords[p].itemScore);
+                var maxItems = students.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore);
+                var max = students.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
+                var min = students.FindAll(x => x.coworkRecord.itemRecords[p].itemScore==order.Last().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
+                var sum = students.Sum(x => x.coworkRecord.itemRecords[p].itemScore);
+                foreach (var student in students)
+                {
+                    if (student.coworkRecord.itemRecords[p].itemScore>0)
+                    {
+                        student.coworkRecord.itemRecords[p].resultType=InteractReultType.TP;
+                        var data = MinMaxNormalization(min, max, student.coworkRecord.itemRecords[p].itemScore);
+                        student.coworkRecord.itemRecords[p].resultWeight=Math.Round(InteractWeight.T1+  data * 1.0  / 100 * (InteractWeight.TT-InteractWeight.T1), 4);
+                        if (maxItems.Select(x => x.seatID).Contains(student.seatID))
+                        {
+                            student.coworkRecord.itemRecords[p].resultType= InteractReultType.TT;
+                            student.coworkRecord.itemRecords[p].resultWeight= InteractWeight.TT;
+                        }
+                    }
+                }
+            }
+            #endregion 数据模拟
+            string jsons = await System.IO.File.ReadAllTextAsync("F:\\lesson-local\\analysis.json");
+            LessonDataAnalysis lessonDataAnalysis = jsons.ToObject<LessonDataAnalysis>();
+            ProcessStudentData(students, lessonDataAnalysis, scount, ecount, qcount, icount, tcount, pcount, xcount);
+            try {
+                await System.IO.File.WriteAllTextAsync($"F:\\mock-data\\{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}.json", new { scount, ecount, qcount, icount, tcount, pcount, xcount, students }.ToJsonString());
+            } catch (Exception ex) {
+                Console.WriteLine(scount);
+            }
+            return Ok(new { scount, ecount, qcount, icount, tcount, pcount, xcount, students });
+        }
+
+        
+
+        private static void ProcessStudentData(List<StudentLessonData> studentLessonDatas, LessonDataAnalysis lessonDataAnalysis, int scount, int ecount, int qcount, int icount, int tcount, int pcount, int xcount)
+        {
+            //历史记录的个人计分集合,通过“2倍标准差规则”移除异常值后得到的集合
+            var max_q = lessonDataAnalysis.pscore.Max();
+            //历史记录的互动计分集合,通过“2倍标准差规则”移除异常值后得到的集合
+            var max_t = lessonDataAnalysis.tscore.Max();
+            //历史记录的小组计分集合,通过“2倍标准差规则”移除异常值后得到的集合
+            var max_h = lessonDataAnalysis.gscore.Max();
+            var j = InteractWeight.T1;
+            foreach (var studentLessonData in studentLessonDatas)
+            {
+                //互动成效指数
+                var a = 0.0;
+                //互动参与指数
+                var b = 0.0;
+                //c个人计分指数,d互动计分指数,e小组计分指数
+                double c = 0, d = 0, e = 0;
+                //课例互动次数
+                double n = studentLessonData.interactRecord.interactRecords.Count()*1.0;
+                //是IES大陆正式站历史课例数据,自2024-03-01至2024-10-08日,互动指数或学法指数黄灯或绿灯,不包含醍摩豆学校及测试学校,课例时长超过5分钟的有效课例(10,680笔数据) 的IRS互动+抢权+挑人的次数集合,
+                //通过“2倍标准差规则” 移除异常值后得到的集合,再通过K-Means聚类算法得到高低位阶互动频次两个集合,并根据当前课例互动次数位阶的集合的质心值,该值定为m值
+                var m = n<=lessonDataAnalysis.clustersInteract.First().Value.Max() ? lessonDataAnalysis.clustersInteract.First().Key*1.0 : lessonDataAnalysis.clustersInteract.Last().Key *1.0;
+                //学生作答次数
+                var w = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Count()*1.0;
+                //作答正确数(包括部分正确)
+                var r = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.T1).Count()*1.0;
+                //有参与的权重集合60≤k(x)≤100
+                var kw = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Sum(x => x.resultWeight*1.0);
+                //有得分的权重集合60<e(x)≤100
+                var er = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.T1).Sum(x => x.resultWeight*1.0);
+                //本节课的所有互动计分
+                var i = studentLessonData.interactRecord.interactRecords.Sum(x => x.itemScore*1.0);
+                //本节课教师手动给学生的个人计分
+                var s = studentLessonData.pscore;
+                //个人计分指数
+                c = s*1.0/max_q;
+                //互动计分指数
+                d = i*1.0/max_t;
+                //互动成效指数
+                a = (d+w*kw/(j*m)+r*er/(j*m))*1.0/n;
+                //互动参与指数
+                b = ((w*w)/m+(r*r)/m)*1.0/n;
+                //c+a= 个人计分指数+ 个人互动成效指数
+                var f = Math.Round(190*1.0/(1+Math.Exp(-(c+a)))-95, 4);
+                studentLessonData.achieve=f;
+                Console.WriteLine($"{studentLessonData.id}=>成效:{f}\t互动次数:{n}\t参与次数:{w}\t正确次数:{r}\t个人计分:{s}\t{Math.Round(c,2)}\t互动计分:{i}\t{Math.Round(d,2)},\t学习成效:{Math.Round(a,2)}");// kw:{Math.Round(kw,2)}\t er:{Math.Round(er,2)}
+            }
+        }
+
+        private static int GetRandomValueByWeight(List<WeightedItem> items)
+        {
+            Random random = new Random();
+            double randomWeight = random.NextDouble();
+            double cumulativeWeight = 0.0;
+
+            foreach (var item in items)
+            {
+                cumulativeWeight += item.Weight;
+                if (randomWeight <= cumulativeWeight)
+                {
+                    return item.Value;
+                }
+            }
+
+            // This should not happen if all weights sum up to 1
+            return items[items.Count - 1].Value;
+        }
+        private static double MinMaxNormalization(double min, double max, double x, double minRank = 1, double maxRank = 100)
+        {
+            //排名指数计算=( 当前值分数- 298) / (9992 - 298) * (99 - 60) + 60
+            //将每个人的积分转化为60-100
+            //排名 = (积分 - 最低积分) / (最高积分 - 最低积分) * (最大排名 - 最小排名) + 最小排名
+            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);
+        }
+    }
+    class WeightedItem
+    {
+        public int Value { get; set; }
+        public double Weight { get; set; }
+    }
+}

+ 1 - 0
TEAMModelOS.Extension/HTEX.Test/HTEX.Test.csproj

@@ -7,6 +7,7 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="Bogus" Version="35.6.1" />
     <PackageReference Include="Microsoft.ML" Version="3.0.1" />
   </ItemGroup>
 

+ 20 - 4
TEAMModelOS.Extension/HTEX.Test/Program.cs

@@ -1,15 +1,22 @@
 using Azure;
+using Bogus;
 using HTEX.Test.Service;
 using MathNet.Numerics;
+using System;
 using System.Configuration;
 using System.Diagnostics;
+using System.IO;
 using System.Linq;
+using System.Reflection;
 using System.Text.RegularExpressions;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.Student;
 using static HTEX.Test.Controllers.LessonRecordController;
+using static Microsoft.Azure.Amqp.Serialization.SerializableType;
+using static System.Runtime.InteropServices.JavaScript.JSType;
 namespace HTEX.Test
 {
     public class Program
@@ -107,14 +114,14 @@ namespace HTEX.Test
 
         public static string Test()
         {
-
-            string jsons =   System.IO.File.ReadAllText( $"F:\\lesson-local\\anlysis.json");
-            LessonDataAnlysis lessonDataAnlysis = jsons.ToObject<LessonDataAnlysis>();
+             
+            string jsons =   System.IO.File.ReadAllText( $"F:\\lesson-local\\analysis.json");
+            LessonDataAnalysis lessonDataAnlysis = jsons.ToObject<LessonDataAnalysis>();
             var n = 5;
             //聚类分数量大和数量小的类群。判断当前出题数在两个类群的最大范围内,再取其质心。
             var m = n<=lessonDataAnlysis.clustersInteract.First().Value.Max() ? lessonDataAnlysis.clustersInteract.First().Value: lessonDataAnlysis.clustersInteract.Last().Value;
             var persent = GetPersent(lessonDataAnlysis.interactNormal, n);
-            Console.WriteLine(persent);
+            //Console.WriteLine(persent);
             return "Hello World!";
         }
 
@@ -138,6 +145,10 @@ namespace HTEX.Test
 
             return anomalies;
         }
+
+       
+       
+        
         /// <summary>
         /// 计算当前元素在集合中超过了多少百分比的值
         /// </summary>
@@ -171,5 +182,10 @@ namespace HTEX.Test
             public int count { get; set;}
             public int key { get; set;}
         }
+        class WeightedItem
+        {
+            public int Value { get; set; }
+            public double Weight { get; set; }
+        }
     }
 }

+ 2 - 1
TEAMModelOS.SDK/Extension/JsonExtensions.cs

@@ -33,7 +33,8 @@ namespace TEAMModelOS.SDK.Extension
             if (option == null) {
                 option = new System.Text.Json.JsonSerializerOptions
                 {
-                    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+                    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
+                 
                 };
             }
             var json = JsonSerializer.Serialize(obj, option);

+ 21 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs

@@ -544,6 +544,19 @@ namespace TEAMModelOS.SDK.Models
         /// 协作能力
         /// </summary>
         public double cowork { get; set; }
+
+        /// <summary>
+        /// 个人计分
+        /// </summary>
+        public double pscore { get; set; }
+        /// <summary>
+        /// 小组计分
+        /// </summary>
+        public double gscore {  get; set; }
+        /// <summary>
+        /// 互动计分
+        /// </summary>
+        public double tscore { get; set; }
     }
     public class StudentRateingRecord
     {
@@ -641,6 +654,10 @@ namespace TEAMModelOS.SDK.Models
         /// 每个题的得分情况
         /// </summary>
         public List<ItemRecord> itemRecords /*{ get; set; }*/ = new List<ItemRecord>();
+
+        public double allocation { get; set; }
+        public double workCount { get; set; }
+        public double qcount { get; set; }
     }
 
     public class ItemRecord
@@ -670,6 +687,10 @@ namespace TEAMModelOS.SDK.Models
         /// 是否是小组类型的
         /// </summary>
         public bool isGroup { get; set;}
+        /// <summary>
+        /// 当前任务操作次数。一般为一次,智慧评分,在互评的时候可能会被分配多个作品,会评论多次。
+        /// </summary>
+        public int optCount { get; set; } = 1;
     }
     public static class InteractReultType
     {