|
@@ -115,7 +115,7 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
public static async Task<(List<StudentLessonData> studentLessonDatas, List<StudentLessonItem> lessonItems, List<CodeBool> codeBools)>
|
|
|
DoStudentLessonData(List<string> objectiveTypes, AzureStorageFactory azureStorage, LessonLocal lessonLocal,DingDing _dingDing,
|
|
|
CosmosClient client,string location ,AzureRedisFactory azureRedis, List<StudentSemesterRecord> studentSemesterRecords, List<OverallEducation> overallEducations,
|
|
|
- LessonDataAnalysisCluster lessonDataAnalysis, List<Student> studentsBase,List<School> schools )
|
|
|
+ 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);
|
|
@@ -135,13 +135,13 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
try
|
|
|
{
|
|
|
|
|
|
- bool exists = await azureStorage.GetBlobContainerClient("0-public").GetBlobClient($"/lesson/analysis/analysis.json").ExistsAsync();
|
|
|
+ bool exists = await azureStorage.GetBlobContainerClient("0-public").GetBlobClient($"/lesson/analysis/analysis-model.json").ExistsAsync();
|
|
|
if (exists)
|
|
|
{
|
|
|
if (lessonDataAnalysis==null)
|
|
|
{
|
|
|
- BlobDownloadResult blobDownload = await azureStorage.GetBlobContainerClient("0-public").GetBlobClient($"/lesson/analysis/analysis.json").DownloadContentAsync();
|
|
|
- lessonDataAnalysis = blobDownload.Content.ToObjectFromJson<LessonDataAnalysisCluster>();
|
|
|
+ BlobDownloadResult blobDownload = await azureStorage.GetBlobContainerClient("0-public").GetBlobClient($"/lesson/analysis/analysis-model.json").DownloadContentAsync();
|
|
|
+ lessonDataAnalysis = blobDownload.Content.ToObjectFromJson<LessonDataAnalysisModel>();
|
|
|
}
|
|
|
|
|
|
lessonItems = LessonETLService.ProcessStudentDataV2(studentLessonDatas, lessonDataAnalysis, codeBools);
|
|
@@ -156,7 +156,7 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
{
|
|
|
if (!ex.Message.Contains("The specified blob does not exist"))
|
|
|
{
|
|
|
- await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")},lesson/analysis/analysis.json转换异常,{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
|
|
|
+ await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")},lesson/analysis/analysis-model.json转换异常,{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
|
|
|
}
|
|
|
}
|
|
|
await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(studentLessonDatas.ToJsonString(), "records", $"{lessonLocal.lessonRecord.id}/student-analysis.json");
|
|
@@ -479,8 +479,8 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
List<KeyValuePair<double, List<double>>> levelInteract = new List<KeyValuePair<double, List<double>>>()
|
|
|
{
|
|
|
new KeyValuePair<double, List<double>>(low, new List<double> { all.Where(x => x<pass).Min(), all.Where(x => x<pass).Max() }),
|
|
|
- new KeyValuePair<double, List<double>>(low, new List<double> { all.Where(x => x>=pass &&x<good).Min(), all.Where(x => x>=pass &&x<good).Max() }),
|
|
|
- new KeyValuePair<double, List<double>>(low, new List<double> { all.Where(x => x>=good).Min(), all.Where(x => x>=good).Max() })
|
|
|
+ new KeyValuePair<double, List<double>>(medium, new List<double> { all.Where(x => x>=pass &&x<good).Min(), all.Where(x => x>=pass &&x<good).Max() }),
|
|
|
+ new KeyValuePair<double, List<double>>(high, new List<double> { all.Where(x => x>=good).Min(), all.Where(x => x>=good).Max() })
|
|
|
};
|
|
|
lessonDataAnalysisCluster.levelInteract= levelInteract;
|
|
|
//// 设置0 为自动规划聚类,11 则为自动规划后得到的数字。
|
|
@@ -494,10 +494,210 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
// lessonDataAnalysisCluster.clustersInteract.Add(new KeyValuePair<double, List<double>>(item.Value.Average(), item.Value));
|
|
|
// //Console.WriteLine($"dp:{item.Key} ,avg: {item.Value.Average()}, count: {item.Value.Count}, min:{item.Value.Min()}, max:{item.Value.Max()},weight:{item.Value.Count*1.0/d.Count()}");
|
|
|
//}
|
|
|
- await azureStorage.GetBlobContainerClient("0-public").UploadFileByContainer(lessonDataAnalysisCluster.ToJsonString(), "lesson", $"analysis/analysis.json");
|
|
|
- System.IO.File.WriteAllText(Path.Combine(pathAnalysis, "analysis.json"), lessonDataAnalysisCluster.ToJsonString());
|
|
|
+ //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.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();
|
|
|
+ analysisModel.gscore= lessonDataAnalysisCluster.gscore.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
|
|
|
+ analysisModel.tscore= lessonDataAnalysisCluster.tscore.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
|
|
|
+ analysisModel.stuCowork= lessonDataAnalysisCluster.stuCowork.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
|
|
|
+ analysisModel.groupCowork= lessonDataAnalysisCluster.groupCowork.GroupBy(x => Math.Ceiling(x)).Select(x => new KeyValuePair<double, int>(x.Key, x.ToList().Count)).ToList();
|
|
|
+ analysisModel.interactPass= lessonDataAnalysisCluster.interactPass;
|
|
|
+ analysisModel.interactGood= lessonDataAnalysisCluster.interactGood;
|
|
|
+ analysisModel.interactLow= lessonDataAnalysisCluster.interactLow;
|
|
|
+ analysisModel.interactMedium= lessonDataAnalysisCluster.interactMedium;
|
|
|
+ analysisModel.interactHigh= lessonDataAnalysisCluster.interactHigh;
|
|
|
+ analysisModel.levelInteract= lessonDataAnalysisCluster.levelInteract;
|
|
|
+ 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());
|
|
|
}
|
|
|
+ /// <summary>
|
|
|
+ ///
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="azureCosmos"></param>
|
|
|
+ /// <param name="item"></param>
|
|
|
+ /// <param name="pathLessons"></param>
|
|
|
+ /// <param name="ignore"></param>
|
|
|
+ /// <param name="objectiveTypes"></param>
|
|
|
+ /// <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)
|
|
|
+ {
|
|
|
+ List<TechCount> techCounts = new List<TechCount>();
|
|
|
+ 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)
|
|
|
+ {
|
|
|
+ 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)
|
|
|
+ {
|
|
|
+ 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>();
|
|
@@ -691,7 +891,52 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
}
|
|
|
return studentLessonDatas;
|
|
|
}
|
|
|
+ /// <summary>
|
|
|
+ ///
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="lessonRecord"></param>
|
|
|
+ /// <param name="localIds"></param>
|
|
|
+ /// <param name="_azureStorage"></param>
|
|
|
+ /// <param name="pathLessons"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static async Task<LessonLocal> GetLessonLocal(LessonRecord lessonRecord, List<string> localIds, AzureStorageFactory _azureStorage, string pathLessons)
|
|
|
+ {
|
|
|
+ string scope = lessonRecord.scope;
|
|
|
+ string owner = lessonRecord.scope.Equals("school") ? lessonRecord.school : lessonRecord.tmdid;
|
|
|
+
|
|
|
+ string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(lessonRecord.startTime).ToString("yyyyMM");
|
|
|
+ LessonLocal lessonLocal = new LessonLocal { lessonRecord=lessonRecord };
|
|
|
+ if (System.IO.File.Exists($"{pathLessons}\\MM{yearMonthPath}\\{lessonRecord.id}-local.json"))
|
|
|
+ {
|
|
|
+ string jsonp = await System.IO.File.ReadAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{lessonRecord.id}-local.json");
|
|
|
+ lessonLocal = jsonp.ToObject<LessonLocal>();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ List<string> files = new List<string>()
|
|
|
+ {
|
|
|
+ $"/records/{lessonRecord.id}/IES/TimeLine.json",
|
|
|
+ $"/records/{lessonRecord.id}/IES/base.json",
|
|
|
+ $"/records/{lessonRecord.id}/IES/Task.json",
|
|
|
+ $"/records/{lessonRecord.id}/IES/SmartRating.json",
|
|
|
+ $"/records/{lessonRecord.id}/IES/IRS.json",
|
|
|
+ $"/records/{lessonRecord.id}/IES/Cowork.json",
|
|
|
+ $"/records/{lessonRecord.id}/Sokrates/SokratesRecords.json",
|
|
|
+ };
|
|
|
+ lessonLocal = new LessonLocal { lessonRecord=lessonRecord };
|
|
|
+ lessonLocal = await GetLessonFiles(lessonLocal, files, owner, _azureStorage);
|
|
|
+ }
|
|
|
|
|
|
+ if (lessonLocal.lessonBase!=null && lessonLocal.lessonBase.student!=null)
|
|
|
+ {
|
|
|
+ var baseData = GetBaseData(lessonLocal.lessonBase!);
|
|
|
+ lessonLocal.studentLessonDatas= baseData.studentLessonDatas;
|
|
|
+ List<ExamData> examDatas = await GetExamInfo(lessonRecord, lessonLocal.timeLineData, _azureStorage, owner);
|
|
|
+ lessonLocal.examDatas = examDatas;
|
|
|
+ lessonLocal.sokratesDatas= lessonLocal.sokratesDatas.IsNotEmpty() ? lessonLocal.sokratesDatas : lessonLocal.timeLineData!=null ? lessonLocal.timeLineData.events : new List<TimeLineEvent>();
|
|
|
+ }
|
|
|
+ return lessonLocal;
|
|
|
+ }
|
|
|
public static async IAsyncEnumerable<LessonLocal> GetLessonLocal(List<LessonRecord> lessonRecords, List<string> localIds, AzureStorageFactory _azureStorage, string pathLessons)
|
|
|
{
|
|
|
foreach (var lessonRecord in lessonRecords)
|
|
@@ -2097,7 +2342,7 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
/// <param name="studentLessonDatas"></param>
|
|
|
/// <param name="lessonDataAnalysis"></param>
|
|
|
/// <returns></returns>
|
|
|
- public static List<StudentLessonItem> ProcessStudentDataV2(List<StudentLessonData> studentLessonDatas, LessonDataAnalysisCluster lessonDataAnalysis, List<CodeBool> codeBools)
|
|
|
+ public static List<StudentLessonItem> ProcessStudentDataV2(List<StudentLessonData> studentLessonDatas, LessonDataAnalysisModel lessonDataAnalysis, List<CodeBool> codeBools)
|
|
|
{
|
|
|
|
|
|
//历史记录的个人计分集合,通过“2倍标准差规则”移除异常值后得到的集合
|
|
@@ -2421,7 +2666,7 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
double n = studentLessonData.taskRecord.itemRecords.Count()*1.0;
|
|
|
if (n>0)
|
|
|
{
|
|
|
- double max_m = lessonDataAnalysis.task.Max();
|
|
|
+ double max_m = lessonDataAnalysis.task.Select(x=>x.Key).Max();
|
|
|
double w = studentLessonData.taskRecord.itemRecords.Where(x => x.resultWeight>0).Count()*1.0;
|
|
|
double y = (10 *w/n+(j/t) *w)/max_m;
|
|
|
double l = max_m*(w*w/n+(j/t) * w)/n;
|
|
@@ -2741,6 +2986,29 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
}
|
|
|
return property.Name;
|
|
|
}
|
|
|
+ /// <summary>
|
|
|
+ /// 当前数超越集合的百分比
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="nums"></param>
|
|
|
+ /// <param name="curr"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ 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))
|
|
|
+ {
|
|
|
+ if (op <= curr)
|
|
|
+ {
|
|
|
+ count+=nums.Find(x=>x.Key==op).Value;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return (count *1.0/ nums.Select(x=>x.Value).Sum() * 100, count);
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 当前数超越集合的百分比
|
|
|
/// </summary>
|
|
@@ -2931,6 +3199,66 @@ namespace HTEX.Lib.ETL.Lesson
|
|
|
/// </summary>
|
|
|
public double xx_cy { get; set; } = 0;
|
|
|
}
|
|
|
+ /// <summary>
|
|
|
+ ///
|
|
|
+ /// </summary>
|
|
|
+ public class LessonDataAnalysisModel {
|
|
|
+ /// <summary>
|
|
|
+ /// 任务模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> task { get; set;}= new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// irs模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> irs { get; set; } = new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// 互动模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> interactNormal { get; set; } = new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// 个人计分模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> pscore { get; set; } = new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// 小组计分模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> gscore { get; set; } = new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// 互动计分模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> tscore { get; set; } = new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// 学生个人协作模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> stuCowork { get; set; } = new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// 学生小组协作模型
|
|
|
+ /// </summary>
|
|
|
+ public List<KeyValuePair<double, int>> groupCowork { get; set; } = new List<KeyValuePair<double, int>>();
|
|
|
+ /// <summary>
|
|
|
+ /// 互动次数及格线
|
|
|
+ /// </summary>
|
|
|
+ public double interactPass { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 互动次数良好线
|
|
|
+ /// </summary>
|
|
|
+
|
|
|
+ public double interactGood { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 互动次数差线
|
|
|
+ /// </summary>
|
|
|
+ public double interactLow { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 互动次数中线
|
|
|
+ /// </summary>
|
|
|
+ public double interactMedium { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 互动次数高线
|
|
|
+ /// </summary>
|
|
|
+ public double interactHigh { get; set; }
|
|
|
+ public List<KeyValuePair<double, List<double>>> levelInteract { get; set; } = new List<KeyValuePair<double, List<double>>>();
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 历史课例的关键数据模型
|
|
|
/// </summary>
|