CrazyIter_Bin hai 6 meses
pai
achega
e6426bbe2b

+ 81 - 63
HTEX.DataETL/Controllers/LessonRecordController.cs

@@ -18,6 +18,7 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Helper.Common.FileHelper;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
 
@@ -164,29 +165,7 @@ namespace HTEX.DataETL.Controllers
             return Ok();
         }
 
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="json"></param>
-        /// <returns></returns>
-        [HttpPost("process-fix-history-students")]
-        public async Task<IActionResult> ProcessFixHistoryStudents(JsonElement json)
-        {
-            string? pathAnalysis = $"F:\\lesson-local\\analysis";
-            try
-            {
-                string jsons = await System.IO.File.ReadAllTextAsync($"F:\\lesson-local\\analysis\\analysis-model.json");
-                var s = JsonSerializer.Deserialize<LessonDataAnalysisModel>(jsons);
-                LessonDataAnalysisModel lessonDataAnalysis = JsonDocument.Parse(jsons).RootElement.ToObject<LessonDataAnalysisModel>();
-                var per = LessonETLService.GetPersent(lessonDataAnalysis.irs, 2);
-
-            }
-            catch (Exception ex)
-            {
-                Console.WriteLine(ex.ToString());
-            }
-            return Ok();
-        }
+        
         /// <summary>
         /// 
         /// </summary>
@@ -201,6 +180,7 @@ namespace HTEX.DataETL.Controllers
             string jsons = await System.IO.File.ReadAllTextAsync($"{pathAnalysis}\\analysis-model.json");
             LessonDataAnalysisModel lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisModel>();
             List<string> filesLessons = FileHelper.ListAllFiles(pathLessons, "-local.json");
+            List<string> filesStudata = FileHelper.ListAllFiles(pathLessons, "-sdata.json");
             var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
             XmlDocument xmlDocument = new XmlDocument();
             xmlDocument.Load($"{runtimePath}\\summary.xml");
@@ -212,17 +192,19 @@ namespace HTEX.DataETL.Controllers
                 string lessonId = file.Split("\\").Last().Replace("-local.json", "");
                 localIds.Add(lessonId);
             }
+            List<LessonLocal> lessonLocals = new List<LessonLocal>();
+            
             List<LessonRecord> lessonRecords = new List<LessonRecord>();
             string recordsPtah = $"{lessonBasePath}\\records\\records.json";
             long stime = 0;//2023-09-01 00:00:00
             long etime = 0;//2024-11-13 23:59:59
-            if (System.IO.File.Exists(recordsPtah))
-            {
-                string jsonData = await System.IO.File.ReadAllTextAsync(recordsPtah);
-                lessonRecords= jsonData.ToObject<List<LessonRecord>>();
-                stime= lessonRecords.Max(x => x.startTime);
-                etime= lessonRecords.Max(x => x.startTime);
-            }
+            //if (System.IO.File.Exists(recordsPtah))
+            //{
+            //    string jsonData = await System.IO.File.ReadAllTextAsync(recordsPtah);
+            //    lessonRecords= jsonData.ToObject<List<LessonRecord>>();
+            //    stime= lessonRecords.Max(x => x.startTime);
+            //    etime= lessonRecords.Max(x => x.startTime);
+            //}
             if (stime==0) 
             {
                 stime = 1693497600000;//2023-09-01 00:00:00
@@ -231,31 +213,39 @@ namespace HTEX.DataETL.Controllers
             {
                 etime = 1731513599000;//2024-11-13 23:59:59
             }
-            var resultSchools = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
-                 .GetList<LessonRecord>($"SELECT value c FROM   c  where  ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>{stime} and c.startTime<{etime} and   c.expire<=0  and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ");
+            List<LessonLocal> locals=  await LessonETLService.FixLocalData(localIds, _azureCosmos, _azureStorage, pathLessons, stime, etime);
+            if (locals.IsNotEmpty()) 
+            {
+                lessonLocals.AddRange(locals);
+            }
+
+            int u = 0;
+            Parallel.ForEach(filesLessons, file =>
+            {
+                string jsonp = System.IO.File.ReadAllText(file);
+                var lessonLocal = jsonp.ToObject<LessonLocal>();
+                if (lessonLocal.lessonBase!=null && lessonLocal.lessonBase.student.IsNotEmpty())
+                {
+                    lessonLocals.Add(lessonLocal);
+                }
+                else
+                {
+                    System.IO.File.Delete(file);
+                    System.IO.File.Delete(file.Replace("-local.json", "-count.json"));
+                    u++;
+                }
+            });
             List<string> ignore = new List<string>() { "PgJump", "PgRcv", "PgAdd" };
-            int index = 0;
-            if (resultSchools.list.IsNotEmpty()) 
+            if (lessonLocals.IsNotEmpty()) 
             {
-                lessonRecords.AddRange(resultSchools.list);
+                lessonRecords=lessonLocals.Where(x => x.lessonRecord.scope.Equals("school")).Select(x =>x.lessonRecord).ToList();
             }
             if (lessonRecords.IsNotEmpty())
             {
-                
                 await System.IO.File.WriteAllTextAsync(recordsPtah, lessonRecords.ToJsonString());
                 List<StudentSemesterRecord>  studentSemesterRecords= new List<StudentSemesterRecord>();
                 List<OverallEducation> overallEducations= new List<OverallEducation>();
                 List<Student> studentsBase = new List<Student>();
-                List<LessonLocal>lessonLocals = new List<LessonLocal>();
-                foreach (var lessonRecord in lessonRecords) 
-                {
-                    var item = await LessonETLService.GetLessonLocal(lessonRecord, localIds, _azureStorage, pathLessons);
-                    lessonLocals.Add(item);
-                    string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
-                    await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json", item.ToJsonString());
-                    index++;
-                }
-              
                 string schoolPtah = $"{lessonBasePath}\\schools\\school.json";
                 if (System.IO.File.Exists(schoolPtah))
                 {
@@ -349,9 +339,18 @@ namespace HTEX.DataETL.Controllers
                 }
                 
                 //List<(string id,string owner, List<StudentLessonData> studentLessonData)> studentLessonDatas= new List<(string id, string owner, List<StudentLessonData>)>();
-                ConcurrentQueue<(string id, string owner, List<StudentLessonItem> studentLessons,List<CodeBool> codeBools, List<StudentLessonData> studentLessonData)> lessonItems = new ConcurrentQueue<(string id, string owner, List<StudentLessonItem> studentLessons, List<CodeBool> codeBools, List<StudentLessonData> studentLessonData)>();
+                ConcurrentQueue<LessonStudentResult> lessonItems = new ConcurrentQueue<LessonStudentResult>();
+                int v = 0;
+                Parallel.ForEach(filesStudata, file =>
+                {
+                    string jsonp = System.IO.File.ReadAllText(file);
+                    var studentResult = jsonp.ToObject<LessonStudentResult>();
+                    lessonItems.Enqueue(studentResult);
+                    v++;
+                });
+
                 int n = 0;
-              
+                lessonLocals= lessonLocals.ExceptBy(lessonItems.Select(x => x.id), y => y.lessonRecord.id).ToList();
                 Parallel.ForEach(lessonLocals, (item, con) =>
                 {
                     try
@@ -361,7 +360,10 @@ namespace HTEX.DataETL.Controllers
                         {
                             string owner = item.lessonRecord.scope.Equals("school") ? item.lessonRecord.school : item.lessonRecord.tmdid;
                             //studentLessonDatas.Add((item.lessonRecord.id, owner, studata.studentLessonDatas));
-                            lessonItems.Append((item.lessonRecord.id, owner, studata.lessonItems, studata.codeBools, studata.studentLessonDatas));
+                            LessonStudentResult result = new LessonStudentResult { id= item.lessonRecord.id, owner= owner, studentLessons= studata.lessonItems, codeBools= studata.codeBools, lessonDatas= studata.studentLessonDatas };
+                            string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
+                            System.IO.File.WriteAllText($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-sdata.json", item.ToJsonString());
+                            lessonItems.Enqueue(result);
                         }
                     }
                     catch (Exception ex)
@@ -391,7 +393,7 @@ namespace HTEX.DataETL.Controllers
                 var grpdata = studentSemesterRecords.GroupBy(x => x.code).Select(x => new { key = x.Key, list = x.ToList() });
                 foreach (var group in grpdata)
                 {
-                    var pages = group.list.Page(200);
+                    var pages = group.list.Page(100);
                    
                     foreach (var page in pages)
                     {
@@ -408,7 +410,7 @@ namespace HTEX.DataETL.Controllers
                 var gpover = overallEducations.GroupBy(x => x.code).Select(x => new { key = x.Key, list = x.ToList() });
                 foreach (var item in gpover)
                 {
-                    var pages = item.list.Page(200);
+                    var pages = item.list.Page(100);
                     foreach (var page in pages)
                     {
                         List<Task<ItemResponse<OverallEducation>>> list = new();
@@ -435,12 +437,13 @@ namespace HTEX.DataETL.Controllers
                     summaryes.Add(summary);
                 }
                 await Parallel.ForEachAsync(lessonItems, async (lessonItem, _) => {
-                    await _azureStorage.GetBlobContainerClient(lessonItem.owner).UploadFileByContainer(lessonItem.studentLessonData.ToJsonString(), "records", $"{lessonItem.id}/student-analysis.json");
+                    await _azureStorage.GetBlobContainerClient(lessonItem.owner).UploadFileByContainer(lessonItem.lessonDatas.ToJsonString(), "records", $"{lessonItem.id}/student-analysis.json");
                     await LessonETLService.ExportToExcelAzureBlob(lessonItem.studentLessons, _azureStorage, lessonItem.owner, $"{lessonItem.id}/student-analysis.xlsx", xmlDocument, summaryes, properties);
                     p++;
                 });
+                return Ok(new { p, m, k,n,u});
             }
-            return Ok();
+            return Ok(new {});
         }
 
         
@@ -516,28 +519,43 @@ namespace HTEX.DataETL.Controllers
                 List<TechCount> techCounts = new List<TechCount>();
                 filesLessons = FileHelper.ListAllFiles(pathLessons, "-local.json");
 
-                stopwatch.Start();
+              
                 List<LessonLocal> lessonLocals = new List<LessonLocal>();
-                Parallel.ForEach(filesLessons, file =>
+                int u = 0;
+                if (force) 
                 {
-                    string jsonp = System.IO.File.ReadAllText(file);
-                    var lessonLocal = jsonp.ToObject<LessonLocal>();
-                    lessonLocals.Add(lessonLocal);
-                });
-                stopwatch.Stop();
+                    stopwatch.Start();
+                     Parallel.ForEach(filesLessons, file =>
+                    {
+                        string jsonp =   System.IO.File.ReadAllText(file);
+                        var lessonLocal = jsonp.ToObject<LessonLocal>();
+
+                        if (lessonLocal.lessonBase!=null && lessonLocal.lessonBase.student.IsNotEmpty())
+                        {
+                            lessonLocals.Add(lessonLocal);
+                        }
+                        else
+                        {
+                            System.IO.File.Delete(file);
+                            System.IO.File.Delete(file.Replace("-local.json", "-count.json"));
+                            u++;
+                        }
+                    });
+                    stopwatch.Stop();
+                }
                 _logger.LogInformation($"Loaded {lessonLocals.Count} lessons in {stopwatch.Elapsed.TotalSeconds} seconds");
+                int  index = 0;
                 await Parallel.ForEachAsync(filesLessons, async (item, _) => {
-                    TechCount techCount=  await  LessonETLService.GetTeachCount(_azureCosmos, item, pathLessons, ignore, Constant.objectiveTypes, _azureStorage, force);
+                    TechCount techCount=  await  LessonETLService.GetTeachCount(_azureCosmos, item, pathLessons, ignore, Constant.objectiveTypes, _azureStorage, force, lessonLocals);
                     if (techCount != null) {
                         techCounts.Add(techCount);
                     }
+                    index++;
                 });
                 long newest = lessonLocals.Max(x=>x.lessonRecord.startTime);
                 await LessonETLService.GenAnalysisData(pathAnalysis, newest, techCounts,_azureStorage);
             }
             return Ok(new {   });
         }
-
-
     }
 }

+ 144 - 316
TEAMModelOS.Extension/HTEX.Lib/ETL/Lesson/LessonETLService.cs

@@ -37,41 +37,41 @@ namespace HTEX.Lib.ETL.Lesson
     public class LessonETLService
     {
 
-        public static async Task<List<LessonLocal>> FixLocalData(List<string> localIds, AzureCosmosFactory _azureCosmos, AzureStorageFactory _azureStorage, string pathLessons,long  stime,long etime)
+        public static async Task<List<LessonLocal>> FixLocalData(List<string> localIds, AzureCosmosFactory _azureCosmos, AzureStorageFactory _azureStorage, string pathLessons, long stime, long etime)
         {
-            if (etime<=1693497600000) 
+            if (etime<=1693497600000)
             {
                 etime= DateTimeOffset.Now.ToUnixTimeMilliseconds();
             }
-            
-            List<string> dbids= new List<string>();
+
+            List<string> dbids = new List<string>();
             var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
-                   .GetList<string>($"SELECT value c.id FROM   c  where   ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime} and c.startTime<{etime} and c.expire<=0  and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", null);
+                   .GetList<string>($"SELECT value c.id FROM   c  where   ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime} and c.startTime<{etime}     and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", null);
             if (resultSchool.list.IsNotEmpty())
             {
                 dbids.AddRange(resultSchool.list);
             }
             var resultTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
-                   .GetList<string>($"SELECT value c.id FROM   c  where   ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime} and c.startTime<{etime}  and c.expire<=0  and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", "LessonRecord");
+                   .GetList<string>($"SELECT value c.id FROM   c  where   ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime} and c.startTime<{etime}     and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", "LessonRecord");
             if (resultTeacher.list.IsNotEmpty())
             {
                 dbids.AddRange(resultTeacher.list);
             }
-            var newIds=  dbids.Except(localIds);
-            List<LessonRecord> list=new List<LessonRecord>();
-            if (newIds!=null  && newIds.Count()>0) 
+            var newIds = dbids.Except(localIds);
+            List<LessonRecord> list = new List<LessonRecord>();
+            if (newIds!=null  && newIds.Count()>0)
             {
                 var resultSchoolLessons = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
-                  .GetList<LessonRecord>($"SELECT value c.id FROM   c  where  c.id in ({string.Join(",",newIds.Select(x=>$"'{x}'"))}) and    ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime} and c.startTime<{etime}  and c.expire<=0  and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", null);
+                  .GetList<LessonRecord>($"SELECT value c FROM   c  where  c.id in ({string.Join(",", newIds.Select(x => $"'{x}'"))}) and    ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime} and c.startTime<{etime}    and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", null);
                 if (resultSchoolLessons.list.IsNotEmpty())
                 {
                     list.AddRange(resultSchoolLessons.list);
                     newIds= newIds.Except(resultSchoolLessons.list.Select(x => x.id));
                 }
-                if (newIds!=null && newIds.Count()>0) 
+                if (newIds!=null && newIds.Count()>0)
                 {
                     var resultTeacherLessons = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
-                  .GetList<LessonRecord>($"SELECT value c.id FROM   c  where  c.id in ({string.Join(",", newIds.Select(x => $"'{x}'"))}) and    ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime}  and c.startTime<{etime}  and c.expire<=0  and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", "LessonRecord");
+                  .GetList<LessonRecord>($"SELECT value c FROM   c  where  c.id in ({string.Join(",", newIds.Select(x => $"'{x}'"))}) and    ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and  c.startTime>={stime}  and c.startTime<{etime}    and c.status<>404  and c.duration>300 and c.pk='LessonRecord' ", "LessonRecord");
                     if (resultTeacherLessons.list.IsNotEmpty())
                     {
                         list.AddRange(resultTeacherLessons.list);
@@ -79,18 +79,32 @@ namespace HTEX.Lib.ETL.Lesson
                 }
             }
             List<LessonLocal> lessonLocals = new List<LessonLocal>();
-            foreach (var record in list) 
+            foreach (var record in list)
             {
-                var item = await LessonETLService.GetLessonLocal(record, localIds, _azureStorage, pathLessons);
-                string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
-                item.lessonRecord.learningCategory= item.lessonBase?.summary?.learningCategory;
-                if (item.lessonRecord.learningCategory == null)
+                LessonLocal item = await LessonETLService.GetLessonLocal(record, localIds, _azureStorage, pathLessons);
+                if (item.lessonBase!=null && item.lessonBase.student.IsNotEmpty())
                 {
+                    string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
+                    item.lessonRecord.learningCategory= item.lessonBase?.summary?.learningCategory;
+                    if (item.lessonRecord.learningCategory == null)
+                    {
 
-                    item.lessonRecord.learningCategory = new LearningCategory();
+                        item.lessonRecord.learningCategory = new LearningCategory();
+                    }
+                    await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json", item.ToJsonString());
+                    lessonLocals.Add(item);
+                }
+                else {
+                    record.analysis=-1;
+                    if (record.scope.Equals("school"))
+                    {
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(record, new PartitionKey(record.code));
+                    }
+                    else
+                    {
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(record, new PartitionKey(record.code));
+                    }
                 }
-                await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json", item.ToJsonString());
-                lessonLocals.Add(item);
             }
             return lessonLocals;
         }
@@ -113,7 +127,7 @@ namespace HTEX.Lib.ETL.Lesson
             // This should not happen if all weights sum up to 1
             return items[items.Count - 1].Value;
         }
-        public static List<CodeBool> GetCodeBools (List<StudentLessonData> studentLessonDatas) {
+        public static List<CodeBool> GetCodeBools(List<StudentLessonData> studentLessonDatas) {
             List<CodeBool> codeBools = new List<CodeBool>() {
                 new CodeBool { code="hd",value=false },//互动
                 new CodeBool { code="pc",value=false },//评测
@@ -170,7 +184,7 @@ namespace HTEX.Lib.ETL.Lesson
                         codeBools.Find(x => x.code.Equals("xzxz"))!.value=true;
                     }
                 }
-                if (studentLessonData.pickups.FindAll(x => x.Contains("grp", StringComparison.OrdinalIgnoreCase)).IsNotEmpty()) 
+                if (studentLessonData.pickups.FindAll(x => x.Contains("grp", StringComparison.OrdinalIgnoreCase)).IsNotEmpty())
                 {
                     codeBools.Find(x => x.code.Equals("xztr"))!.value=true;
                 }
@@ -189,20 +203,14 @@ namespace HTEX.Lib.ETL.Lesson
         /// <param name="azureStorage"></param>
         /// <param name="lessonLocal"></param>
         /// <returns></returns>
-        public static   (List<StudentLessonData> studentLessonDatas, List<StudentLessonItem> lessonItems, List<CodeBool> codeBools)
-            DoStudentLessonDataV2(List<string> objectiveTypes,  LessonLocal lessonLocal,   string location,  List<StudentSemesterRecord> studentSemesterRecords, List<OverallEducation> overallEducations,
+        public static (List<StudentLessonData> studentLessonDatas, List<StudentLessonItem> lessonItems, List<CodeBool> codeBools)
+            DoStudentLessonDataV2(List<string> objectiveTypes, LessonLocal lessonLocal, string location, List<StudentSemesterRecord> studentSemesterRecords, List<OverallEducation> overallEducations,
             LessonDataAnalysisModel lessonDataAnalysis, List<Student> studentsBase, List<School> schools)
         {
-            List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
-            studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
-            studentLessonDatas = LessonETLService.GetIRSData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.irsDatas, studentLessonDatas, lessonLocal.examDatas, lessonLocal?.lessonRecord?.id);
-            studentLessonDatas =  LessonETLService.GetCoworkData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.coworkDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-            studentLessonDatas =  LessonETLService.GetExamData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.examDatas, studentLessonDatas, objectiveTypes, lessonLocal.lessonRecord.id);
-            studentLessonDatas = LessonETLService.GetSmartRatingData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.smartRatingDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-            studentLessonDatas = LessonETLService.GetTaskData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.taskDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-            var pickupData = LessonETLService.GetPickupData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, studentLessonDatas, lessonLocal.lessonRecord.id);
-            studentLessonDatas= pickupData.studentLessonDatas;
-            var codeBools = GetCodeBools(studentLessonDatas);
+
+            var studata = GenStudentLessonData(lessonLocal, objectiveTypes);
+            var codeBools = studata.codeBools;
+            List<StudentLessonData> studentLessonDatas = studata.studentLessonDatas;
             List<StudentLessonItem> lessonItems = new List<StudentLessonItem>();
             string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
             if (codeBools.FindAll(x => x.value).IsNotEmpty())
@@ -225,7 +233,7 @@ namespace HTEX.Lib.ETL.Lesson
                                 StudentSemesterRecord studentSemester = studentSemesterRecords.Find(x => x.id.Equals($"{pre_id}-{studentLessonData.id}") && x.code.Equals(code));
                                 if (studentSemester==null)
                                 {
- 
+
                                     studentSemester= new StudentSemesterRecord
                                     {
                                         id= $"{pre_id}-{studentLessonData.id}",
@@ -238,7 +246,7 @@ namespace HTEX.Lib.ETL.Lesson
                                         period= period?.id,
                                         pk="StudentSemesterRecord"
                                     };
- 
+
                                     studentSemesterRecords.Add(studentSemester);
                                 }
 
@@ -315,7 +323,7 @@ namespace HTEX.Lib.ETL.Lesson
                                         }
                                     }
                                 }
-                               
+
                                 string oid = $"{semester.studyYear}-{semester.currSemester.id}-{studentSemester.stuid}";
                                 string ocode = $"OverallEducation-{school.id}";
 
@@ -374,13 +382,14 @@ namespace HTEX.Lib.ETL.Lesson
                                         }
                                     }
                                     else {
-                                        var lesData=  overallEducation.les.Find(x => x.id.Equals(lessonLocal.lessonRecord.id));
+                                        overallEducation.lessonScore.RemoveAll(x => x.lessonId.Equals(lessonLocal.lessonRecord.id));
+                                        var lesData = overallEducation.les.Find(x => x.id.Equals(lessonLocal.lessonRecord.id));
                                         if (lesData== null)
                                         {
                                             overallEducation.les.Add(new StuLesson { id=lessonLocal.lessonRecord.id, attend=0, time = lessonLocal.lessonRecord.startTime });
                                         }
                                     }
-                                   
+
                                 }
                             }
                         }
@@ -390,17 +399,17 @@ namespace HTEX.Lib.ETL.Lesson
             return (studentLessonDatas, lessonItems, codeBools);
         }
 
-      public static async Task GenAnalysisData(string pathAnalysis, long newest, List<TechCount> techCounts,AzureStorageFactory azureStorage)
+        public static async Task GenAnalysisData(string pathAnalysis, long newest, List<TechCount> techCounts, AzureStorageFactory azureStorage)
         {
             var yearMonthDatas = techCounts.GroupBy(x => x.yearMonth).Select(x => new { key = x.Key, list = x.ToList() });
             // lessonDataAnalysisMonths = new List<LessonDataAnalysisMonth>();
             LessonDataAnalysisCluster lessonDataAnalysisCluster = new LessonDataAnalysisCluster();
             foreach (var yearMonthData in yearMonthDatas)
             {
-                if (string.IsNullOrWhiteSpace(yearMonthData.key))
-                {
-                    Console.WriteLine(yearMonthData.list.Select(x => x.lessonId).ToJsonString());
-                }
+                //if (string.IsNullOrWhiteSpace(yearMonthData.key))
+                //{
+                //   // Console.WriteLine(yearMonthData.list.Select(x => x.lessonId).ToJsonString());
+                //}
                 LessonDataAnalysisMonth lessonDataAnalysisMonth = new LessonDataAnalysisMonth() { updateTime= newest, yearMonth= yearMonthData.key };
                 lessonDataAnalysisMonth.pscore  = yearMonthData.list.SelectMany(x => x.pscore).ToList();
                 lessonDataAnalysisMonth.tscore  = yearMonthData.list.SelectMany(x => x.tscore).ToList();
@@ -410,7 +419,7 @@ namespace HTEX.Lib.ETL.Lesson
                 lessonDataAnalysisMonth.task = yearMonthData.list.Where(x => x.taskCount > 0).Select(x => (double)x.taskCount).ToList();
                 lessonDataAnalysisMonth.stuCowork=yearMonthData.list.SelectMany(x => x.stuCowork).ToList();
                 lessonDataAnalysisMonth.groupCowork=yearMonthData.list.SelectMany(x => x.groupCowork).ToList();
-                lessonDataAnalysisMonth.pickup=  yearMonthData.list.Where(x => x.pickup.Count()>0).Select(x=>x.pickup).ToList();
+                lessonDataAnalysisMonth.pickup=  yearMonthData.list.Where(x => x.pickup.Count()>0).Select(x => x.pickup).ToList();
                 System.IO.File.WriteAllText(Path.Combine(pathAnalysis, $"{yearMonthData.key}-m-analysis.json"), lessonDataAnalysisMonth.ToJsonString());
                 // lessonDataAnalysisMonths.Add( lessonDataAnalysisMonth);
                 if (lessonDataAnalysisMonth.task.IsNotEmpty())
@@ -518,7 +527,7 @@ namespace HTEX.Lib.ETL.Lesson
             //await azureStorage.GetBlobContainerClient("0-public").UploadFileByContainer(lessonDataAnalysisCluster.ToJsonString(), "lesson", $"analysis/analysis.json");
             //System.IO.File.WriteAllText(Path.Combine(pathAnalysis, "analysis.json"), lessonDataAnalysisCluster.ToJsonString());
             LessonDataAnalysisModel analysisModel = new LessonDataAnalysisModel();
-            analysisModel.task= lessonDataAnalysisCluster.task.GroupBy(x =>Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
+            analysisModel.task= lessonDataAnalysisCluster.task.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
             analysisModel.irs= lessonDataAnalysisCluster.irs.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
             analysisModel.interactNormal= lessonDataAnalysisCluster.interactNormal.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
             analysisModel.pscore= lessonDataAnalysisCluster.pscore.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
@@ -535,9 +544,9 @@ namespace HTEX.Lib.ETL.Lesson
             await azureStorage.GetBlobContainerClient("0-public").UploadFileByContainer(analysisModel.ToJsonString(), "lesson", $"analysis/analysis-model.json");
             System.IO.File.WriteAllText(Path.Combine(pathAnalysis, "analysis-model.json"), analysisModel.ToJsonString());
         }
-        public static async Task<TechCount>  GenTeachCount(LessonLocal lessonLocal, AzureStorageFactory azureStorage, List<string> objectiveTypes, List<string> ignore,string pathLessons,AzureCosmosFactory azureCosmos)
+        public static async Task<TechCount> GenTeachCount(LessonLocal lessonLocal, AzureStorageFactory azureStorage, List<string> objectiveTypes, List<string> ignore, string pathLessons, AzureCosmosFactory azureCosmos)
         {
-            var data = GenStudentLessonData(lessonLocal,objectiveTypes);
+            var data = GenStudentLessonData(lessonLocal, objectiveTypes);
             string yearMonth = DateTimeOffset.FromUnixTimeMilliseconds(lessonLocal.lessonRecord.startTime).ToString("yyyyMM");
             if (data.codeBools.FindAll(x => x.value).IsNotEmpty())
             {
@@ -624,6 +633,7 @@ namespace HTEX.Lib.ETL.Lesson
                         }
                         string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
                         await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-count.json", count.ToJsonString());
+                        return count;
                     }
                 }
             }
@@ -649,9 +659,9 @@ namespace HTEX.Lib.ETL.Lesson
                 }
                 catch (Exception ex) { }
             }
-            return null; 
+            return null;
         }
-        public static (List<StudentLessonData> studentLessonDatas, List<CodeBool> codeBools,List<string> pickup) GenStudentLessonData(LessonLocal lessonLocal, List<string> objectiveTypes)
+        public static (List<StudentLessonData> studentLessonDatas, List<CodeBool> codeBools, List<string> pickup) GenStudentLessonData(LessonLocal lessonLocal, List<string> objectiveTypes)
         {
             List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
             studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
@@ -663,7 +673,7 @@ namespace HTEX.Lib.ETL.Lesson
             var pickupData = LessonETLService.GetPickupData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, studentLessonDatas, lessonLocal.lessonRecord.id);
             studentLessonDatas= pickupData.studentLessonDatas;
             var codeBools = LessonETLService.GetCodeBools(studentLessonDatas);
-            return (studentLessonDatas,codeBools, pickupData.pickup);
+            return (studentLessonDatas, codeBools, pickupData.pickup);
         }
 
         /// <summary>
@@ -677,14 +687,14 @@ namespace HTEX.Lib.ETL.Lesson
         /// <param name="azureStorage"></param>
         /// <param name="force"></param>
         /// <returns></returns>
-        public static async Task<TechCount> GetTeachCount(AzureCosmosFactory azureCosmos, string item, string pathLessons, List<string> ignore, List<string> objectiveTypes, AzureStorageFactory azureStorage, bool force)
+        public static async Task<TechCount> GetTeachCount(AzureCosmosFactory azureCosmos, string item, string pathLessons, List<string> ignore, List<string> objectiveTypes, AzureStorageFactory azureStorage, bool force, List<LessonLocal> lessonLocals)
         {
-            List<TechCount> techCounts = new List<TechCount>();
+            TechCount count = null;
             if (item.EndsWith("-local.json"))
             {
                 string lessonId = item.Split("\\").Last().Replace("-local.json", "");
                 string countFile = item.Replace("-local.json", "-count.json");
-                TechCount count = null;
+
                 if (!force)
                 {
                     if (System.IO.File.Exists(countFile))
@@ -700,202 +710,16 @@ namespace HTEX.Lib.ETL.Lesson
                 }
                 if (force)
                 {
-                    string localjson = await System.IO.File.ReadAllTextAsync(item);
-                    var lessonLocal = localjson.ToObject<LessonLocal>();
-                    List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
-                    studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
-                    studentLessonDatas = LessonETLService.GetIRSData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.irsDatas, studentLessonDatas, lessonLocal.examDatas, lessonLocal.lessonRecord.id);
-                    studentLessonDatas =  LessonETLService.GetCoworkData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.coworkDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-                    studentLessonDatas =  LessonETLService.GetExamData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.examDatas, studentLessonDatas, objectiveTypes, lessonLocal.lessonRecord.id);
-                    studentLessonDatas = LessonETLService.GetSmartRatingData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.smartRatingDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-                    studentLessonDatas = LessonETLService.GetTaskData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.taskDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-                    var pickupData = LessonETLService.GetPickupData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, studentLessonDatas, lessonLocal.lessonRecord.id);
-                    studentLessonDatas= pickupData.studentLessonDatas;
-                    var codeBools = LessonETLService.GetCodeBools(studentLessonDatas);
-                 }
-
-                if (count!=null)
-                {
-                    return count;
-                }
-            }
-            return null; 
-        }
-        public static async IAsyncEnumerable<TechCount> GetTeachCount(AzureCosmosFactory azureCosmos,List<LessonRecord> lessonRecords, List<string> filesLessons, string pathLessons, List<string> ignore, List<string> objectiveTypes, AzureStorageFactory azureStorage,bool force)
-        {
-            List<TechCount> techCounts = new List<TechCount>();
-            foreach (var item in filesLessons)
-            {
-                if (item.EndsWith("-local.json"))
-                {
-                    string lessonId = item.Split("\\").Last().Replace("-local.json", "");
-                    string countFile = item.Replace("-local.json", "-count.json");
-                    TechCount count = null;
-                    if (!force)
-                    {
-                        if (System.IO.File.Exists(countFile))
-                        {
-                            string contjson = await System.IO.File.ReadAllTextAsync(countFile);
-                            count = contjson.ToObject<TechCount>();
-                        }
-                        else
-                        {
-                            force=true;
-                            
-                        }
-                    }
-                    if (force) 
+                    var lessonLocal = lessonLocals.Find(x => x.lessonRecord.id.Equals(lessonId));
+                    if (lessonLocal==null)
                     {
                         string localjson = await System.IO.File.ReadAllTextAsync(item);
-                        var lessonLocal = localjson.ToObject<LessonLocal>();
-                        List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
-                        studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
-                        studentLessonDatas = LessonETLService.GetIRSData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.irsDatas, studentLessonDatas, lessonLocal.examDatas, lessonLocal.lessonRecord.id);
-                        studentLessonDatas =  LessonETLService.GetCoworkData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.coworkDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-                        studentLessonDatas =  LessonETLService.GetExamData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.examDatas, studentLessonDatas, objectiveTypes, lessonLocal.lessonRecord.id);
-                        studentLessonDatas = LessonETLService.GetSmartRatingData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.smartRatingDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-                        studentLessonDatas = LessonETLService.GetTaskData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.taskDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
-                        var pickupData = LessonETLService.GetPickupData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, studentLessonDatas, lessonLocal.lessonRecord.id);
-                        studentLessonDatas= pickupData.studentLessonDatas;
-                        var codeBools = LessonETLService.GetCodeBools(studentLessonDatas);
-                        string yearMonth=DateTimeOffset.FromUnixTimeMilliseconds(lessonLocal.lessonRecord.startTime).ToString("yyyyMM");
-                        if (codeBools.FindAll(x => x.value).IsNotEmpty())
-                        {
-                            if (count==null) { count= new TechCount(); }
-                            count.lessonId=item.Split("\\").Last().Replace("-local.json", "");
-                            count.examCount= lessonLocal.examDatas.Count;
-                            count.taskCount= lessonLocal.taskDatas.Count;
-                            count.irsCount= lessonLocal.irsDatas.Count;
-                            count.interactNormalCount=count.irsCount;
-                            count.coworkCount= lessonLocal.coworkDatas.Count;
-                            count.smartRatingCount= lessonLocal.smartRatingDatas.Count;
-                            count.timeCount=lessonLocal.sokratesDatas.Where(x => !ignore.Contains(x.Event)  &&  !x.Event.Contains("End", StringComparison.OrdinalIgnoreCase)).GroupBy(x => x.Event).Select(x => new CodeLong() { code=x.Key, value= x.ToList().Count }).ToList();
-
-
-                            if (lessonLocal.lessonRecord!=null)
-                            {
-
-                                count.yearMonth=yearMonth;
-
-                                if (lessonLocal?.lessonBase?.summary!=null)
-                                {
-                                    count.smartRatingCountBase=lessonLocal.lessonBase.summary.smartRatingCount;
-                                    count.irsCountBase=lessonLocal.lessonBase.summary.interactionCount;
-                                    count.taskCountBase=lessonLocal.lessonBase.summary.collateTaskCount;
-                                    count.coworkCountBase=lessonLocal.lessonBase.summary.coworkTaskCount;
-                                    count.examCountBase=lessonLocal.lessonBase.summary.examCount;
-                                    count.interactNormalCountBase= count.interactNormalCount;
-                                }
-                                if (lessonLocal?.lessonBase?.report?.clientSummaryList!=null)
-                                {
-                                    count.pscore= lessonLocal.lessonBase.report.clientSummaryList.Where(x => x.score>0).Select(x => x.score);
-                                    count.gscore= lessonLocal.lessonBase.report.clientSummaryList.Where(x => x.groupScore>0).Select(x => x.groupScore);
-                                    count.tscore= lessonLocal.lessonBase.report.clientSummaryList.Where(x => x.interactScore>0).Select(x => x.interactScore);
-                                }
-                                {
-
-                                    count.pickup= pickupData.pickup;
-                                    //  var techCount = techCounts.Find(x => !string.IsNullOrWhiteSpace(x.lessonId)  &&  !string.IsNullOrWhiteSpace(lessonLocal?.lessonRecord?.id) &&  x.lessonId.Equals(lessonLocal.lessonRecord.id));
-                                    int sumUpload = 0;
-                                    int taskCount = 0;
-                                    int maxUpload = 0;
-                                    HashSet<string> pickUp = new HashSet<string>();
-                                    foreach (var stu in studentLessonDatas)
-                                    {
-                                        var countS = stu.taskRecord.itemRecords.Where(x => x.optCount>0);
-                                        if (countS.Count()>0)
-                                        {
-                                            int stuUploadmax = stu.taskRecord.itemRecords.Where(x => x.optCount>0).Max(x => x.optCount);
-                                            if (stuUploadmax> maxUpload)
-                                            {
-                                                maxUpload=stuUploadmax;
-                                            }
-                                        }
-                                        int stuUpload = stu.taskRecord.itemRecords.Where(x => x.optCount>0).Sum(x => x.optCount);
-
-                                        sumUpload+=stuUpload;
-                                        if (stu.taskRecord.itemRecords.Count()> taskCount)
-                                        {
-                                            taskCount=stu.taskRecord.itemRecords.Count();
-                                        }
-                                        var stu_scores = stu.coworkRecord.itemRecords.Where(x => x.itemScore>0).Select(x => x.itemScore);
-                                        if (stu_scores!=null  && stu_scores.Count()>0)
-                                        {
-                                            count.stuCowork.AddRange(stu_scores);
-                                        }
-                                        var grp_scores = stu.group_coworkScore.Where(x => x>0);
-                                        if (grp_scores!=null  && grp_scores.Count()>0)
-                                        {
-                                            count.groupCowork.AddRange(grp_scores);
-                                        }
-                                        //if (stu.pickups.IsNotEmpty())
-                                        //{
-                                        //    foreach (var pickup in stu.pickups)
-                                        //    {
-                                        //        pickUp.Add(pickup);
-                                        //    }
-                                        //}
-                                    }
-                                    if (studentLessonDatas.Count>0&& taskCount>0  && maxUpload>0)
-                                    {
-                                        var avgUpload = sumUpload*1.0/(studentLessonDatas.Count *taskCount);
-                                        count.upload.Add(new List<double>() { avgUpload, maxUpload });
-                                    }
-                                    //if (pickUp.Count>0)
-                                    //{
-                                    //    count.pickup.AddRange(pickUp.ToList());
-                                    //}
-                                    string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
-                                    await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-count.json", count.ToJsonString());
-                                    //if (force)
-                                    //{
-
-                                    //}
-                                    //else
-                                    //{
-                                    //    if (lessonRecords.FindAll(x => x.id.Equals(lessonLocal.lessonRecord.id)).IsNotEmpty())
-                                    //    {
-                                    //        // await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-stu.json", studentLessonDatas.ToJsonString());
-                                    //        //只有不是强制更新的时候再去刷新线上的json文件。
-
-                                    //        await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(studentLessonDatas.ToJsonString(), "records", $"{lessonLocal.lessonRecord.id}/student-analysis.json");
-                                    //        await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-count.json", count.ToJsonString());
-                                    //    }
-                                    //}
-                                }
-                            }
-                        }
-                        else 
-                        {
-                            lessonLocal.lessonRecord.analysis=-1;
-                            if (lessonLocal.lessonRecord.scope.Equals("school"))
-                            {
-                                await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(lessonLocal.lessonRecord, new PartitionKey(lessonLocal.lessonRecord.code));
-                            }
-                            else
-                            {
-                                await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(lessonLocal.lessonRecord, new PartitionKey(lessonLocal.lessonRecord.code));
-                            }
-                            try
-                            {
-                                System.IO.File.Delete($"{pathLessons}\\MM{yearMonth}\\{lessonLocal.lessonRecord!.id}-local.json");
-                            }
-                            catch (Exception ex) { }
-                            try
-                            {
-                                System.IO.File.Delete($"{pathLessons}\\MM{yearMonth}\\{lessonLocal.lessonRecord!.id}-count.json");
-                            }
-                            catch (Exception ex) { }
-                        }
-                    }
-
-                    if (count!=null)
-                    {
-                        yield return count;
+                        lessonLocal = localjson.ToObject<LessonLocal>();
                     }
+                    count= await GenTeachCount(lessonLocal, azureStorage, objectiveTypes, ignore, pathLessons, azureCosmos);
                 }
             }
-
+            return count;
         }
         public static List<StudentLessonData> GetBaseInfo(LessonBase lessonBase, List<StudentLessonData> studentLessonDatas, string? id)
         {
@@ -938,7 +762,7 @@ namespace HTEX.Lib.ETL.Lesson
                         $"/records/{lessonRecord.id}/IES/Cowork.json",
                         $"/records/{lessonRecord.id}/Sokrates/SokratesRecords.json",
                     };
-            LessonLocal lessonLocal  = new LessonLocal { lessonRecord=lessonRecord };
+            LessonLocal lessonLocal = new LessonLocal { lessonRecord=lessonRecord };
             lessonLocal =  await GetLessonFiles(lessonLocal, files, owner, _azureStorage);
             if (lessonLocal.lessonBase!=null  &&  lessonLocal.lessonBase.student!=null)
             {
@@ -950,11 +774,11 @@ namespace HTEX.Lib.ETL.Lesson
             }
             return lessonLocal;
         }
-       
+
         private static async Task<LessonLocal> GetLessonFiles(LessonLocal lessonLocal, List<string> files, string owner, AzureStorageFactory _azureStorage)
         {
 #if DEBUG
-            foreach (var file in files) 
+            foreach (var file in files)
             {
                 try
                 {
@@ -1205,7 +1029,7 @@ namespace HTEX.Lib.ETL.Lesson
                 }
 
             }
-            
+
             return studentLessonDatas;
         }
 
@@ -1948,19 +1772,19 @@ namespace HTEX.Lib.ETL.Lesson
                 var order = studentLessonDatas.Where(x => x.attend==1).OrderByDescending(x => x.coworkRecord.itemRecords[p].itemScore);
                 var maxItems = studentLessonDatas.FindAll(x => x.attend==1&& x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore);
                 double max = 0;
-                if (studentLessonDatas.FindAll(x => x.attend==1&& x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore).IsNotEmpty()) 
+                if (studentLessonDatas.FindAll(x => x.attend==1&& x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore).IsNotEmpty())
                 {
                     max=studentLessonDatas.FindAll(x => x.attend==1&& x.coworkRecord.itemRecords[p].itemScore==order.First().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
                 }
                 double min = 0;
-                if (studentLessonDatas.FindAll(x => x.attend==1&& x.coworkRecord.itemRecords[p].itemScore==order.Last().coworkRecord.itemRecords[p].itemScore).IsNotEmpty()) 
+                if (studentLessonDatas.FindAll(x => x.attend==1&& x.coworkRecord.itemRecords[p].itemScore==order.Last().coworkRecord.itemRecords[p].itemScore).IsNotEmpty())
                 {
                     min=   studentLessonDatas.FindAll(x => x.attend==1&& x.coworkRecord.itemRecords[p].itemScore==order.Last().coworkRecord.itemRecords[p].itemScore).First().coworkRecord.itemRecords[p].itemScore;
                 }
                 double sum = 0;
                 if (studentLessonDatas.FindAll(x => x.attend==1).IsNotEmpty())
                 {
-                  sum=   studentLessonDatas.FindAll(x => x.attend==1).Sum(x => x.coworkRecord.itemRecords[p].itemScore);
+                    sum=   studentLessonDatas.FindAll(x => x.attend==1).Sum(x => x.coworkRecord.itemRecords[p].itemScore);
                 }
                 foreach (var student in studentLessonDatas)
                 {
@@ -2130,19 +1954,19 @@ namespace HTEX.Lib.ETL.Lesson
                         double max = 0;
                         if (maxItems.IsNotEmpty())
                         {
-                              max = meteor_VoteSummary.FindAll(x => x.result==order.First().result).First().result;
+                            max = meteor_VoteSummary.FindAll(x => x.result==order.First().result).First().result;
                         }
                         double min = 0;
-                        if (meteor_VoteSummary.FindAll(x => x.result==order.Last().result).IsNotEmpty()) 
+                        if (meteor_VoteSummary.FindAll(x => x.result==order.Last().result).IsNotEmpty())
                         {
-                              min = meteor_VoteSummary.FindAll(x => x.result==order.Last().result).First().result;
+                            min = meteor_VoteSummary.FindAll(x => x.result==order.Last().result).First().result;
                         }
                         double sum = 0;
                         if (meteor_VoteSummary.IsNotEmpty())
                         {
                             sum = meteor_VoteSummary.Sum(x => x.result);
                         }
-                        
+
                         //排名指数计算=( 当前值分数- 298) / (9992 - 298) * (99 - 60) + 60
                         //将每个人的积分转化为60-100
                         //排名 = (积分 - 最低积分) / (最高积分 - 最低积分) * (最大排名 - 最小排名) + 最小排名
@@ -2224,7 +2048,7 @@ namespace HTEX.Lib.ETL.Lesson
                         {
                             min = smartRatingData.smartRateSummary.meteor_ScoreSummary.FindAll(x => x.result==order.Last().result).First().result;
                         }
-                         
+
                         var sum = smartRatingData.smartRateSummary.meteor_ScoreSummary.Sum(x => x.result);
 
                         foreach (var meteor_ScoreSummary in smartRatingData.smartRateSummary.meteor_ScoreSummary)
@@ -2293,15 +2117,15 @@ namespace HTEX.Lib.ETL.Lesson
                     }
                     var order = smartRatingData.smartRateSummary.mutualSummary.mutualResults.Where(x => x.result>0).OrderByDescending(x => x.result);
                     var maxItems = smartRatingData.smartRateSummary.mutualSummary.mutualResults.FindAll(x => x.result==order.First().result);
-                    double max =  0; 
-                    if (maxItems.IsNotEmpty()) 
+                    double max = 0;
+                    if (maxItems.IsNotEmpty())
                     {
-                          max = smartRatingData.smartRateSummary.mutualSummary.mutualResults.FindAll(x => x.result==order.First().result).First().result;
+                        max = smartRatingData.smartRateSummary.mutualSummary.mutualResults.FindAll(x => x.result==order.First().result).First().result;
                     }
                     double min = 0;
                     if (smartRatingData.smartRateSummary.mutualSummary.mutualResults.FindAll(x => x.result==order.Last().result).IsNotEmpty())
-                    {                    
-                          min = smartRatingData.smartRateSummary.mutualSummary.mutualResults.FindAll(x => x.result==order.Last().result).First().result;
+                    {
+                        min = smartRatingData.smartRateSummary.mutualSummary.mutualResults.FindAll(x => x.result==order.Last().result).First().result;
                     }
                     var sum = smartRatingData.smartRateSummary.mutualSummary.mutualResults.Sum(x => x.result);
                     foreach (var mutualResult in smartRatingData.smartRateSummary.mutualSummary.mutualResults)
@@ -2361,7 +2185,7 @@ namespace HTEX.Lib.ETL.Lesson
         /// <param name="studentLessonDatas"></param>
         /// <param name="lessonDataAnalysis"></param>
         /// <returns></returns>
-        public static List<StudentLessonItem>   ProcessStudentDataV2(List<StudentLessonData> studentLessonDatas, LessonDataAnalysisModel lessonDataAnalysis, List<CodeBool> codeBools)
+        public static List<StudentLessonItem> ProcessStudentDataV2(List<StudentLessonData> studentLessonDatas, LessonDataAnalysisModel lessonDataAnalysis, List<CodeBool> codeBools)
         {
 
             //历史记录的个人计分集合,通过“2倍标准差规则”移除异常值后得到的集合
@@ -2369,7 +2193,7 @@ namespace HTEX.Lib.ETL.Lesson
             //历史记录的互动计分集合,通过“2倍标准差规则”移除异常值后得到的集合
             //var max_t = lessonDataAnalysis.tscore.Max();
             //历史记录的小组计分集合,通过“2倍标准差规则”移除异常值后得到的集合
-           // var max_h = lessonDataAnalysis.gscore.Max();
+            // var max_h = lessonDataAnalysis.gscore.Max();
             var j = InteractWeight.T1;
             double t = InteractWeight.TT;
             List<StudentLessonItem> lessonItems = new List<StudentLessonItem>();
@@ -2382,11 +2206,11 @@ namespace HTEX.Lib.ETL.Lesson
                     u=100.0;
                 }
                 //c个人计分指数,d互动计分指数,e小组计分指数
-                double  d = 0, e = 0;
+                double d = 0, e = 0;
                 //本节课教师手动给学生的个人计分
                 var s = studentLessonData.pscore;
                 //个人计分指数
-                double  c =  GetPersent(lessonDataAnalysis.pscore, s).persent;// s*1.0/max_q;
+                double c = GetPersent(lessonDataAnalysis.pscore, s).persent;// s*1.0/max_q;
 
                 {
                     //智慧挑人
@@ -2431,7 +2255,7 @@ namespace HTEX.Lib.ETL.Lesson
                         var l = n<lessonDataAnalysis.interactPass ? lessonDataAnalysis.interactLow : n>lessonDataAnalysis.interactGood ? lessonDataAnalysis.interactHigh : lessonDataAnalysis.interactMedium;
                         //出题系数=当前互动次数与互动通过次数之间的比例*当前互动次数与互动中位数之间的比例*当前互动次数与互动高阶互动频次的比例
                         // var m = (n*1.0/l) *(p.persent/100)  *  (curr.Value.Count*1.0/all.Count());
-                        var m = (n*1.0/l) *(p.persent/100)  *  (lessonDataAnalysis.interactNormal.Where(x => x.Value>= curr.Value[0]&&  x.Value<=curr.Value[1] ).Sum(x=>x.Value)*1.0/lessonDataAnalysis.interactNormal.Sum(x=>x.Value));
+                        var m = (n*1.0/l) *(p.persent/100)  *  (lessonDataAnalysis.interactNormal.Where(x => x.Value>= curr.Value[0]&&  x.Value<=curr.Value[1]).Sum(x => x.Value)*1.0/lessonDataAnalysis.interactNormal.Sum(x => x.Value));
                         //学生作答次数
                         var w = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Count()*1.0;
                         //作答正确数(包括部分正确)
@@ -2524,8 +2348,8 @@ namespace HTEX.Lib.ETL.Lesson
 
 
 
-                        
-                        
+
+
                         //互动专注指数
                         // var b = ((w*w/n)+(r*r/w))*1.0*m;
                         // var f2 = Math.Round(200*1.0/(1+Math.Exp(-(b)))-100, 4);
@@ -2555,20 +2379,20 @@ namespace HTEX.Lib.ETL.Lesson
                             f2=(w/n)*100+ 0.2 * (w/n)* (r/w)*100;
                             if (f2>100) { f2=100; }
                             //智慧挑人有被挑中的
-                            if (f2>0) 
+                            if (f2>0)
                             {
                                 if (lessonItem.zh_tr>0)
                                 {
                                     f2=f2*0.8+lessonItem.zh_tr*0.2;
                                 }
                             }
-                            else{
+                            else {
                                 if (lessonItem.zh_tr>0)
                                 {
                                     f2=lessonItem.zh_tr*0.5;
                                 }
                             }
-                            
+
                         }
                         lessonItem.hd_cy=f2;
                         lessonItem.hd_cyc=w;
@@ -2599,7 +2423,7 @@ namespace HTEX.Lib.ETL.Lesson
                     }
                     //   _logger.LogInformation($"{studentLessonData.id}=>评测指数:{f8}\t得分率:{Math.Round(sum_s/n,4)}\t专注指数:{f9}\t作答率:{Math.Round(sum_a/n,4)}");
                 }
-                
+
                 {
                     //小组相关指数
                     /*  PickupNameLst 
@@ -2620,10 +2444,10 @@ namespace HTEX.Lib.ETL.Lesson
                      *  Pickup0_49
                      */
                     var grpPicks = studentLessonData.pickups.Where(x => x.StartsWith("1--") && x.Contains("Grp", StringComparison.OrdinalIgnoreCase));
-                    var groups= studentLessonDatas.Where(x => !string.IsNullOrWhiteSpace(x.groupId)).Select(x => x.groupId).Distinct();
+                    var groups = studentLessonDatas.Where(x => !string.IsNullOrWhiteSpace(x.groupId)).Select(x => x.groupId).Distinct();
                     int groupCount = 1;
                     int memberCount = studentLessonDatas.Count;
-                    if (groups!=null &&groups.Count()>0) 
+                    if (groups!=null &&groups.Count()>0)
                     {
                         groupCount=groups.Count();
                         var members = studentLessonDatas.Where(x => !string.IsNullOrWhiteSpace(x.groupId)  &&  !string.IsNullOrWhiteSpace(studentLessonData.groupId)&&x.groupId.Equals(studentLessonData.groupId));
@@ -2638,11 +2462,11 @@ namespace HTEX.Lib.ETL.Lesson
                     double groupType = 0;
                     foreach (var grppick in grpPicks)
                     {
-                        pickRate+=  (1.0/groupCount) * (1.0/memberCount)* 100 ;
+                        pickRate+=  (1.0/groupCount) * (1.0/memberCount)* 100;
                     }
                     if (grpPickCount>0)
                     {
-                        pickRate=100- Math.Round(pickRate/grpPickCount,4);
+                        pickRate=100- Math.Round(pickRate/grpPickCount, 4);
                         groupType+=1;
                         lessonItem.xz_tr=grpPickCount;
                     }
@@ -2663,22 +2487,22 @@ namespace HTEX.Lib.ETL.Lesson
                         groupType+=1;
                         lessonItem.xz_jf=studentLessonData.gscore;
                     }
-                    double groupTask  = 0;
-                    var groupTasks=  studentLessonData.taskRecord.itemRecords.Where(x => x.isGroup);
-                    if(groupTasks!=null && groupTasks.Count()>0) 
-                    { 
+                    double groupTask = 0;
+                    var groupTasks = studentLessonData.taskRecord.itemRecords.Where(x => x.isGroup);
+                    if (groupTasks!=null && groupTasks.Count()>0)
+                    {
                         //double score = CalculateScore(groupTasks.Sum(x=>x.optCount));
                         groupType+=1;
-                        double a= lessonItem.xz_sc=groupTasks.Sum(x => x.optCount);
+                        double a = lessonItem.xz_sc=groupTasks.Sum(x => x.optCount);
                         double n = groupTasks.Count();
                         double w = groupTasks.Where(x => x.optCount>0).Count();
                         groupTask= Math.Round(80*1.0/(1+Math.Exp(-(w/n+(w/n)*(a/w)-1)))+20, 4);
 
                     }
                     double fxGrp = 0;
-                    if (groupType>0) { 
+                    if (groupType>0) {
                         fxGrp = (pickRate+coworkRate+gscoreRate+groupTask)/groupType; }
-                    if (groupType==2  &&(pickRate>0 && gscoreRate>0)  )
+                    if (groupType==2  &&(pickRate>0 && gscoreRate>0))
                     {
                         fxGrp = (pickRate*0.8+coworkRate+gscoreRate*0.8+groupTask)/groupType;
                     }
@@ -2686,28 +2510,27 @@ namespace HTEX.Lib.ETL.Lesson
                     {
                         fxGrp=(pickRate+coworkRate+gscoreRate+groupTask)*0.8/groupType;
                     }
-                    lessonItem.hz_nl=Math.Round(fxGrp,4);
+                    lessonItem.hz_nl=Math.Round(fxGrp, 4);
                 }
                 {
                     //任务相关指数
                     double n = studentLessonData.taskRecord.itemRecords.Count()*1.0;
                     if (n>0)
                     {
-                       // double max_m = lessonDataAnalysis.task.Select(x=>x.Key).Max();
+                        // double max_m = lessonDataAnalysis.task.Select(x=>x.Key).Max();
                         double w = studentLessonData.taskRecord.itemRecords.Where(x => x.resultWeight>0).Count()*1.0;
-                     
+
                         lessonItem.rw_fqc =n;
                         lessonItem.rw_cyc =w;
-                        double a = lessonItem.rw_zpc =studentLessonData.taskRecord.itemRecords.Sum(x=>x.optCount);
+                        double a = lessonItem.rw_zpc =studentLessonData.taskRecord.itemRecords.Sum(x => x.optCount);
                         //lessonItem.rw_cx =f4;
-                       // lessonItem.rw_cy =f5;
+                        // lessonItem.rw_cy =f5;
                         double score = 0;
                         if (w>0 &&   lessonItem.rw_zpc>0)
                         {
-                            score= Math.Round(80*1.0/(1+Math.Exp(-(w/n+(w/n)*(a/w)-1)))+20,4);
+                            score= Math.Round(80*1.0/(1+Math.Exp(-(w/n+(w/n)*(a/w)-1)))+20, 4);
                         }
                         lessonItem.rw_cx =score;
-                        lessonItem.rw_cy =score;
                     }
                     // _logger.LogInformation($"{studentLessonData.id}=>任务指数:{f4}\t专注指数:{f5}\t任务次数:{n}\t参与次数:{w}\t");
 
@@ -2772,12 +2595,12 @@ namespace HTEX.Lib.ETL.Lesson
                         //{
                         //    //x=sw/(j *wc);
                         //}
-                       // double max_xzcg = 75;
+                        // double max_xzcg = 75;
                         //double k = (wc*wc/n+x)/n+ wc*(ss/max_xzcg)* (wc/n);
                         //double k = wc/n +wc*(ss/max_xzcg)* (wc/n);
                         var avg = lessonDataAnalysis.stuCowork.Select(x => x.Value* x.Key).Sum()*1.0/lessonDataAnalysis.stuCowork.Sum(x => x.Value);
-                        double k=(GetPersent(lessonDataAnalysis.stuCowork, ss).persent/100+ ss/ avg)* (wc/n  );
-                       // double f6 = Math.Round(190*1.0/(1+Math.Exp(-(k)))-95, 4);
+                        double k = (GetPersent(lessonDataAnalysis.stuCowork, ss).persent/100+ ss/ avg)* (wc/n);
+                        // double f6 = Math.Round(190*1.0/(1+Math.Exp(-(k)))-95, 4);
                         double f7 = Math.Round(200*1.0/(1+Math.Exp(-(k)))-100, 4);
 
                         lessonItem.xz_fqc =n;
@@ -2791,7 +2614,7 @@ namespace HTEX.Lib.ETL.Lesson
 
                 double xx_cx = 0, xx_cy = 0;
                 int avg_cx = 0, avg_cy = 0;
-                if (lessonItem.xz_cx>0  && codeBools.FindAll(x=>x.code.Equals("xz") && x.value==true).IsNotEmpty())
+                if (lessonItem.xz_cx>0  && codeBools.FindAll(x => x.code.Equals("xz") && x.value==true).IsNotEmpty())
                 {
                     avg_cx+=1;
                 }
@@ -2812,7 +2635,7 @@ namespace HTEX.Lib.ETL.Lesson
                 {
                     avg_cx+=1;
                 }
-                if (lessonItem.hz_nl>0  )
+                if (lessonItem.hz_nl>0)
                 {
                     avg_cx+=1;
                 }
@@ -2832,7 +2655,7 @@ namespace HTEX.Lib.ETL.Lesson
                 {
                     avg_cy+=1;
                 }
-                if (lessonItem.rw_cy>0 && codeBools.FindAll(x => x.code.Equals("rw") && x.value==true).IsNotEmpty())
+                if (lessonItem.rw_cx>0 && codeBools.FindAll(x => x.code.Equals("rw") && x.value==true).IsNotEmpty())
                 {
                     avg_cy+=1;
                 }
@@ -2852,9 +2675,9 @@ namespace HTEX.Lib.ETL.Lesson
                 //{
                 //    avg_cy+=1;
                 //}
-                if (avg_cy>0) 
+                if (avg_cy>0)
                 {
-                    xx_cy+=Math.Round(lessonItem.hd_cy * 1.0/avg_cy+ lessonItem.pc_zd* 1.0/avg_cy+ lessonItem.rw_cy* 1.0/avg_cy+ lessonItem.pj_nl* 1.0/avg_cy+ lessonItem.xz_cy* 1.0/avg_cy+ lessonItem.hz_nl* 1.0/avg_cy, 4);
+                    xx_cy+=Math.Round(lessonItem.hd_cy * 1.0/avg_cy+ lessonItem.pc_zd* 1.0/avg_cy+ lessonItem.rw_cx* 1.0/avg_cy+ lessonItem.pj_nl* 1.0/avg_cy+ lessonItem.xz_cy* 1.0/avg_cy+ lessonItem.hz_nl* 1.0/avg_cy, 4);
                 }
                 lessonItem.xx_cx=xx_cx;
                 lessonItem.xx_cy=xx_cy;
@@ -2909,10 +2732,10 @@ namespace HTEX.Lib.ETL.Lesson
         /// <param name="items"></param>
         /// <param name="filePath"></param>
         /// <returns></returns>
-        public static async Task ExportToExcelAzureBlob(List<StudentLessonItem> items, AzureStorageFactory azureStorage,string owner , string path ,  XmlDocument xmlDocument,List<string> summarys, PropertyInfo[] properties)
+        public static async Task ExportToExcelAzureBlob(List<StudentLessonItem> items, AzureStorageFactory azureStorage, string owner, string path, XmlDocument xmlDocument, List<string> summarys, PropertyInfo[] properties)
         {
             ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
-            using (var memoryStream = new MemoryStream()) 
+            using (var memoryStream = new MemoryStream())
             {
                 using (ExcelPackage package = new ExcelPackage())
                 {
@@ -3025,21 +2848,21 @@ namespace HTEX.Lib.ETL.Lesson
         /// <param name="nums"></param>
         /// <param name="curr"></param>
         /// <returns></returns>
-        public static (double persent, int count) GetPersent(List<KeyValuePair<double, int>>  nums, double curr)
+        public static (double persent, int count) GetPersent(List<KeyValuePair<double, int>> nums, double curr)
         {
             int count = 0;
-            foreach (var op in nums.Select(x=>x.Key).OrderBy(x => x))
+            foreach (var op in nums.Select(x => x.Key).OrderBy(x => x))
             {
                 if (op <= curr)
                 {
-                    count+=nums.Find(x=>x.Key==op).Value;
+                    count+=nums.Find(x => x.Key==op).Value;
                 }
                 else
                 {
                     break;
                 }
             }
-            return (count *1.0/ nums.Select(x=>x.Value).Sum() * 100, count);
+            return (count *1.0/ nums.Select(x => x.Value).Sum() * 100, count);
         }
 
         /// <summary>
@@ -3065,6 +2888,14 @@ namespace HTEX.Lib.ETL.Lesson
             return (count *1.0/ nums.Count() * 100, count);
         }
     }
+    public class LessonStudentResult
+    {
+        public string id { get; set; }
+        public string owner { get; set; }
+        public List<StudentLessonItem> studentLessons { get; set; } = new List<StudentLessonItem>();
+        public List<CodeBool> codeBools { get; set; } = new List<CodeBool>();
+        public List<StudentLessonData> lessonDatas { get; set; } = new List<StudentLessonData>();
+    }
     /// <summary>
     /// 学生导出Excel的Entity
     /// </summary>
@@ -3105,7 +2936,7 @@ namespace HTEX.Lib.ETL.Lesson
         /// </summary>
         public double hd_cx { get; set; } = 0;
         /// <summary>
-        /// 互动专注指数
+        /// 互动参与指数
         /// </summary>
         public double hd_cy { get; set; } = 0;
         /// <summary>
@@ -3129,13 +2960,10 @@ namespace HTEX.Lib.ETL.Lesson
         /// </summary>
         public double rw_zpc { get; set; } = 0;
         /// <summary>
-        /// 任务成效指数
+        /// 任务指数
         /// </summary>
         public double rw_cx { get; set; } = 0;
-        /// <summary>
-        /// 任务专注指数
-        /// </summary>
-        public double rw_cy { get; set; } = 0;
+         
 
         /// <summary>
         /// 评价发起次数
@@ -3178,7 +3006,7 @@ namespace HTEX.Lib.ETL.Lesson
         /// </summary>
         public double pj_po { get; set; } = 0;
         /// <summary>
-        /// 评价能力
+        /// 评价能力指数
         /// </summary>
         public double pj_nl { get; set; } = 0;
         /// <summary>
@@ -3198,7 +3026,7 @@ namespace HTEX.Lib.ETL.Lesson
         /// </summary>
         public double xz_cx { get; set; } = 0;
         /// <summary>
-        /// 协作专注指数
+        /// 协作参与指数
         /// </summary>
         public double xz_cy { get; set; } = 0;
        
@@ -3219,16 +3047,16 @@ namespace HTEX.Lib.ETL.Lesson
         /// </summary>
         public double xz_sc { get; set; } = 0;
         /// <summary>
-        /// 合作能力
+        /// 合作能力指数
         /// </summary>
         public double hz_nl { get; set; } = 0;
 
         /// <summary>
-        /// 学习成效
+        /// 学习成效指数
         /// </summary>
         public double xx_cx { get; set; } = 0;
         /// <summary>
-        /// 学习专注度
+        /// 学习态度指数
         /// </summary>
         public double xx_cy { get; set; } = 0;
     }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 8 - 22
TEAMModelOS.Extension/HTEX.Lib/summary.xml


+ 2 - 3
TEAMModelOS.Extension/HTEX.Test/Program.cs

@@ -6,6 +6,7 @@ using HTEX.Test.Service;
 using MathNet.Numerics;
 using MathNet.Numerics.LinearAlgebra;
 using System;
+using System.Collections.Concurrent;
 using System.Configuration;
 using System.Diagnostics;
 using System.IO;
@@ -27,10 +28,8 @@ namespace HTEX.Test
     {
         public static async Task Main(string[] args)
         {
-            //Test2();
-
            
-           //await MockDataController.MockData();
+            //await MockDataController.MockData();
             var builder = WebApplication.CreateBuilder(args);
 
             // Add services to the container.

+ 25 - 3
TEAMModelOS.Function/IESServiceBusTrigger.cs

@@ -45,6 +45,9 @@ using HTEX.Lib.ETL.Lesson;
 using System.Globalization;
 using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
 using static TEAMModelOS.SDK.Models.Service.SystemService;
+using System.Xml;
+using System.Reflection;
+using System.Text.RegularExpressions;
 
 namespace TEAMModelOS.Function
 {
@@ -1767,7 +1770,11 @@ namespace TEAMModelOS.Function
                                             if (lessonRecord.duration>0)
                                             {
                                                 var location = Environment.GetEnvironmentVariable("Option:Location");
-                                                if (location.Equals("China", StringComparison.OrdinalIgnoreCase)) 
+
+                                                var studatas = LessonETLService.GenStudentLessonData(lessonLocal, Constant.objectiveTypes  );
+                                                string owner = lessonRecord.scope.Equals("school") ? lessonRecord.school : lessonRecord.tmdid;
+
+                                                if (location.Equals("China", StringComparison.OrdinalIgnoreCase))
                                                 {
                                                     List<School> schools = new List<School>();
                                                     List<StudentSemesterRecord> studentSemesterRecords = new List<StudentSemesterRecord>();
@@ -1804,7 +1811,7 @@ namespace TEAMModelOS.Function
                                                         {
                                                             overallEducations.AddRange(overallEducationResults.list);
                                                         }
-                                                        LessonETLService.DoStudentLessonDataV2(Constant.objectiveTypes, lessonLocal, location, studentSemesterRecords, overallEducations, lessonDataAnalysis, studentsBase, schools);
+                                                        var studata = LessonETLService.DoStudentLessonDataV2(Constant.objectiveTypes, lessonLocal, location, studentSemesterRecords, overallEducations, lessonDataAnalysis, studentsBase, schools);
                                                         await Parallel.ForEachAsync(studentSemesterRecords, async (studentSemester, cancellationToken) =>
                                                         {
                                                             await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(studentSemester, new PartitionKey(studentSemester.code));
@@ -1817,8 +1824,23 @@ namespace TEAMModelOS.Function
                                                             await _azureRedis.GetRedisClient(8).HashSetAsync(key, overallEducation.studentId, overallEducation.ToJsonString());
                                                             await _azureRedis.GetRedisClient(8).KeyExpireAsync(key, new TimeSpan(180 *24, 0, 0));
                                                         });
-                                                    }
+                                                        await _azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(studata.studentLessonDatas.ToJsonString(), "records", $"{lessonRecord.id}/student-analysis.json");
+                                                        XmlDocument xmlDocument = new XmlDocument();
+                                                        var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
+                                                        xmlDocument.Load($"{runtimePath}\\summary.xml");
+                                                        PropertyInfo[] properties = typeof(StudentLessonItem).GetProperties();
+                                                        List<string> summaryes = new List<string>();
+                                                        for (int i = 0; i < properties.Length; i++)
+                                                        {
+                                                            string summary = Regex.Replace(LessonETLService.GetPropertySummary(properties[i], xmlDocument), @"\s+", "");
+                                                            summaryes.Add(summary);
+                                                        }
+                                                        await LessonETLService.ExportToExcelAzureBlob(studata.lessonItems, _azureStorage, owner, $"{lessonRecord.id}/student-analysis.xlsx", xmlDocument, summaryes, properties);
 
+                                                    }
+                                                }
+                                                else {
+                                                    await _azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(studatas.studentLessonDatas.ToJsonString(), "records", $"{lessonRecord.id}/student-analysis.json");
                                                 }
 
 

+ 32 - 21
TEAMModelOS/Controllers/Third/XunFeiJYY/XunFeilJYYController.cs

@@ -16,6 +16,10 @@ using TEAMModelOS.SDK.Extension;
 using System.Text.Json;
 using System.Web;
 using System.Text;
+using System.Net.Http;
+using System.Net.Http.Json;
+using Azure.Core;
+using Microsoft.Azure.Cosmos;
 
 
 namespace TEAMModelOS.Controllers.Third.XunFeiJYY
@@ -29,13 +33,19 @@ namespace TEAMModelOS.Controllers.Third.XunFeiJYY
     [Route("xunfei-jjy")]
     public class XunFeilJYYController : ControllerBase
     {
-        public static readonly string authurl = "http://www.jyyun.com/sso-oauth/authorize";
-        public static readonly string url= "https://open.jyyun.com";
-        public static readonly string appid = "ea4e44e1dea54caba7b06bdea72970fa";
-        public static readonly string appsecret = "bb79a189fb9c22e9ae1a62b279a112c0";
-        public static readonly string apikey = "305C300D06092A864886F70D0101010500034B003048024100C362EAB80DDFD682367592DD8274A40A9FE9F37DDEC56AC8E0FBE4A5A6D9F6FDAAA495460821CA94EF4A955B582822D7BB289142F2C562FC04DA2D3B940C3D730203010001";
-        public static readonly string testuserid = "fbc284072a40da84adbe206f721b3285bc5101240c006447328c7afa3b7ae20d122a14a73144eea261756cce3e83c3f6ef940d9e8d823c7c";
-        public static readonly string testschlid = "fbc284072a40da841b643aa367013eb18a1d351ed46b0feb15f629530e2f3c1137ae30823af5c69d3b88ef0fa3c761efee102032fc5d2a5a";
+        private static readonly string authurl = "http://www.jyyun.com/sso-oauth";
+        private static readonly string authorize = "authorize";
+        private static readonly string getOpenId = "getOpenId";
+        private static readonly string getUserInfo = "getUserInfo";
+
+        private static readonly string url= "https://open.jyyun.com";
+        private static readonly string getUserByUserId = "getUserByUserId";
+
+        private static readonly string appid = "ea4e44e1dea54caba7b06bdea72970fa";
+        private static readonly string appsecret = "bb79a189fb9c22e9ae1a62b279a112c0";
+        private static readonly string apikey = "305C300D06092A864886F70D0101010500034B003048024100C362EAB80DDFD682367592DD8274A40A9FE9F37DDEC56AC8E0FBE4A5A6D9F6FDAAA495460821CA94EF4A955B582822D7BB289142F2C562FC04DA2D3B940C3D730203010001";
+        private static readonly string testuserid = "fbc284072a40da84adbe206f721b3285bc5101240c006447328c7afa3b7ae20d122a14a73144eea261756cce3e83c3f6ef940d9e8d823c7c";
+        private static readonly string testschlid = "fbc284072a40da841b643aa367013eb18a1d351ed46b0feb15f629530e2f3c1137ae30823af5c69d3b88ef0fa3c761efee102032fc5d2a5a";
         private readonly AzureCosmosFactory _azureCosmos;
         private readonly DingDing _dingDing;
         private readonly Option _option;
@@ -44,6 +54,7 @@ namespace TEAMModelOS.Controllers.Third.XunFeiJYY
         private readonly IWebHostEnvironment _environment;
         private readonly IConfiguration _configuration;
         private readonly ILogger<XunFeilJYYController> _logger;
+        private readonly IHttpClientFactory _httpClientFactory;
 
         public XunFeilJYYController(ILogger<XunFeilJYYController> logger, IConfiguration configuration, IWebHostEnvironment environment, 
             CoreAPIHttpService coreAPIHttpService, AzureStorageFactory azureStorage, DingDing dingDing, AzureCosmosFactory azureCosmos, IOptionsSnapshot<Option> option)  
@@ -69,7 +80,7 @@ namespace TEAMModelOS.Controllers.Third.XunFeiJYY
                 {
                     HostName = _option.HostName;
                 }
-                string xunfei_url = $"{authurl}?appkey={appid}&redirectUri=https://{HostName}/xunfei-jjy/sso&state={DateTimeOffset.Now.ToUnixTimeMilliseconds()}&display=web";
+                string xunfei_url = $"{authurl}/{authorize}?appkey={appid}&redirectUri={HttpUtility.UrlEncode($"https://{HostName}/xunfei-jjy/sso", Encoding.UTF8)}&state={DateTimeOffset.Now.ToUnixTimeMilliseconds()}&display=web";
                 return Ok(new { xunfei_url, code = 200 });
             }
             else 
@@ -77,25 +88,25 @@ namespace TEAMModelOS.Controllers.Third.XunFeiJYY
                 return Ok(new { code = 400, msg = "参数错误" });
             }
         }
-        [HttpPost("sso")]
+        [HttpGet("sso")]
         [AllowAnonymous]
-        public async Task<IActionResult> Sso(JsonElement json)
+        public async Task<IActionResult> Sso([FromQuery]string accesstoken,[FromQuery]string state)
         {
-            json.TryGetProperty("p", out var p);
-            if ($"{p}".Equals("xunfei-jjy-sso"))
+            //前端缓存accesstoken,用于做免登录验证。直接获取用户的Token .
+            var  httpClient=  _httpClientFactory.CreateClient();
+
+            HttpResponseMessage response_getOpenId  =  await httpClient.PostAsJsonAsync($"{authurl}/{getOpenId}",new { appkey= appid , appsecret= appsecret, accessToken= accesstoken });
+            if (response_getOpenId.IsSuccessStatusCode) 
             {
-                string HostName = HttpContext.GetHostName();
-                if (!string.IsNullOrWhiteSpace(_option.HostName))
+                var result = await response_getOpenId.Content.ReadAsStringAsync();
+                var resultData= result.ToObject<JsonElement>();
+
+                if (resultData.TryGetProperty("data", out JsonElement data)) 
                 {
-                    HostName = _option.HostName;
+                    
                 }
-                string xunfei_url = $"{authurl}?appkey={appid}&redirectUri={HttpUtility.UrlEncode($"https://{HostName}/xunfei-jjy/sso", Encoding.UTF8)}&state={DateTimeOffset.Now.ToUnixTimeMilliseconds()}&display=web";
-                return Ok(new { xunfei_url, code = 200 });
-            }
-            else
-            {
-                return Ok(new { code = 400, msg = "参数错误" });
             }
+            return Ok(new { code = 200 });
         }
     }
 }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 28 - 28
TEAMModelOS/appsettings.Development.json