using Azure;
using Azure.Storage.Blobs.Models;
using DocumentFormat.OpenXml.Drawing.Charts;
using DocumentFormat.OpenXml.Office2010.Excel;
using DocumentFormat.OpenXml.Office2013.Drawing.ChartStyle;
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
using MathNet.Numerics;
using MathNet.Numerics.Distributions;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using OfficeOpenXml;
using OpenXmlPowerTools;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using TEAMModelOS.SDK;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.Models;
using TEAMModelOS.SDK.Models.Cosmos.Common;
using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
using TEAMModelOS.SDK.Models.Dtos;
using static TEAMModelOS.SDK.Models.ThirdService;
namespace HTEX.Lib.ETL.Lesson
{
public class LessonETLService
{
///
/// 生成学生student-analysis.json
///
///
///
///
///
public static async Task<(List studentLessonDatas, List lessonItems)>
DoStudentLessonData(List objectiveTypes, AzureStorageFactory azureStorage, LessonLocal lessonLocal,DingDing _dingDing,
CosmosClient client,string location ,AzureRedisFactory azureRedis, List studentSemesterRecords, List overallEducations,
LessonDataAnalysisCluster lessonDataAnalysis, List studentsBase,List schools
)
{
List studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject>();
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;
List lessonItems = new List();
string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
try
{
bool exists= await azureStorage.GetBlobContainerClient("0-public").GetBlobClient($"/lesson/analysis/analysis.json").ExistsAsync();
if (exists)
{
if (lessonDataAnalysis==null)
{
BlobDownloadResult blobDownload = await azureStorage.GetBlobContainerClient("0-public").GetBlobClient($"/lesson/analysis/analysis.json").DownloadContentAsync();
lessonDataAnalysis = blobDownload.Content.ToObjectFromJson();
}
lessonItems = LessonETLService.ProcessStudentDataV2(studentLessonDatas, lessonDataAnalysis);
XmlDocument xmlDocument = new XmlDocument();
var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
xmlDocument.Load($"{runtimePath}\\summary.xml");
await LessonETLService.ExportToExcelAzureBlob(lessonItems,azureStorage, owner,$"{lessonLocal.lessonRecord.id}/student-analysis.xlsx", xmlDocument);
// await _dingDing.SendBotMsg($"学生课中报告已经生成:{owner},records/{lessonLocal.lessonRecord.id}/student-analysis.xlsx",GroupNames.成都开发測試群組);
}
}
catch (Exception ex)
{
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 azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(studentLessonDatas.ToJsonString(), "records", $"{lessonLocal.lessonRecord.id}/student-analysis.json");
if (lessonLocal.lessonRecord.scope.Equals("school")&& !string.IsNullOrWhiteSpace(lessonLocal.lessonRecord.school) && location.Equals("China",StringComparison.OrdinalIgnoreCase))
{
School school = schools.Find(x=>x.id.Equals(lessonLocal.lessonRecord.school));
if (school==null)
{
ResponseMessage response = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(lessonLocal.lessonRecord.school, new PartitionKey("Base"));
if (response.IsSuccessStatusCode)
{
school = JsonDocument.Parse(response.Content).RootElement.ToObject();
schools.Add(school);
}
}
if (school!=null)
{
var sdtus= studentLessonDatas.Where(y =>!studentsBase.Where(z=>z.schoolId.Equals(school.id)).Select(x => x.id).Contains(y.id) );
if (sdtus!=null && sdtus.Count()>0)
{
var result = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetList($"select value c from c where c.id in ({string.Join(",", sdtus.Select(d => $"'{d.id}'"))})", $"Base-{school.id}");
if (result.list.Any())
{
studentsBase.AddRange(result.list);
}
}
string? periodId = !string.IsNullOrWhiteSpace(lessonLocal.lessonRecord.periodId) ? lessonLocal.lessonRecord.periodId : school.period.FirstOrDefault()?.id;
var period = school.period.Find(x => x.id.Equals(periodId));
if (period!=null)
{
var semester = SchoolService.GetSemester(period, lessonLocal.lessonRecord.startTime);
string pre_id = $"{semester.studyYear}-{semester.currSemester.id}";
string code = $"StudentSemesterRecord-{school.id}";
foreach (var studentLessonData in studentLessonDatas)
{
StudentSemesterRecord studentSemester = studentSemesterRecords.Find(x=>x.id.Equals($"{pre_id}-{studentLessonData.id}") && x.code.Equals(code));
if (studentSemester==null)
{
ResponseMessage responseMessage = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemStreamAsync($"{pre_id}-{studentLessonData.id}", new PartitionKey(code));
if (responseMessage.IsSuccessStatusCode)
{
studentSemester= JsonDocument.Parse(responseMessage.Content).ToObject();
}
else
{
studentSemester= new StudentSemesterRecord
{
id= $"{pre_id}-{studentLessonData.id}",
code=code,
stuid= studentLessonData.id,
userType=Constant.ScopeStudent,
school=school.id,
studyYear=semester.studyYear,
semesterId=semester.currSemester.id,
period= period?.id,
pk="StudentSemesterRecord"
};
}
studentSemesterRecords.Add(studentSemester);
}
var les = studentSemester.les.Find(x => x.id.Equals(lessonLocal.lessonRecord.id));
if (les==null)
{
les = new StuLesson()
{
id= lessonLocal.lessonRecord.id,
time= lessonLocal.lessonRecord.startTime,
attend=0
};
studentSemester.les.Add(les);
}
else {
les.time= lessonLocal.lessonRecord.startTime;
}
var lesson = studentSemester.lessons.Find(x => x.id.Equals(lessonLocal.lessonRecord.id));
if (lesson!=null)
{
if (studentLessonData.cooperation>0 || studentLessonData.achieve>0|| studentLessonData.attitude>0 || studentLessonData.cowork>0 || studentLessonData.appraise>0)
{
les.attend=1;
lesson.tmdid = lessonLocal.lessonRecord.tmdid;
lesson.sid = lessonLocal.lessonRecord.subjectId;
lesson.cid = lessonLocal.lessonRecord.courseId;
lesson.hrate = studentLessonData.cooperation;
lesson.crate = studentLessonData.achieve;
lesson.trate = studentLessonData.attitude;
lesson.xrate = studentLessonData.cowork;
lesson.prate = studentLessonData.appraise;
}
else
{
if (studentLessonData.attend==1)
{
les.attend=1;
}
else
{
les.attend=0;
}
}
}
else
{
if (studentLessonData.cooperation>0 || studentLessonData.achieve>0|| studentLessonData.attitude>0 || studentLessonData.cowork>0 || studentLessonData.appraise>0)
{
les.attend=1;
lesson = new StuLessonLite
{
id=lessonLocal.lessonRecord.id,
tmdid=lessonLocal.lessonRecord.tmdid,
sid= lessonLocal.lessonRecord.subjectId,
cid= lessonLocal.lessonRecord.courseId,
hrate=studentLessonData.cooperation,
crate=studentLessonData.achieve,
trate=studentLessonData.attitude,
xrate=studentLessonData.cowork,
prate=studentLessonData.appraise
};
studentSemester.lessons.Add(lesson);
}
else
{
if (studentLessonData.attend==1)
{
les.attend=1;
}
else
{
les.attend=0;
}
}
}
//await client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(studentSemester, new PartitionKey(studentSemester.code));
string oid = $"{semester.studyYear}-{semester.currSemester.id}-{studentSemester.stuid}";
string ocode = $"OverallEducation-{school.id}";
var student= studentsBase.Find(x => x.id.Equals(studentSemester.stuid));
if (student!=null)
{
OverallEducation overallEducation = overallEducations.Find(x => x.id.Equals(oid) && x.code.Equals(ocode));
if (overallEducation== null)
{
ResponseMessage oresponse = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemStreamAsync(oid, new PartitionKey(ocode));
if (!oresponse.IsSuccessStatusCode)
{
overallEducation = new OverallEducation
{
id =oid,
code = $"OverallEducation-{school.id}",
pk = "OverallEducation",
ttl = -1,
name = student.name,
classId = student?.classId,
schoolCode = $"{school.id}",
semesterId = semester.currSemester.id,
year = semester.studyYear,
periodId = $"{period.id}",
stuYear = student.year,
studentId = student.id,
lessonScore= new List()
};
}
else
{
overallEducation = JsonDocument.Parse(oresponse.Content).RootElement.ToObject();
}
overallEducations.Add(overallEducation);
}
var hasrecord = overallEducation.lessonScore.Find(x => x.lessonId.Equals(lessonLocal.lessonRecord.id));
if (hasrecord==null)
{
hasrecord= new StudentLessonRecord();
overallEducation.lessonScore.Add(hasrecord);
}
hasrecord.gscore = studentLessonData.gscore;
hasrecord.pscore = studentLessonData.pscore;
hasrecord.tscore = studentLessonData.tscore;
hasrecord.tmdid = lessonLocal.lessonRecord.tmdid;
hasrecord.school = school.id;
hasrecord.scope = lessonLocal.lessonRecord.scope;
hasrecord.lessonId = lessonLocal.lessonRecord.id;
hasrecord.courseId = lessonLocal.lessonRecord.courseId;
periodId = period?.id;
hasrecord.subjectId = lessonLocal.lessonRecord.subjectId;
hasrecord.time= lessonLocal.lessonRecord.startTime;
hasrecord.attend=les.attend;
if (lesson!=null)
{
hasrecord.hrate=lesson.hrate;
hasrecord.crate=lesson.crate;
hasrecord.trate=lesson.trate;
hasrecord.xrate=lesson.xrate;
hasrecord.prate=lesson.prate;
}
//if (overallEducation!=null)
//{
// await client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(overallEducation, partitionKey: new PartitionKey(overallEducation.code));
// string key = $"OverallEducation:{school.id}:{period.id}:{semester.studyYear}:{semester.currSemester.id}:{student?.classId}";
// await azureRedis.GetRedisClient(8).HashSetAsync(key, studentLessonData.id, overallEducation.ToJsonString());
// await azureRedis.GetRedisClient(8).KeyExpireAsync(key, new TimeSpan(180 *24, 0, 0));
//}
}
}
}
}
}
return (studentLessonDatas, lessonItems);
}
public static async Task GenAnalysisData(string pathAnalysis, long newest, List techCounts,AzureStorageFactory azureStorage)
{
var yearMonthDatas = techCounts.GroupBy(x => x.yearMonth).Select(x => new { key = x.Key, list = x.ToList() });
// lessonDataAnalysisMonths = new List();
LessonDataAnalysisCluster lessonDataAnalysisCluster = new LessonDataAnalysisCluster();
foreach (var yearMonthData in yearMonthDatas)
{
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();
lessonDataAnalysisMonth.gscore = yearMonthData.list.SelectMany(x => x.gscore).ToList();
lessonDataAnalysisMonth.irs= yearMonthData.list.Where(x => x.irsCount>0).Select(x => (double)x.irsCount).ToList();
lessonDataAnalysisMonth.interactNormal= yearMonthData.list.Where(x => x.interactNormalCount > 0).Select(x => (double)x.interactNormalCount).ToList();
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();
System.IO.File.WriteAllText(Path.Combine(pathAnalysis, $"{yearMonthData.key}-m-analysis.json"), lessonDataAnalysisMonth.ToJsonString());
// lessonDataAnalysisMonths.Add( lessonDataAnalysisMonth);
if (lessonDataAnalysisMonth.task.IsNotEmpty())
{
lessonDataAnalysisCluster.task.AddRange(lessonDataAnalysisMonth.task);
}
if (lessonDataAnalysisMonth.irs.IsNotEmpty())
{
lessonDataAnalysisCluster.irs.AddRange(lessonDataAnalysisMonth.irs);
}
if (lessonDataAnalysisMonth.interactNormal.IsNotEmpty())
{
lessonDataAnalysisCluster.interactNormal.AddRange(lessonDataAnalysisMonth.interactNormal);
}
if (lessonDataAnalysisMonth.pscore.IsNotEmpty())
{
lessonDataAnalysisCluster.pscore.AddRange(lessonDataAnalysisMonth.pscore);
}
if (lessonDataAnalysisMonth.gscore.IsNotEmpty())
{
lessonDataAnalysisCluster.gscore.AddRange(lessonDataAnalysisMonth.gscore);
}
if (lessonDataAnalysisMonth.tscore.IsNotEmpty())
{
lessonDataAnalysisCluster.tscore.AddRange(lessonDataAnalysisMonth.tscore);
}
if (lessonDataAnalysisMonth.stuCowork.IsNotEmpty())
{
lessonDataAnalysisCluster.stuCowork.AddRange(lessonDataAnalysisMonth.stuCowork);
}
if (lessonDataAnalysisMonth.groupCowork.IsNotEmpty())
{
lessonDataAnalysisCluster.groupCowork.AddRange(lessonDataAnalysisMonth.groupCowork);
}
lessonDataAnalysisCluster.pickup.AddRange(lessonDataAnalysisMonth.pickup);
}
//标准差偏差N倍,视为异常数据
int thresholdMultiplier = 2;
lessonDataAnalysisCluster.task= LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.task.OrderBy(x => x), thresholdMultiplier);
lessonDataAnalysisCluster.pscore= LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.pscore.OrderBy(x => x), thresholdMultiplier);
lessonDataAnalysisCluster.gscore= LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.gscore.OrderBy(x => x), thresholdMultiplier);
lessonDataAnalysisCluster.tscore= LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.tscore.OrderBy(x => x), thresholdMultiplier);
lessonDataAnalysisCluster.irs = LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.irs.OrderBy(x => x), thresholdMultiplier);
lessonDataAnalysisCluster.interactNormal=LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.interactNormal.OrderBy(x => x), thresholdMultiplier);
lessonDataAnalysisCluster.stuCowork=LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.stuCowork.OrderBy(x => x), thresholdMultiplier);
lessonDataAnalysisCluster.groupCowork=LessonETLService.CleanDataBySDThreshold(lessonDataAnalysisCluster.groupCowork.OrderBy(x => x), thresholdMultiplier);
var all = lessonDataAnalysisCluster.interactNormal.OrderBy(x => x).ToArray();
//超过60 80的
double n = all.Max()+1;
//var clusterInteract = HTEX.Lib.ETL.KMeansService.KMeansOptimized(d, 3);
//foreach (var item in clusterInteract.OrderBy(x => x.Key))
//{
// lessonDataAnalysisCluster.clustersInteract.Add(new KeyValuePair>(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()}");
//}
//IEnumerable all = lessonDataAnalysisCluster.clustersInteract.SelectMany(x => x.Value);
int pass = 0;
for (var i = 1; i=60)
{
pass = i;
break;
}
}
var low = all.Where(x => x=80)
{
good = i;
break;
}
}
var medium = all.Where(x => x>=pass &&x x>=good).Average();
lessonDataAnalysisCluster.interactGood=good;
lessonDataAnalysisCluster.interactPass=pass;
lessonDataAnalysisCluster.interactHigh=high;
lessonDataAnalysisCluster.interactMedium=medium;
lessonDataAnalysisCluster.interactLow=low;
List>> levelInteract = new List>>()
{
new KeyValuePair>(low, new List { all.Where(x => x x>(low, new List { all.Where(x => x>=pass &&x x>=pass &&x>(low, new List { all.Where(x => x>=good).Min(), all.Where(x => x>=good).Max() })
};
lessonDataAnalysisCluster.levelInteract= levelInteract;
//// 设置0 为自动规划聚类,11 则为自动规划后得到的数字。
//var clusterInteract = KMeansService.KMeansOptimized(d,11,10);
////foreach (var item in clusterInteract)
////{
//// Console.WriteLine($"dp:{item.Key} ,avg: {item.Value.Average()}, count: {item.Value.Count}, min:{item.Value.Min()}, max:{item.Value.Max()}");
////}
//foreach (var item in clusterInteract.OrderBy(x => x.Key))
//{
// lessonDataAnalysisCluster.clustersInteract.Add(new KeyValuePair>(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());
}
public static async IAsyncEnumerable GetTeachCount(List lessonRecords, List filesLessons, string pathLessons, List ignore, List objectiveTypes, AzureStorageFactory azureStorage,bool force)
{
foreach (var item in filesLessons)
{
if (item.EndsWith("-local.json"))
{
TechCount count = null;
string lessonId = item.Split("\\").Last().Replace("-local.json", "");
string countFile = item.Replace("-local.json", "-count.json");
if (System.IO.File.Exists(countFile))
{
if (System.IO.File.Exists(countFile))
{
string contjson = await System.IO.File.ReadAllTextAsync(countFile);
count = contjson.ToObject();
}
}
if (string.IsNullOrWhiteSpace(count?.yearMonth)|| force)
{
string localjson = await System.IO.File.ReadAllTextAsync(item);
var lessonLocal = localjson.ToObject();
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=DateTimeOffset.FromUnixTimeMilliseconds(lessonLocal.lessonRecord.startTime).ToString("yyyyMM");
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);
}
///处理学生数据
{
List studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject>();
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;
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 pickUp = new HashSet();
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() { avgUpload, maxUpload });
}
//if (pickUp.Count>0)
//{
// count.pickup.AddRange(pickUp.ToList());
//}
string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
// if (!azureStorage.GetBlobContainerClient(owner).GetBlobClient($"records/{lessonLocal.lessonRecord.id}/student-analysis.json").Exists())
{
}
// if (!System.IO.File.Exists($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-stu.json"))
{
}
if (force)
{
await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-count.json", count.ToJsonString());
}
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());
}
}
}
}
}
if (count!=null)
{
yield return count;
}
}
}
}
public static List GetBaseInfo(LessonBase lessonBase, List studentLessonDatas, string? id)
{
if (lessonBase?.report?.clientSummaryList !=null && lessonBase.report.clientSummaryList.IsNotEmpty())
{
foreach (var item in lessonBase.report.clientSummaryList)
{
var student = studentLessonDatas.Find(x => x.seatID!=null && x.seatID.Equals($"{item.seatID}"));
if (student!= null)
{
student.gscore= item.groupScore;
student.tscore= item.interactScore;
student.pscore= item.score;
}
}
}
return studentLessonDatas;
}
public static async IAsyncEnumerable GetLessonLocal(List lessonRecords, List localIds, AzureStorageFactory _azureStorage, string pathLessons)
{
foreach (var lessonRecord in lessonRecords)
{
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();
}
else
{
List files = new List()
{
$"/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 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();
}
yield return lessonLocal;
}
}
private static async Task GetLessonFiles(LessonLocal lessonLocal, List files, string owner, AzureStorageFactory _azureStorage)
{
await Parallel.ForEachAsync(files, async (file, _) =>
{
try
{
var exists = _azureStorage.GetBlobContainerClient(owner).GetBlobClient(file).Exists();
if (exists)
{
BlobDownloadResult blobDownloadResult = await _azureStorage.GetBlobContainerClient(owner).GetBlobClient(file).DownloadContentAsync();
switch (true)
{
case bool when file.Contains("IES/TimeLine.json"):
lessonLocal.timeLineData= blobDownloadResult.Content.ToObjectFromJson();
break;
case bool when file.Contains("IES/base.json"):
lessonLocal.lessonBase= blobDownloadResult.Content.ToObjectFromJson();
break;
case bool when file.Contains("IES/Task.json"):
lessonLocal.taskDatas= blobDownloadResult.Content.ToObjectFromJson>();
break;
case bool when file.Contains("IES/SmartRating.json"):
lessonLocal.smartRatingDatas= blobDownloadResult.Content.ToObjectFromJson>();
break;
case bool when file.Contains("IES/IRS.json"):
lessonLocal.irsDatas= blobDownloadResult.Content.ToObjectFromJson>();
break;
case bool when file.Contains("IES/Cowork.json"):
lessonLocal.coworkDatas= blobDownloadResult.Content.ToObjectFromJson>();
break;
case bool when file.Contains("Sokrates/SokratesRecords.json"):
lessonLocal.sokratesDatas= blobDownloadResult.Content.ToObjectFromJson>();
break;
}
}
}
catch (RequestFailedException ex)
{
Console.WriteLine($"{file},{ex.Message},{ex.StackTrace}");
}
catch (Exception ex)
{
Console.WriteLine($"{file},{ex.Message},{ex.StackTrace}");
}
});
return lessonLocal;
}
///
/// 处理base.json的数据
///
///
///
///
public static (LessonBase lessonBase, List studentLessonDatas) GetBaseData(LessonBase lessonBase)
{
//处理学生定位数据
List studentLessonDatas = new List();
int index = 0;
try
{
if (lessonBase!=null)
{
lessonBase.student.ForEach(x =>
{
int attend = 0;
var client = lessonBase.report.clientSummaryList.Find(y => y.seatID == x.seatID);
if (client!=null)
{
attend=client.attendState;
}
studentLessonDatas.Add(new LocalStudent()
{
id = x.id,
index = index,
seatID =$"{x.seatID}",
groupId = x.groupId,
attend= attend
});
index++;
});
}
}
catch (Exception ex)
{
Console.WriteLine(lessonBase.ToJsonString());
}
return (lessonBase, studentLessonDatas);
}
///
///单独处理挑人的逻辑
///是否从小组里面挑人。
///不需要去重页面,直接获取挑人大类 PickupResult
///小类处理:PickupRight , PickupOption , PickupNthGrp ,PickupEachGrp ,PickupDiff , PickupResult 挑人算不算互动?? 读取PickupMemberId "[\r\n 35\r\n]"
///
///
///
///
///
///
public static (List studentLessonDatas, List pickup) GetPickupData(LessonBase lessonBase, TimeLineData timeLineData, List studentLessonDatas, string lessonId)
{
var enventsPickup = timeLineData?.events.Where(x => !string.IsNullOrWhiteSpace(x.Pgid) && x.Event.Equals("PickupResult"));
List pickup = new List();
if (enventsPickup.IsNotEmpty())
{
foreach (var item in enventsPickup)
{
List mbrs = item.PickupMemberId.ToObject>();
// 挑人挑中 TT ,没有挑中 T1
foreach (var studentLessonData in studentLessonDatas)
{
var mbr = mbrs.FindAll(x => studentLessonData.seatID!.Equals($"{x}"));
if (mbr.IsNotEmpty())
{
foreach (var m in mbr)
{
studentLessonData.attend=1;
//studentLessonData.interactRecord.interactRecords.Add(new ItemRecord()
//{
// resultWeight = InteractWeight.TT,
// resultType=InteractReultType.TT,
// itemType = string.IsNullOrWhiteSpace(item.PickupType) ? "PickupResult" : item.PickupType
//});
studentLessonData.pickups.Add(string.IsNullOrWhiteSpace(item.PickupType) ? "1--PickupResult" : $"1--{item.PickupType}");
}
}
else
{
//处理未挑中的
if (studentLessonData.attend==1)
{
studentLessonData.pickups.Add(string.IsNullOrWhiteSpace(item.PickupType) ? "0--PickupResult" : $"0--{item.PickupType}");
}
}
}
pickup.Add(item.PickupType);
}
}
return (studentLessonDatas, pickup);
}
///
///读取互动信息
///Event 过滤类型 'PopQuesLoad', 'ReAtmpAnsStrt', 'BuzrAns','BuzrLoad'
/// 在IRS.json处理 'PopQuesLoad'互动问答 , 'ReAtmpAnsStrt' 二次作答 , 'BuzrAns' 抢权(新), 'BuzrLoad'抢权(旧)
///TimeLine.json 中找到对应类型,根据Pgid 去 IRS.json 中找到对应数据,从clientAnswers 的下标对应 base.json 中的 student 找到对应学生信息 clientAnswers.length > 1 则表示有二次作答
///读取IRS.json
///
///
///
///
///
///
///
///
public static List GetIRSData(LessonBase lessonBase, TimeLineData timeLineData, List irsDatas, List studentLessonDatas, List examDatas, string lessonId)
{
List interactTypes = new List() { "PopQuesLoad", "ReAtmpAnsStrt", "BuzrAns", "BuzrLoad" };
//去重页面
var enventsInteract = timeLineData?.events?.Where(x => !string.IsNullOrWhiteSpace(x.Pgid) && interactTypes.Contains(x.Event)).GroupBy(x => x.Pgid).Select(x => new { key = x.Key, list = x.ToList() });
if (enventsInteract!= null && enventsInteract.Count()>0)
{
var keys = enventsInteract.Select(x => x.key).ToList();
foreach (var item in enventsInteract)
{
ProcessIRSPageData(irsDatas, studentLessonDatas, examDatas, item);
}
//处理其他,评测类型的互动,因为有可能不会记录在TimeLine.json中
var envents_other = timeLineData.events.Where(x => !string.IsNullOrWhiteSpace(x.Pgid) && !keys.Contains(x.Pgid)).GroupBy(x => x.Pgid).Select(x => new { key = x.Key, list = x.ToList() });
if (envents_other!=null && envents_other.Count()>0)
{
foreach (var item in envents_other)
{
ProcessIRSPageData(irsDatas, studentLessonDatas, examDatas, item);
}
}
}
else
{
//处理其他,评测类型的互动,因为有可能不会记录在TimeLine.json中
if (timeLineData!=null)
{
var envents_other = timeLineData.events.Where(x => !string.IsNullOrWhiteSpace(x.Pgid)).GroupBy(x => x.Pgid).Select(x => new { key = x.Key, list = x.ToList() });
if (envents_other!=null && envents_other.Count()>0)
{
foreach (var item in envents_other)
{
ProcessIRSPageData(irsDatas, studentLessonDatas, examDatas, item);
}
}
}
else
{
foreach (var item in irsDatas.Select(x => x.pageID))
{
ProcessIRSPageData(irsDatas, studentLessonDatas, examDatas, new { key = item });
}
}
}
return studentLessonDatas;
}
private static List ProcessIRSPageData(List irsDatas, List studentLessonDatas, List examDatas, dynamic item)
{
var irsDataPages = irsDatas.Where(y => item.key.Equals(y.pageID));
foreach (var irsDataPage in irsDataPages)
{
//检查是否设置正确答案。
var answers_q = irsDataPage.question?["exercise"]?["answer"]?.ToJsonString().ToObject>();
//根据题去找对应的试卷和评测信息
var question_id = $"{irsDataPage.question?["id"]}";
var examData = examDatas.Where(x => x.paper!=null && x.paper.slides.Exists(x => !string.IsNullOrWhiteSpace(x.url) && x.url.Equals($"{question_id}.json"))).FirstOrDefault();
List answers = new List();
answers_q?.ForEach(x => {
if (!string.IsNullOrWhiteSpace(x))
{
answers.Add(x);
}
});
var _objective = irsDataPage.question?["exercise"]?["objective"];
var scoreNode = irsDataPage.question?["exercise"]?["score"];
var _type = irsDataPage.question?["exercise"]?["type"];
var _answerType = irsDataPage.question?["exercise"]?["answerType"];//file,audio,text,image
var qitem = irsDataPage.question?["item"]?.AsArray();
if (qitem!=null && qitem.Count()>0)
{
for (var i = 0; i();
}
//题型
string type = string.Empty;
if (_type!=null)
{
//题型
type = _type.GetValue();
List types = new List() { "single", "multiple", "judge", "sortmultiple" };
if (types.Contains(type))
{
objective = true;
}
else
{
objective = false;
}
}
if (_answerType!=null)
{
_answerType.GetValue();
//暂不处理,可能存在依然传文字的情况
//不是文本作答的处理,题目不是客观题,答案不记录
//if (!_answerType.Equals("text"))
//{
// objective=false;
// answers=new List();
//}
}
if (scoreNode!=null)
{
double.TryParse(scoreNode.ToString(), out questionScore);
}
string interactType = string.Empty;
if (irsDataPage.clientAnswers.IsNotEmpty())
{
//第一个list是几轮,一次作答,二次作答, 第二个list是学生的下标, 第三个list是 答案
List>> clientAnswers = new List>>();
foreach (var key in irsDataPage.clientAnswers.Keys)
{
clientAnswers.Add(irsDataPage.clientAnswers[key]);
}
// 获取第一个列表的长度作为比较基准
int firstListLength = clientAnswers.First().Count;
bool isSameLength = true;
// 遍历剩余的列表并检查它们的长度是否与第一个列表相同
foreach (var innerList in clientAnswers.Skip(1))
{
if (innerList.Count != firstListLength)
{
isSameLength = false;
break;
}
}
//并检查学生集合的长度是否与第一个列表相同
if (isSameLength && studentLessonDatas.Count()==firstListLength)
{
for (int index = 0; index< clientAnswers[0].Count; index++)
{
var student = studentLessonDatas[index];
double studentScore = 0;
if (examData!=null && examData.examClassResult.IsNotEmpty())
{
var examResultIndex = examData.examClassResult.First().studentIds.IndexOf(student.id);
var questionIndex = examData.paper.slides.Select(x => x.url).ToList().IndexOf($"{question_id}.json");
if (examResultIndex>=0
&& examData.examClassResult.First().studentScores.Count>=(examResultIndex+1) //防止索引越界
&& examData.examClassResult.First().studentScores[examResultIndex].Count>=(questionIndex+1)) //防止索引越界
{
//获取index学生在questionIndex题的分数
studentScore = examData.examClassResult.First().studentScores[examResultIndex][questionIndex];
}
}
//index 代表学生下标
List interactRecords = new List();
if (clientAnswers.Count==1)
{
//即问即答
interactType = "PopQuesLoad";
var ans0 = clientAnswers[0][index];
var IS0 = GetInteractResultHasAnswer(answers, ans0, objective, type, questionScore, studentScore);
interactRecords.Add(new ItemRecord()
{
resultWeight = IS0.weight,
resultType=IS0.reultType,
itemType= interactType,
criterion= questionScore,
itemScore= IS0.interactScore
});
}
if (clientAnswers.Count==2)
{
//二次作答
interactType="ReAtmpAnsStrt";
var ans1 = clientAnswers[1][index];
var IS1 = GetInteractResultHasAnswer(answers, ans1, objective, type, questionScore, studentScore);
interactRecords.Add(new ItemRecord()
{
resultWeight = IS1.weight,
resultType=IS1.reultType,
itemType= interactType,
criterion= questionScore,
itemScore= IS1.interactScore
});
}
if (clientAnswers.Count>2)
{
//三次作答
interactType="TeAtmpAnsStrt";
var ans2 = clientAnswers[2][index];
var IS2 = GetInteractResultHasAnswer(answers, ans2, objective, type, questionScore, studentScore);
interactRecords.Add(new ItemRecord()
{
resultWeight = IS2.weight,
resultType=IS2.reultType,
itemType= interactType,
criterion= questionScore,
itemScore= IS2.interactScore
});
}
if (studentLessonDatas[index].attend==1)
{
studentLessonDatas[index].interactRecord.interactRecords.AddRange(interactRecords);
}
}
}
}
//是否抢权作答的模式
if (irsDataPage.isBuzz)
{
interactType = "BuzrAns";
//处理参与抢权的
Dictionary buzzParticipants = new Dictionary();
foreach (var buzzParticipant in irsDataPage.buzzParticipants)
{
var studentData = studentLessonDatas.Find(x => x.seatID!.Equals(buzzParticipant));
if (studentData != null)
{
buzzParticipants[buzzParticipant]=new ItemRecord() { resultWeight = InteractWeight.T1, itemType= interactType, resultType= InteractReultType.T1 };
}
}
//处理抢权成功的
foreach (var buzzClient in irsDataPage.buzzClients)
{
buzzParticipants[buzzClient]=new ItemRecord() { resultWeight = InteractWeight.TT, itemType= interactType, resultType= InteractReultType.TT };
}
foreach (var studentLessonData in studentLessonDatas)
{
if (buzzParticipants.ContainsKey(studentLessonData.seatID!))
{
//处理已经有抢权结果的数据
studentLessonData.attend=1;
studentLessonData.interactRecord.interactRecords.Add(buzzParticipants[studentLessonData.seatID!]);
}
else
{
if (studentLessonData.attend==1)
{
//处理未参与抢权的
studentLessonData.interactRecord.interactRecords.Add(new ItemRecord() { resultWeight = InteractWeight.T0, itemType = interactType, resultType= InteractReultType.T0 });
}
}
}
}
}
return studentLessonDatas;
}
private static (double weight, string reultType, double interactScore) GetInteractResultHasAnswer(List? answers, List ans0, bool objective, string type, double questionScore, double studentScore)
{
//List ans0 = new List();
//ans?.ForEach(x => {
// if (!string.IsNullOrWhiteSpace(x))
// {
// ans0.Add(x);
// }
// else { ans.Add("");}
//});
double weight = InteractWeight.T0;
string reultType = InteractReultType.T0;
double interactScore = 0;
if (answers.IsNotEmpty())
{
if (ans0.IsNotEmpty())
{
if (objective) //客观题
{
//标准答案等于作答的结果
if (answers!.Count == ans0.Count)
{
if (answers.All(item => ans0.Contains(item)))
{
//完全正确
weight= InteractWeight.TT;
reultType= InteractReultType.TT;
interactScore= studentScore==0 ? questionScore : studentScore;
}
else
{
//作答错误
weight= InteractWeight.T1;
reultType = InteractReultType.T1;
interactScore= studentScore;
}
}
//标准答案比作答的结果多
else if (answers!.Count > ans0.Count)
{
if (ans0.All(item => answers.Contains(item)))
{
//部分正确
weight= InteractWeight.TP;
reultType = InteractReultType.TP;
// 2 * 0.3 * 10= 6
interactScore= studentScore==0 ? 1/(InteractWeight.TT-InteractWeight.T1) * (InteractWeight.TP-InteractWeight.T1) * questionScore : studentScore;
}
else
{
//作答错误
weight= InteractWeight.T1;
reultType = InteractReultType.T1;
interactScore= studentScore;
}
}
//标准答案比作答结果少
else
{
//作答错误
weight= InteractWeight.T1;
reultType = InteractReultType.T1;
interactScore= studentScore;
}
}
else
{
//填空题
if ("complete".Equals(type) && answers!.Count==ans0.Count)
{
bool hasT = false;
bool hasF = false;
for (int i = 0; i < answers!.Count; i++)
{
if (answers[i].Equals(ans0[i]))
{
hasT=true;
}
else
{
hasF=true;
}
}
if (hasT && !hasF)
{
//完全正确
weight= InteractWeight.TT;
reultType = InteractReultType.TT;
interactScore= studentScore==0 ? questionScore : studentScore;
}
else if (hasT && hasF)
{
//部分正确
weight= InteractWeight.TP;
reultType = InteractReultType.TP;
// 2 * 0.3 * 10= 6
interactScore= studentScore==0 ? 1/(InteractWeight.TT-InteractWeight.T1) * (InteractWeight.TP-InteractWeight.T1) * questionScore : studentScore;
}
else if (!hasT && hasF)
{
//没有正确的,但有错误的,代表参与了
weight= InteractWeight.T1;
reultType = InteractReultType.T1;
interactScore= studentScore;
}
else if (!hasT && !hasF)
{
//没有正确的,也没有错误的,代表没有作答
weight= InteractWeight.T0;
reultType = InteractReultType.T0;
interactScore= studentScore;
}
}
else
{
//主观题,完全匹配的
if (answers!.All(item => ans0.Contains(item)))
{
//完全正确
weight= InteractWeight.TT;
reultType = InteractReultType.TT;
interactScore= studentScore==0 ? questionScore : studentScore;
}
else
{ // 使用LINQ查询来判断是否有匹配的答案
bool hasMatchingAnswer = answers!.Intersect(ans0).Any();
if (hasMatchingAnswer)
{
//主观题回答正确即为完全正确
weight= InteractWeight.TT;
reultType = InteractReultType.TT;
interactScore= studentScore==0 ? questionScore : studentScore;
}
else
{
//优先根据得分与标准分的占比算出得分率,如果没有得分率,如果是直接从互动,不知道是评测的 需要先去评测找作答得分。,则采用Levenshtein距离来评估两个字符串的相似度
//没有匹配上答案,则采用Levenshtein距离来评估两个字符串的相似度
if (questionScore>0)
{
if (studentScore>0)
{
weight = studentScore * 1.0 / questionScore* (InteractWeight.TT-InteractWeight.T1);
if (weight==InteractWeight.T1)
{
reultType = InteractReultType.T1;
interactScore=studentScore;
}
else if (weight>InteractWeight.TT)
{
reultType = InteractReultType.TT;
interactScore=studentScore==0 ? questionScore : studentScore;
}
else
{
reultType = InteractReultType.TP;
// 2 * 0.3 * 10= 6
interactScore= studentScore==0 ? 1/(InteractWeight.TT-InteractWeight.T1) * (InteractWeight.TP-InteractWeight.T1) * questionScore : studentScore;
}
}
else
{
weight=InteractWeight.T1+(CalculateSimilarity(answers![0], ans0[0]) *(InteractWeight.TT-InteractWeight.T1));
if (weight==InteractWeight.T1)
{
reultType = InteractReultType.T1;
interactScore=studentScore;
}
else if (weight>InteractWeight.TT)
{
reultType = InteractReultType.TT;
interactScore=studentScore==0 ? questionScore : studentScore;
}
else
{
reultType = InteractReultType.TP;
// 2 * 0.3 * 10= 6
interactScore= studentScore==0 ? 1/(InteractWeight.TT-InteractWeight.T1) * (InteractWeight.TP-InteractWeight.T1) * questionScore : studentScore;
}
}
}
else
{
weight=InteractWeight.T1+(CalculateSimilarity(answers![0], ans0[0]) *(InteractWeight.TT-InteractWeight.T1));
if (weight==InteractWeight.T1)
{
reultType = InteractReultType.T1;
interactScore=studentScore;
}
else if (weight>InteractWeight.TT)
{
reultType = InteractReultType.TT;
interactScore=studentScore==0 ? questionScore : studentScore;
}
else
{
reultType = InteractReultType.TP;
// 2 * 0.3 * 10= 6
interactScore= studentScore==0 ? 1/(InteractWeight.TT-InteractWeight.T1) * (InteractWeight.TP-InteractWeight.T1) * questionScore : studentScore;
}
}
}
}
}
}
}
else
{
//没有作答
weight= InteractWeight.T0;
reultType = InteractReultType.T0;
interactScore=studentScore;
}
}
else
{
//没有标准答案的情况
if (ans0.IsNotEmpty())
{
bool hasAns = false;
ans0.ForEach(x => {
if (!string.IsNullOrWhiteSpace(x))
{
hasAns = true;
}
});
if (hasAns)
{
//作答了
weight= InteractWeight.T1;
reultType = InteractReultType.T1;
interactScore=studentScore;
}
else
{
//没有作答
weight= InteractWeight.T0;
reultType = InteractReultType.T0;
interactScore=studentScore;
}
}
else
{
//没有作答
weight= InteractWeight.T0;
reultType = InteractReultType.T0;
interactScore=studentScore;
}
//如果教师手动给了分或AI评分
if (questionScore>0 && studentScore>0)
{
weight = studentScore * 1.0 / questionScore* (InteractWeight.TT-InteractWeight.T1);
if (weight==InteractWeight.T1)
{
reultType = InteractReultType.T1;
interactScore=studentScore;
}
else if (weight>InteractWeight.TT)
{
reultType = InteractReultType.TT;
interactScore=studentScore==0 ? questionScore : studentScore;
}
else
{
reultType = InteractReultType.TP;
interactScore= studentScore==0 ? 1/(InteractWeight.TT-InteractWeight.T1) * (InteractWeight.TP-InteractWeight.T1) * questionScore : studentScore;
}
}
}
return (weight, reultType, interactScore);
}
///
/// C# 代码 如何判断两句话是否一个意思,非机器学习的算法。使用Levenshtein距离来评估两个字符串的相似度,但是不能判断它们是否表达了同一个意思,后续借助AI实现
///
///
///
///
public static double CalculateSimilarity(string s1, string s2)
{
int n = s1.Length;
int m = s2.Length;
int[,] d = new int[n + 1, m + 1];
for (int i = 0; i <= n; i++)
{
d[i, 0] = i;
}
for (int j = 0; j <= m; j++)
{
d[0, j] = j;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;
d[i, j] = Math.Min(Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost);
}
}
return (1.0 - ((double)d[n, m] / Math.Max(s1.Length, s2.Length)));
}
public static async Task> GetExamInfo(LessonRecord item, TimeLineData? timeLineData, AzureStorageFactory _azureStorage/*,ILogger _logger*/, string owner)
{
//读取ExamData
List examDatas = new List();
try
{
var examPages = timeLineData?.events.Where(x => !string.IsNullOrWhiteSpace(x.Pgid) && !string.IsNullOrWhiteSpace(x.ExamId));
if (examPages!=null && examPages.Count()>0)
{
var examsFiles = await _azureStorage.GetBlobContainerClient(owner).List($"records/{item.id}/Exam");
var paperFiles = await _azureStorage.GetBlobContainerClient(owner).List($"records/{item.id}/ExamPaper");
foreach (var examsFile in examsFiles)
{
if (examsFile.EndsWith("Exam.json"))
{
ExamData? examData = null;
try
{
BlobDownloadResult examDataDownload = await _azureStorage.GetBlobContainerClient(owner).GetBlobClient(examsFile).DownloadContentAsync();
var str = examDataDownload.Content.ToString().Replace("\r\n", "").Replace("\ufeff", "").Replace("\"publish\": \"0\"", "\"publish\": 0").Replace("\"publish\": \"1\"", "\"publish\": 1");
examData= str.ToObject();
// examData = examDataDownload.Content.ToObjectFromJson();
}
catch (Exception ex)
{
if (!ex.Message.Contains("The specified blob does not exist"))
{
// _logger.LogError(ex, $"文件不存在:{examsFile}");
}
}
if (examData!=null && examData.exam.papers.IsNotEmpty())
{
string paperId = examData.exam.papers.First().id;
if (_azureStorage.GetBlobContainerClient(owner).GetBlobClient($"/records/{item.id}/ExamPaper/{paperId}/index.json").Exists())
{
LessonPaper lessonPaper = null;
try
{
BlobDownloadResult paperblobDownload = await _azureStorage.GetBlobContainerClient(owner).GetBlobClient($"/records/{item.id}/ExamPaper/{paperId}/index.json").DownloadContentAsync();
lessonPaper = paperblobDownload.Content.ToObjectFromJson();
examData.paper = lessonPaper;
}
catch (Exception ex)
{
if (!ex.Message.Contains("The specified blob does not exist"))
{
// _logger.LogError(ex, $"文件不存在:/records/{item.id}/ExamPaper/{paperId}/index.json");
}
}
}
examDatas.Add(examData);
}
}
}
}
}
catch (Exception ex)
{
// _logger.LogError(ex, ex.Message);
}
return examDatas;
}
///
/// 获取课中评测数据
///
///
///
///
///
///
///
public static List GetExamData(LessonBase lessonBase, TimeLineData timeLineData, List examDatas, List studentLessonDatas, List objectiveTypes, string lessonId)
{
foreach (var examData in examDatas)
{
//直接取第一个元素的试卷,因为在HiTeach中,只会是一个试卷(一个科目),一个班参与。
var allocation = examData?.exam?.papers?.FirstOrDefault()?.point?.Sum();
var answersStd = examData?.exam?.papers?.FirstOrDefault()?.answers;
List> answers = new List>();
if (answersStd!=null)
{
answersStd.ForEach(x => //去除[""]此种类型的标准答案,转为[]
{
List ans = new List();
if (x.Count!=0)
{
if (x.Count==1)
{
if (string.IsNullOrWhiteSpace(x[0]))
{
answers.Add(ans);
}
else
{
answers.Add(x);
}
}
else
{
answers.Add(x);
}
}
else
{
answers.Add(ans);
}
});
}
examData?.examClassResult?.ForEach(item => {
//学生下标
int index = 0;
if (item.studentAnswersArray.Count()>0
&& item.studentAnswersArray.Count() == item.studentIds.Count() //学生作答数量和学生id数量一致
&& item.studentScores.Count()==item.studentIds.Count()) //学生分数和学生id数量一致
{
item.studentAnswersArray.ForEach(stu => {
var student = studentLessonDatas.Find(x => x.id!.Equals(item.studentIds[index]));
if (student!=null && student.attend==1)
{
//是否要判断主观题或者客观题, 多套试卷,有主观题的
//,如果没获得结果,
//主观题有回答的:608942756458532864\Clients\18782481024\Ans\27-4341670635487887360-examExchangeAnswerlist
//27 从1开始的学生序号-4341670635487887360评测编号,内容qNo 是从1开始的题号。
if (stu.IsNotEmpty() && answers.Count()==stu.Count && examData.exam.papers[0].type.Count()==answers.Count)
{
StudentExamRecord studentExam = new StudentExamRecord();
var studentScore = item.studentScores[index];
List answerRecords = new List();
//题目下标
int itemIndex = 0;
stu.ForEach(ans =>
{
bool objective = objectiveTypes.Contains(examData.exam.papers[0].type[itemIndex]);
var questionScore = examData.exam.papers[0].point[itemIndex];
string type = examData.exam.papers[0].type[itemIndex];
var res = GetInteractResultHasAnswer(answers[itemIndex], ans, objective, type, questionScore, studentScore[itemIndex]);
ItemRecord interactRecord = new ItemRecord()
{
itemType="SPQStrt",//类型
resultType=res.reultType,//作答结果类型
resultWeight=res.weight,//得分权重
criterion= questionScore,//标准分
itemScore= studentScore[itemIndex]//得分
};
answerRecords.Add(interactRecord);
itemIndex++;
});
studentExam.score= answerRecords.Where(x => x.itemScore>=0).Select(x => x.itemScore).Sum();//得分
studentExam.scoreRate= allocation.HasValue && allocation.Value>0 ? studentExam.score * 1.0/allocation.Value : 0;//得分率
studentExam.answerRate= answerRecords.Where(x => x.resultWeight>0).Count()*1.0/studentScore.Count();//作答率
studentExam.examId=examData.exam.id;
studentExam.itemRecords=answerRecords;
student.examRecords.Add(studentExam);
}
}
index++;
});
}
});
}
return studentLessonDatas;
}
///
/// 协作参与率 态度计算
///
///
///
///
///
///
///
public static List GetCoworkData(LessonBase lessonBase, TimeLineData timeLineData, List coworkDatas, List studentLessonDatas, string lessonId)
{
int p = 0;
foreach (var coworkData in coworkDatas)
{
var keys = coworkData.participateLevelList.Keys;
foreach (var key in keys)
{
var student = studentLessonDatas.Find(x => x.seatID!.Equals(key));
if (student!=null && student.attend==1)
{
var score = coworkData.participateLevelList[key];//协作得分,是否是经过指数计算的
var itemRecord = new ItemRecord { criterion=-1, itemType= coworkData.coworkType, itemScore=score, isGroup= coworkData.coworkType.Equals("Group") ? true : false };
//不能完全依赖
if (score>0)
{
student.coworkScore.Add(score);
itemRecord.resultWeight = InteractWeight.TP;
itemRecord.resultType = InteractReultType.TP;
}
else
{
itemRecord.resultWeight = InteractWeight.T0;
itemRecord.resultType = InteractReultType.T0;
}
student.coworkRecord.itemRecords.Add(itemRecord);
}
if (key.Contains("g", StringComparison.OrdinalIgnoreCase))
{
string groupId = key.Replace("g", "").Replace("G", "");
var score = coworkData.participateLevelList[key];
if (score>0)
{
var groupStu = studentLessonDatas.FindAll(x => x.attend==1 && !string.IsNullOrWhiteSpace(x.groupId) && x.groupId.Equals(groupId));
if (groupStu.IsNotEmpty())
{
foreach (var stu in groupStu)
{
stu.group_coworkScore.Add(score);
stu.coworkRecord.itemRecords[p].itemScore+=score;
stu.coworkRecord.itemRecords[p].resultWeight=InteractWeight.TP;
stu.coworkRecord.itemRecords[p].resultType=InteractReultType.TP;
}
}
}
}
}
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())
{
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())
{
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);
}
foreach (var student in studentLessonDatas)
{
if (student.attend==1 && student.coworkRecord.itemRecords.Count>=p+1 && student.coworkRecord.itemRecords[p].itemScore>0)
{
student.coworkRecord.itemRecords[p].resultType=InteractReultType.TP;
var data = MinMaxNormalization(min, max, student.coworkRecord.itemRecords[p].itemScore);
student.coworkRecord.itemRecords[p].resultWeight=InteractWeight.T1+ data * 1.0 / 100 * (InteractWeight.TT-InteractWeight.T1);
if (maxItems.Select(x => x.seatID).Contains(student.seatID))
{
student.coworkRecord.itemRecords[p].resultType= InteractReultType.TT;
student.coworkRecord.itemRecords[p].resultWeight= InteractWeight.TT;
}
}
}
p++;
}
return studentLessonDatas;
}
///
/// 处理学生回推数据,并将回推纳入学习态度计算。
///
///
///
///
///
///
public static List GetTaskData(LessonBase lessonBase, TimeLineData timeLineData, List taskDatas, List studentLessonDatas, string lessonId)
{
//协作也算任务的一种,'WrkSpaceLoad' 作品收集, "isGroupItem": false,
int indexTask = 0;
foreach (var taskData in taskDatas)
{
//作品收集是全部人员都要参加
foreach (var student in studentLessonDatas)
{
if (student.attend==1)
{
var work = taskData.clientWorks.Find(x => $"{x.seatID}".Equals(student.seatID));
if (work!= null)
{
if (work.blobFiles.Count>0)
{
student.uploadCount.Add(work.blobFiles.Count);
}
student.taskRecord.itemRecords.Add(new ItemRecord { itemType="WrkSpaceLoad", itemScore=work.blobFiles.Count *10, resultWeight=InteractWeight.TT, resultType=InteractReultType.TT, isGroup= work.isGroupItem, optCount=work.blobFiles.Count });
}
else
{
student.taskRecord.itemRecords.Add(new ItemRecord { itemType="WrkSpaceLoad", itemScore=0, resultWeight=InteractWeight.T0, resultType=InteractReultType.T0, isGroup= false });
}
}
}
////////
///需要处理小组的情况,当前人员没有提交作品,但是有可能是小组其他人员提交了,需要判断一下。
///
var students = studentLessonDatas.FindAll(x => x.attend==1 && x.taskRecord.itemRecords[indexTask].isGroup==true);
foreach (var student in students)
{
var groupStudents = studentLessonDatas.FindAll(x => x.id!=student.id && x.attend==1 && !string.IsNullOrWhiteSpace(x.groupId) && x.groupId.Equals(student.groupId));
foreach (var groupstudent in groupStudents)
{
groupstudent.taskRecord.itemRecords[indexTask].isGroup=true;
groupstudent.taskRecord.itemRecords[indexTask].optCount=student.taskRecord.itemRecords[indexTask].optCount;
groupstudent.taskRecord.itemRecords[indexTask].itemScore=student.taskRecord.itemRecords[indexTask].itemScore;
groupstudent.taskRecord.itemRecords[indexTask].resultWeight=student.taskRecord.itemRecords[indexTask].resultWeight;
groupstudent.taskRecord.itemRecords[indexTask].resultType=student.taskRecord.itemRecords[indexTask].resultType;
}
}
var groupDatas = taskData.clientWorks.FindAll(x => x.seatID==0 && x.isGroupItem);
foreach (var groupData in groupDatas)
{
var groupStudents = studentLessonDatas.FindAll(x => x.attend==1 && !string.IsNullOrWhiteSpace(x.groupId) && x.groupId.Equals(groupData.groupID));
foreach (var student in groupStudents)
{
student.taskRecord.itemRecords[indexTask].isGroup=true;
student.taskRecord.itemRecords[indexTask].optCount=groupData.blobFiles.Count;
student.taskRecord.itemRecords[indexTask].itemScore= 10* groupData.blobFiles.Count;
if (groupData.blobFiles.Count>0)
{
student.taskRecord.itemRecords[indexTask].resultWeight=InteractWeight.TT;
student.taskRecord.itemRecords[indexTask].resultType=InteractReultType.TT;
}
else
{
student.taskRecord.itemRecords[indexTask].resultWeight=InteractWeight.T0;
student.taskRecord.itemRecords[indexTask].resultType=InteractReultType.T0;
}
}
}
indexTask++;
}
return studentLessonDatas;
}
///
///评分参与率 态度计算
///读取互评信息
///评分相关 在SmartRating.json 处理 GrandRating 星光大评分, 投票Voting 和 PeerAssessment(All每人多件评分,Two随机分配互评, Self自评)
///Event 过滤类型 'RatingStart'
///smartRateSummary.mutualSummary.mutualType 互评【All(每人多件评分) Two(随机分配互评) Self(自评)】 smartRateSummary.meteor_VoteSummary 投票
///读取SmartRating.json
///
///
///
///
///
///
public static List GetSmartRatingData(LessonBase lessonBase, TimeLineData timeLineData, List smartRatingDatas, List studentLessonDatas, string lessonId)
{
int index = 0;
foreach (var smartRatingData in smartRatingDatas)
{
string type = "";
//投票类型的
var keys_vote = smartRatingData.smartRateSummary?.meteor_VoteSummary?.Keys?.ToList();
if (keys_vote.IsNotEmpty())
{
type="Voting";
bool addData = false;
foreach (var key in keys_vote!)
{
try
{
//问题数据F:\lesson-local\632424798693232640-local.json pclxxx
if (smartRatingData.smartRateSummary!.voteDetailResult.TryGetValue(key, out var value))
{
var voteDetailResults = smartRatingData.smartRateSummary!.voteDetailResult[key];
foreach (var student in studentLessonDatas)
{
if (student.attend==1)
{
//投票是全员参与
var datasS = voteDetailResults.FindAll(x => x.id.Equals(student.seatID));
if (datasS.IsNotEmpty())
{
//T1,只有评论别人,没被别人评论 或者是评论了别人,但是没有被别人评论,
student.rateingRecord.itemRecords.Add(new ItemRecord { itemType=type, resultType=InteractReultType.T1, resultWeight = InteractWeight.T1 });
addData=true;
}
else
{ //T0 是没有评论别人,也没被别人评论,
student.rateingRecord.itemRecords.Add(new ItemRecord { itemType=type, resultType=InteractReultType.T0, resultWeight = InteractWeight.T0 });
addData=true;
}
//T0 是没有评论别人,也没被别人评论,
//T1,只有评论别人,没被别人评论 或者是评论了别人,但是没有被别人评论,
//TP 有被别人评论,且评论了别人,
//TT是评论了别人,且被别人评论次数最高,或者分值最高。
}
}
}
}
catch (Exception ex)
{
throw new Exception($"{lessonId}\n{ex.Message}\n{ex.StackTrace}");
}
var meteor_VoteSummary = smartRatingData.smartRateSummary!.meteor_VoteSummary[key];
var order = meteor_VoteSummary.OrderByDescending(x => x.result);
var maxItems = meteor_VoteSummary.FindAll(x => x.result==order.First().result);
double max = 0;
if (maxItems.IsNotEmpty())
{
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())
{
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
//排名 = (积分 - 最低积分) / (最高积分 - 最低积分) * (最大排名 - 最小排名) + 最小排名
foreach (var datasD in meteor_VoteSummary)
{
//有被人评论或投票
var student = studentLessonDatas.Find(x => x.seatID!.Equals(datasD.id));
if (student!=null)
{
if (index x.id).Contains(student.seatID))
{
student.rateingRecord.itemRecords[index].resultType= InteractReultType.TT;
student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.TT;
}
}
}
}
}
if (addData)
{
index++;
}
}
}
//星光大评分,全员评分
var keys_GrandRating = smartRatingData.smartRateSummary?.scoreDetailResult?.Keys?.ToList();
if (keys_GrandRating.IsNotEmpty() && smartRatingData.smartRateSummary!=null && smartRatingData.smartRateSummary.meteor_ScoreSummary.IsNotEmpty())
{
bool addData = false;
type="GrandRating";
foreach (var student in studentLessonDatas)
{
if (student.attend==1)
{
if (keys_GrandRating!.Contains(student.seatID!))
{
//T1,只有评论别人,没被别人评论 或者是评论了别人,但是没有被别人评论,
student.rateingRecord.itemRecords.Add(new ItemRecord { itemType=type, resultType=InteractReultType.T1, resultWeight = InteractWeight.T1 });
addData = true;
}
else
{
//T0 是没有评论别人,也没被别人评论,
student.rateingRecord.itemRecords.Add(new ItemRecord { itemType=type, resultType=InteractReultType.T0, resultWeight = InteractWeight.T0 });
addData = true;
}
}
}
var order = smartRatingData.smartRateSummary.meteor_ScoreSummary.Where(x => x.result>0||!string.IsNullOrWhiteSpace(x.comment)).OrderByDescending(x => x.result);
if (order.Count()>0)
{
var maxItems = smartRatingData.smartRateSummary.meteor_ScoreSummary.FindAll(x => x.result==order.First().result);
double max = 0;
if (maxItems.IsNotEmpty())
{
max = smartRatingData.smartRateSummary.meteor_ScoreSummary.FindAll(x => x.result==order.First().result).First().result;
}
double min = 0;
if (smartRatingData.smartRateSummary.meteor_ScoreSummary.FindAll(x => x.result==order.Last().result).IsNotEmpty())
{
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)
{
var student = studentLessonDatas.Find(x => x.seatID!.Equals(meteor_ScoreSummary.id));
if (student!=null)
{
if (index x.id).Contains(student.seatID) &&student.rateingRecord.itemRecords[index].itemScore>0)
{
student.rateingRecord.itemRecords[index].resultType= InteractReultType.TT;
student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.TT;
}
}
}
}
}
}
if (addData)
{
index++;
}
}
// 互评 PeerAssessment(All每人多件评分,Two随机分配互评, Self自评)
var keys_PeerAssessment = smartRatingData.smartRateSummary?.mutualDetailSummary?.Keys?.ToList();
if (keys_PeerAssessment.IsNotEmpty() && smartRatingData.smartRateSummary?.mutualSummary!=null
&& smartRatingData.smartRateSummary.mutualSummary.mutualResults.IsNotEmpty()
&& smartRatingData.smartRateSummary.mutualSummary.materialInfos.IsNotEmpty())
{
bool addData = false;
type="PeerAssessment";
foreach (var student in studentLessonDatas)
{
if (student.attend==1)
{
if (keys_PeerAssessment!.Contains(student.seatID!))
{
//T1,只有评论别人,没被别人评论 或者是评论了别人,但是没有被别人评论,
student.rateingRecord.itemRecords.Add(new ItemRecord { itemType=type, resultType=InteractReultType.T1, resultWeight = InteractWeight.T1 });
addData = true;
}
else
{
//T0 是没有评论别人,也没被别人评论,
student.rateingRecord.itemRecords.Add(new ItemRecord { itemType=type, resultType=InteractReultType.T0, resultWeight = InteractWeight.T0 });
addData = true;
}
}
}
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())
{
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;
}
var sum = smartRatingData.smartRateSummary.mutualSummary.mutualResults.Sum(x => x.result);
foreach (var mutualResult in smartRatingData.smartRateSummary.mutualSummary.mutualResults)
{
var student = studentLessonDatas.Find(x => x.seatID!.Equals(mutualResult.id));
if (student!=null)
{
if (index x.id).Contains(student.seatID))
{
student.rateingRecord.itemRecords[index].resultType= InteractReultType.TT;
student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.TT;
}
}
}
}
}
if (addData)
{
index++;
}
}
}
return studentLessonDatas;
}
///
/// 最小-最大归一化(Min-Max Normalization)算法。这种算法通常用于将数据的特征值缩放到一个指定的范围内,通常是0到1之间,或者任何其他指定的范围。
///
///
public static double MinMaxNormalization(double min, double max, double x, double minRank = 1, double maxRank = 100)
{
//排名指数计算=( 当前值分数- 298) / (9992 - 298) * (99 - 60) + 60
//将每个人的积分转化为60-100
//排名 = (积分 - 最低积分) / (最高积分 - 最低积分) * (最大排名 - 最小排名) + 最小排名
return x==0 ? 0 : max-min!=0 ? (x - min)*1.0 / (max - min) * (maxRank - minRank) + minRank : (x)*1.0 / (max) * (maxRank - minRank) + minRank;
}
///
/// 处理学生课中数据
///
///
///
///
public static List ProcessStudentDataV2(List studentLessonDatas, LessonDataAnalysisCluster lessonDataAnalysis)
{
//历史记录的个人计分集合,通过“2倍标准差规则”移除异常值后得到的集合
var max_q = lessonDataAnalysis.pscore.Max();
//历史记录的互动计分集合,通过“2倍标准差规则”移除异常值后得到的集合
var max_t = lessonDataAnalysis.tscore.Max();
//历史记录的小组计分集合,通过“2倍标准差规则”移除异常值后得到的集合
var max_h = lessonDataAnalysis.gscore.Max();
var j = InteractWeight.T1;
double t = InteractWeight.TT;
List lessonItems = new List();
foreach (var studentLessonData in studentLessonDatas)
{
StudentLessonItem lessonItem = new StudentLessonItem() { studentId= studentLessonData.id! };
double u = 0.0;
if (studentLessonData.attend==1)
{
u=100.0;
}
//c个人计分指数,d互动计分指数,e小组计分指数
double d = 0, e = 0;
//本节课教师手动给学生的个人计分
var s = studentLessonData.pscore;
//个人计分指数
double c = GetPersent(lessonDataAnalysis.pscore, s).persent;// s*1.0/max_q;
{
//互动相关的计分
//课例互动次数
double n = studentLessonData.interactRecord.interactRecords.Count()*1.0;
if (n>0)
{
//是IES大陆正式站历史课例数据,自2024-03-01至2024-10-08日,互动指数或学法指数黄灯或绿灯,不包含醍摩豆学校及测试学校,课例时长超过5分钟的有效课例(10,680笔数据) 的IRS互动+抢权+挑人的次数集合,
//通过“2倍标准差规则” 移除异常值后得到的集合,再通过K-Means聚类算法得到高低位阶互动频次两个集合,并根据当前课例互动次数位阶的集合的质心值,该值定为m值
IEnumerable all = lessonDataAnalysis.levelInteract.SelectMany(x => x.Value);
var currMacth = lessonDataAnalysis.levelInteract.FindAll(x => x.Value.Min()<=n && x.Value.Max()>=n);
KeyValuePair> curr = new KeyValuePair>();
if (currMacth!=null && currMacth.Count()>0)
{
curr = currMacth.MinBy(x => x.Key);
}
else
{
curr = lessonDataAnalysis.levelInteract.MaxBy(x => x.Key);
}
var p = LessonETLService.GetPersent(all, n);
var l = nlessonDataAnalysis.interactGood ? lessonDataAnalysis.interactHigh : lessonDataAnalysis.interactMedium;
//出题系数=当前互动次数与互动通过次数之间的比例*当前互动次数与互动中位数之间的比例*当前互动次数与互动高阶互动频次的比例
var m = (n*1.0/l) *(p.persent/100) * (curr.Value.Count*1.0/all.Count());
//学生作答次数
var w = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Count()*1.0;
//作答正确数(包括部分正确)
var r = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.T1).Count()*1.0;
//有参与的权重集合60≤k(x)≤100
var kw = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Sum(x => x.resultWeight*1.0);
//有得分的权重集合60 x.resultWeight>InteractWeight.T1).Sum(x => x.resultWeight*1.0);
//本节课的所有互动计分
var i = studentLessonData.interactRecord.interactRecords.Sum(x => x.itemScore*1.0);
//互动计分指数
d = GetPersent(lessonDataAnalysis.tscore, i).persent; //i*1.0/max_t;
//互动成效指数
var a = 1.0;
if (w==0)
{
a = kw/10/n;
}
else
{
if (r==0)
{
a = (kw/(10*w))*(w/n);
}
else
{
a = (kw/(10*w))*(w/n)+er/(r*10)*(r/w);
}
}
//c+a= 个人计分指数+ 个人互动成效指数
//互动成效
var f1 = Math.Round(190*1.0/(1+Math.Exp(-(a*m)))-95, 4);
if (f1==0)
{
if (d>0 && c==0)
{
f1=d*0.6;
}
else if (d==0 && c>0)
{
f1=c*0.6;
}
else
{
f1=(d*0.6+c*0.6)/2;
}
}
else
{
//如果有互动计分,则互动成效指数取0.8 0.2
var dy = (95-f1)/95/2;
if (dy>0.2)
{
dy=0.2;
}
if (dy<0.1) {
dy=0.1;
}
f1=f1*(dy>0.1? 1-dy : 1-dy*2)+d*dy+c*dy;
}
if (f1>95)
{
f1=95;
}
//var f1 = Math.Round(a*m);
lessonItem.hd_cx=f1;
//互动专注指数
// var b = ((w*w/n)+(r*r/w))*1.0*m;
// var f2 = Math.Round(200*1.0/(1+Math.Exp(-(b)))-100, 4);
double f2 = 0;
//if (w>0)
//{
// double xs = m/n>0.1 ? m/n/10 : m/n;
// if (xs>0.05)
// {
// xs=xs/3;
// }
// lessonItem.hd_xs=Math.Round(xs, 4);
// var b = xs* ((w/n)*0.8+ 0.2 * (w/n)* (r/w));
// f2 = Math.Round(200*1.0/(1+Math.Exp(-(b)))-100, 4);
// if (f2>1)
// {
// f2=100;
// }
// else
// {
// f2=f2*100;
// }
//}
if (w>0) {
//作答正确的也算在参与度中,只是占比比作答率占比更小,占20%,即 0.2 * (w/n)* (r/w)*100,计算结果可能会大于100,则强制限定
f2=(w/n)*100+ 0.2 * (w/n)* (r/w)*100;
if (f2>100) { f2=100; }
}
lessonItem.hd_cy=f2;
lessonItem.hd_cyc=w;
lessonItem.hd_fqc=n;
lessonItem.hd_zqc=r;
lessonItem.gr_jf=s;
}
//studentLessonData.achieve=f1;
//studentLessonData.attitude=f2;
// _logger.LogInformation($"{studentLessonData.id}=>学习成效:{f1}\t学习态度:{f2}\t互动次数:{n}\t参与次数:{w}\t正确次数:{r}\t个人计分:{s}\t{Math.Round(c, 2)}\t互动计分:{i}\t{Math.Round(d, 2)}");
}
{
//评测相关指数
double n = studentLessonData.examRecords.Count()*1.0;
if (n>0)
{
//题目数量
double nq = studentLessonData.examRecords.Sum(x => x.qcount)*1.0;
// double max_e = lessonDataAnalysis.exam.Max();
//得分率
double sum_s = studentLessonData.examRecords.Sum(x => x.scoreRate);
//作答率
double sum_a = studentLessonData.examRecords.Sum(x => x.answerRate);
double f8 = Math.Round(sum_s/n*100, 4);
double f9 = Math.Round(sum_a/n*100, 4);
lessonItem.pc_df=f8;
lessonItem.pc_zd=f9;
}
// _logger.LogInformation($"{studentLessonData.id}=>评测指数:{f8}\t得分率:{Math.Round(sum_s/n,4)}\t专注指数:{f9}\t作答率:{Math.Round(sum_a/n,4)}");
}
{
//小组相关指数
/* PickupNameLst PickupOption PickupNthGrp PickupGrp PickupRange PickupEachGrp PickupDiff PickupWrong PickupNoDiff PickupRight PickupGener PickupWtoW PickupWtoR PickupLSA_WordFreq PickupLSA_Classify 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();
int groupCount = 1;
int memberCount = studentLessonDatas.Count;
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));
if (members!=null && members.Count()>0)
{
memberCount= members.Count();
}
}
var grpPickCount = grpPicks.Count();
double pickRate = 0;
double groupType = 0;
foreach (var grppick in grpPicks)
{
pickRate+= (1.0/groupCount) * (1.0/memberCount)* 100 ;
}
if (grpPickCount>0)
{
pickRate=100- Math.Round(pickRate/grpPickCount,4);
groupType+=1;
lessonItem.xz_tr=grpPickCount;
}
double coworkRate = 0;
if (studentLessonData.group_coworkScore.IsNotEmpty())
{
double coworkGrp = studentLessonData.group_coworkScore.Average();
var coworkData = GetPersent(lessonDataAnalysis.groupCowork, coworkGrp);
coworkRate= coworkData.persent;
groupType+=1;
lessonItem.xz_xz=studentLessonData.group_coworkScore.Sum();
}
double gscoreRate = 0;
if (studentLessonData.gscore>0)
{
var gscoreData = GetPersent(lessonDataAnalysis.gscore, studentLessonData.gscore);
gscoreRate= gscoreData.persent;
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 score = CalculateScore(groupTasks.Sum(x=>x.optCount));
groupType+=1;
lessonItem.xz_sc=groupTasks.Count();
}
double fxGrp = 0;
if (groupType>0) {
fxGrp = (pickRate+coworkRate+gscoreRate+groupTask)/groupType; }
if (groupType==2 &&(pickRate>0 && gscoreRate>0) )
{
fxGrp = (pickRate*0.8+coworkRate+gscoreRate*0.8+groupTask)/groupType;
}
if (groupType==1)
{
fxGrp=(pickRate+coworkRate+gscoreRate+groupTask)*0.8/groupType;
}
lessonItem.hz_nl=Math.Round(fxGrp,4);
}
{
//任务相关指数
double n = studentLessonData.taskRecord.itemRecords.Count()*1.0;
if (n>0)
{
double max_m = lessonDataAnalysis.task.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;
double f4 = Math.Round(190*1.0/(1+Math.Exp(-(y)))-95, 4);
double f5 = Math.Round(200*1.0/(1+Math.Exp(-(l)))-100, 4);
lessonItem.rw_fqc =n;
lessonItem.rw_cyc =w;
lessonItem.rw_zpc =studentLessonData.taskRecord.itemRecords.Sum(x=>x.optCount);
lessonItem.rw_cx =f4;
lessonItem.rw_cy =f5;
double score = 0;
if (w>0)
{
foreach (var item in studentLessonData.taskRecord.itemRecords)
{
score += CalculateScore(item.optCount);
}
}
lessonItem.rw_cx =score*1.0/n;
}
// _logger.LogInformation($"{studentLessonData.id}=>任务指数:{f4}\t专注指数:{f5}\t任务次数:{n}\t参与次数:{w}\t");
}
{
//评价相关指数
double n = studentLessonData.rateingRecord.itemRecords.Count()*1.0;
if (n>0)
{
var v = studentLessonData.rateingRecord.itemRecords.Where(x => x.itemType.Equals("Voting"));
double vc = v.Count()*1.0;
var g = studentLessonData.rateingRecord.itemRecords.Where(x => x.itemType.Equals("GrandRating"));
double gc = g.Count()*1.0;
var p = studentLessonData.rateingRecord.itemRecords.Where(x => x.itemType.Equals("PeerAssessment"));
double pc = p.Count()*1.0;
var vg = v.Sum(x => x.itemScore);
var vo = v.Sum(x => x.optCount);
double vs = vc/n* (vg+ vo);
var gg = g.Sum(x => x.itemScore);
var go = g.Sum(x => x.optCount);
double gs = gc/n* (gg+ go);
var pg = p.Sum(x => x.itemScore);
var po = p.Sum(x => x.optCount);
double ps = pc/n* (pg+ po);
double h = vs+ps+gs;
double f3 = Math.Round(190*1.0/(1+Math.Exp(-(h)))-95, 4);
studentLessonData.appraise=f3;
// _logger.LogInformation($"{studentLessonData.id}=>评价能力:{f3}\t评价次数:{n}\t投票次数:{vc}-{vg}-{vo}\t星光次数:{gc}-{gg}-{go}\t互评次数:{pc}-{pg}-{po}");
lessonItem.pj_nl =f3;
lessonItem.pj_cs =n;
lessonItem.pj_vc =vc;
lessonItem.pj_vg =vg;
lessonItem.pj_vo =vo;
lessonItem.pj_gc =gc;
lessonItem.pj_gg =gg;
lessonItem.pj_go =go;
lessonItem.pj_pc =pc;
lessonItem.pj_pg =pg;
lessonItem.pj_po =po;
}
}
{
//协作相关指数
var n = studentLessonData.coworkRecord.itemRecords.Count()*1.0;
if (n>0)
{
//总的协作成果数
var w = studentLessonData.coworkRecord.itemRecords.Where(x => x.resultWeight>0);
double ss = w.Sum(x => x.itemScore)*1.0;
double sw = w.Sum(x => x.resultWeight)*1.0;
double wc = w.Count()*1.0;
double x = 0.0;
if (wc>0)
{
x=sw/(j *wc);
}
double max_xzcg = 40;
double k = (wc*wc/n+x)/n+ wc*(ss/max_xzcg)* (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;
lessonItem.xz_cyc =wc;
lessonItem.xz_cgf =ss;
lessonItem.xz_cx =f6;
lessonItem.xz_cy =f7;
}
//_logger.LogInformation($"{studentLessonData.id}=>协作指数:{f6}\t专注指数:{f7}\t协作次数:{n}\t参与次数:{wc}\t协作成果分数:{ss}\t{k}");
}
double xx_cx = 0, xx_cy = 0;
int avg_cx = 0, avg_cy = 0;
if (lessonItem.xz_cx>0)
{
avg_cx+=1;
}
if (lessonItem.pj_nl>0)
{
avg_cx+=1;
}
if (lessonItem.rw_cx>0)
{
avg_cx+=1;
}
if (lessonItem.pc_df>0)
{
avg_cx+=1;
}
if (lessonItem.hd_cx>0)
{
avg_cx+=1;
}
if (lessonItem.hz_nl>0)
{
avg_cx+=1;
}
if (avg_cx>0)
{
xx_cx+=Math.Round(lessonItem.hd_cx * 1.0/avg_cx+ lessonItem.pc_df* 1.0/avg_cx+ lessonItem.rw_cx* 1.0/avg_cx+ lessonItem.pj_nl* 1.0/avg_cx+ lessonItem.xz_cx* 1.0/avg_cx+ lessonItem.hz_nl* 1.0/avg_cx,4);
}
if (lessonItem.xz_cy>0)
{
avg_cy+=1;
}
if (lessonItem.pj_nl>0)
{
avg_cy+=1;
}
if (lessonItem.rw_cy>0)
{
avg_cy+=1;
}
if (lessonItem.pc_zd>0)
{
avg_cy+=1;
}
if (lessonItem.hd_cy>0)
{
avg_cy+=1;
}
if (lessonItem.hz_nl>0)
{
avg_cy+=1;
}
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);
}
lessonItem.xx_cx=xx_cx;
lessonItem.xx_cy=xx_cy;
lessonItems.Add(lessonItem);
studentLessonData.achieve= lessonItem.xx_cx;
studentLessonData.attitude= lessonItem.xx_cy;
studentLessonData.appraise= lessonItem.pj_nl;
studentLessonData.cowork= lessonItem.xz_cx;
studentLessonData.cooperation=lessonItem.hz_nl;
}
return lessonItems;
}
static double CalculateScore(int n, double k = 1)
{
if (n == 0)
{
return 0;
}
else
{
double score = 60 + (40 / (1 + Math.Exp(-k * (n - 1))));
return Math.Max(80, Math.Min(score, 100));
}
}
///
/// 使用标准差定义异常值。如果一个数字与平均值的偏差超过某个标准差倍数(例如2倍或3倍),则可以认为它是异常的。
///
///
///
public static List CleanDataBySDThreshold(IEnumerable array, double thresholdMultiplier = 2)
{
if (array.Count() == 0) return new List();
double average = Math.Round(array.Sum()*1.0/array.Count(), 4);
double variance = array.Select(x => Math.Round(Math.Pow(x - average, 2), 4)).Sum()*1.0/array.Count();
double standardDeviation = Math.Sqrt(Math.Round(variance, 4));
double threshold = Math.Round(thresholdMultiplier * standardDeviation);
List datas = new List();
foreach (double value in array)
{
double deviation = Math.Round(Math.Abs(value - average), 4);
if (deviation <= threshold)
{
datas.Add(value);
}
}
return datas;
}
///
///
///
///
///
///
public static async Task ExportToExcelAzureBlob(List items, AzureStorageFactory azureStorage,string owner , string path , XmlDocument xmlDocument)
{
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (var memoryStream = new MemoryStream())
{
using (ExcelPackage package = new ExcelPackage())
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("学生课中数据");
// 获取类的属性
PropertyInfo[] properties = typeof(StudentLessonItem).GetProperties();
// 添加表头
int currentRow = 1;
for (int i = 0; i < properties.Length; i++)
{
string summary = Regex.Replace(GetPropertySummary(properties[i], xmlDocument), @"\s+", "");
worksheet.Cells[currentRow, i + 1].Value = summary;
}
// 填充数据
currentRow = 2;
foreach (var item in items)
{
for (int i = 0; i < properties.Length; i++)
{
worksheet.Cells[currentRow, i + 1].Value = properties[i].GetValue(item);
}
currentRow++;
}
// 设置表格样式
worksheet.Cells[worksheet.Dimension.Address].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left;
worksheet.Cells[worksheet.Dimension.Address].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Top;
// 保存到文件流
await package.SaveAsAsync(memoryStream);
memoryStream.Position=0;
}
await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(memoryStream, "records", path);
}
}
///
/// 导出Excel
///
///
///
///
public static async Task ExportToExcelLocal(List items, string filePath, XmlDocument xmlDocument)
{
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage())
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("学生课中数据");
// 获取类的属性
PropertyInfo[] properties = typeof(StudentLessonItem).GetProperties();
// 添加表头
int currentRow = 1;
for (int i = 0; i < properties.Length; i++)
{
string summary = Regex.Replace(GetPropertySummary(properties[i], xmlDocument), @"\s+", "");
worksheet.Cells[currentRow, i + 1].Value = summary;
}
// 填充数据
currentRow = 2;
foreach (var item in items)
{
for (int i = 0; i < properties.Length; i++)
{
worksheet.Cells[currentRow, i + 1].Value = properties[i].GetValue(item);
}
currentRow++;
}
// 设置表格样式
worksheet.Cells[worksheet.Dimension.Address].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left;
worksheet.Cells[worksheet.Dimension.Address].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Top;
// 保存到文件
FileInfo fileInfo = new System.IO.FileInfo(filePath);
await package.SaveAsAsync(fileInfo);
}
}
private static string GetPropertySummary(PropertyInfo property, XmlDocument xmlDocument)
{
XmlNodeList? xmlNodeList = xmlDocument.DocumentElement?.SelectNodes("//member[@name='P:" + property.DeclaringType?.FullName + "." + property.Name + "']");
if (xmlNodeList!= null && xmlNodeList.Count > 0)
{
XmlNode? xmlNode = xmlNodeList[0];
if (xmlNode != null && xmlNode.FirstChild != null)
{
return xmlNode.FirstChild.InnerText;
}
}
return property.Name;
}
///
/// 当前数超越集合的百分比
///
///
///
///
public static (double persent, int count) GetPersent(IEnumerable nums, double curr)
{
int count = 0;
foreach (var op in nums.OrderBy(x => x))
{
if (op <= curr)
{
count++;
}
else
{
break;
}
}
return (count *1.0/ nums.Count() * 100, count);
}
}
///
/// 学生导出Excel的Entity
///
public class StudentLessonItem
{
///
/// 学生id
///
public string? studentId { get; set; }
///
/// 互动发起次数
///
public double hd_fqc { get; set; } = 0;
///
/// 互动参与次数
///
public double hd_cyc { get; set; } = 0;
///
/// 互动正确次数
///
public double hd_zqc { get; set; } = 0;
///
/// 个人计分
///
public double gr_jf { get; set; } = 0;
///
/// 互动成效指数
///
public double hd_cx { get; set; } = 0;
///
/// 互动专注指数
///
public double hd_cy { get; set; } = 0;
///
/// 评测得分率
///
public double pc_df { get; set; } = 0;
///
/// 评测作答率
///
public double pc_zd { get; set; } = 0;
///
/// 任务发起次数
///
public double rw_fqc { get; set; } = 0;
///
/// 任务参与次数
///
public double rw_cyc { get; set; } = 0;
///
/// 任务作品数
///
public double rw_zpc { get; set; } = 0;
///
/// 任务成效指数
///
public double rw_cx { get; set; } = 0;
///
/// 任务专注指数
///
public double rw_cy { get; set; } = 0;
///
/// 评价发起次数
///
public double pj_cs { get; set; } = 0;
///
/// 投票发起次数
///
public double pj_vc { get; set; } = 0;
///
/// 投票得票数
///
public double pj_vg { get; set; } = 0;
///
/// 投票次数
///
public double pj_vo { get; set; } = 0;
///
/// 星光发起次数
///
public double pj_gc { get; set; } = 0;
///
/// 星光得分数
///
public double pj_gg { get; set; } = 0;
///
/// 星光评分次数
///
public double pj_go { get; set; } = 0;
///
/// 互评发起次数
///
public double pj_pc { get; set; } = 0;
///
/// 互评得分数
///
public double pj_pg { get; set; } = 0;
///
/// 互评评分次数
///
public double pj_po { get; set; } = 0;
///
/// 评价能力
///
public double pj_nl { get; set; } = 0;
///
/// 协作发起次数
///
public double xz_fqc { get; set; } = 0;
///
/// 协作参与次数
///
public double xz_cyc { get; set; } = 0;
///
/// 协作成果分数
///
public double xz_cgf { get; set; } = 0;
///
/// 协作能力指数
///
public double xz_cx { get; set; } = 0;
///
/// 协作专注指数
///
public double xz_cy { get; set; } = 0;
///
/// 小组挑人
///
public double xz_tr { get; set; } = 0;
///
/// 小组计分
///
public double xz_jf { get; set; } = 0;
///
/// 小组协作成果分
///
public double xz_xz { get; set; } = 0;
///
/// 组任务上传数
///
public double xz_sc { get; set; } = 0;
///
/// 合作能力
///
public double hz_nl { get; set; } = 0;
///
/// 学习成效
///
public double xx_cx { get; set; } = 0;
///
/// 学习专注度
///
public double xx_cy { get; set; } = 0;
}
///
/// 历史课例的关键数据模型
///
public class LessonDataAnalysisCluster : LessonDataAnalysisBase
{
///
///
///
// public List>> clustersInteract { get; set; } = new List>>();
/////
/////
/////
//public List>> clustersPscore { get; set; } = new List>>();
/////
/////
/////
//public List>> clustersTscore { get; set; } = new List>>();
/////
/////
/////
//public List>> clustersGscore { get; set; } = new List>>();
public List>> levelInteract { get; set; } = new List>>();
public double interactPass { get; set; }
public double interactGood { get; set; }
public double interactLow { get; set; }
public double interactMedium { get; set; }
public double interactHigh { get; set; }
}
///
///
///
public abstract class LessonDataAnalysisBase
{
/////
///// 协作次数
/////
//public IEnumerable cowork { get; set; } = new List();
/////
/////
/////
//public IEnumerable coworkBase { get; set; } = new List();
///
///
///
public List task { get; set; } = new List();
/////
/////
/////
//public IEnumerable taskBase { get; set; } = new List();
/////
/////
/////
//public IEnumerable exam { get; set; } = new List();
/////
/////
/////
//public IEnumerable examBase { get; set; } = new List();
/////
/////
/////
//public IEnumerable smartRating { get; set; } = new List();
/////
/////
/////
//public IEnumerable smartRatingBase { get; set; } = new List();
///
///
///
public List irs { get; set; } = new List();
///
///
///
public List interactNormal { get; set; } = new List();
///
/// 个人计分
///
public List pscore { get; set; } = new List();
///
/// 小组计分
///
public List gscore { get; set; } = new List();
///
/// 互动计分
///
public List tscore { get; set; } = new List();
///
/// 作品上传数
///
public List> upload { get; set; } = new List>();
///
/// 学生协作成果数
///
public List stuCowork { get; set; } = new List();
///
/// 小组协作成果数
///
public List groupCowork { get; set; } = new List();
///
/// 挑人集合
///
public List> pickup { get; set; } = new List>();
/////
///// 挑人集合-小组
/////
//public List> pickup_group { get; set; } = new List>();
}
///
/// 每月的课例模型数据
///
public class LessonDataAnalysisMonth : LessonDataAnalysisBase
{
///
/// 时间戳
///
public long updateTime { get; set; }
///
/// yyyyMM
///
public string? yearMonth { get; set; }
}
///
///
///
public class LessonLocal
{
///
///
///
public LessonBase? lessonBase { get; set; }
///
///
///
public TimeLineData? timeLineData { get; set; }
///
///
///
public LessonRecord? lessonRecord { get; set; }
///
///
///
public List studentLessonDatas { get; set; } = new List();
///
///
///
public List taskDatas { get; set; } = new List();
///
///
///
public List smartRatingDatas { get; set; } = new List();
///
///
///
public List irsDatas { get; set; } = new List();
///
///
///
public List coworkDatas { get; set; } = new List();
///
///
///
public List examDatas { get; set; } = new List();
///
///
///
public List sokratesDatas { get; set; } = new List();
}
///
///
///
public class TechCount
{
public string? yearMonth { get; set; }
///
///
///
public string? lessonId { get; set; }
///
/// 评测数量
///
public int examCount { get; set; }
///
/// 任务数量
///
public int taskCount { get; set; }
///
/// IRS次数
///
public int irsCount { get; set; }
///
/// 互动次数
///
//public int interactExamCount { get; set; }
///
/// 互动次数
///
public int interactNormalCount { get; set; }
///
/// 协作次数
///
public int coworkCount { get; set; }
///
/// 智能评分次数
///
public int smartRatingCount { get; set; }
///
///
///
public List timeCount { get; set; } = new List();
///
///
///
public IEnumerable pscore { get; set; } = new List();
///
///
///
public IEnumerable gscore { get; set; } = new List();
///
///
///
public IEnumerable tscore { get; set; } = new List();
///
/// 评测数量
///
public int examCountBase { get; set; }
///
/// 任务数量
///
public int taskCountBase { get; set; }
///
/// IRS次数
///
public int irsCountBase { get; set; }
///
/// 互动次数
///
//public int interactExamCountBase { get; set; }
///
/// 互动次数
///
public int interactNormalCountBase { get; set; }
///
/// 协作次数
///
public int coworkCountBase { get; set; }
///
/// 智能评分次数
///
public int smartRatingCountBase { get; set; }
///
/// 作品上传数
///
public List> upload { get; set; } = new List>();
///
/// 学生协作成果数
///
public List stuCowork { get; set; } = new List();
///
/// 小组协作成果数
///
public List groupCowork { get; set; } = new List();
public List pickup { get; set; } = new List();
}
}