123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579 |
- 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 Microsoft.OData.UriParser;
- 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
- {
- public static async Task<List<LessonLocal>> FixLocalData(List<string> localIds, AzureCosmosFactory _azureCosmos, AzureStorageFactory _azureStorage, string pathLessons,long stime,long etime)
- {
- if (etime<=1693497600000)
- {
- etime= DateTimeOffset.Now.ToUnixTimeMilliseconds();
- }
-
- List<string> dbids= new List<string>();
- var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
- .GetList<string>($"SELECT value c.id FROM c where ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>={stime} and c.startTime<{etime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' ", null);
- if (resultSchool.list.IsNotEmpty())
- {
- dbids.AddRange(resultSchool.list);
- }
- var resultTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
- .GetList<string>($"SELECT value c.id FROM c where ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>={stime} and c.startTime<{etime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' ", "LessonRecord");
- if (resultTeacher.list.IsNotEmpty())
- {
- dbids.AddRange(resultTeacher.list);
- }
- var newIds= dbids.Except(localIds);
- List<LessonRecord> list=new List<LessonRecord>();
- if (newIds!=null && newIds.Count()>0)
- {
- var resultSchoolLessons = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
- .GetList<LessonRecord>($"SELECT value c.id FROM c where c.id in ({string.Join(",",newIds.Select(x=>$"'{x}'"))}) and ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>={stime} and c.startTime<{etime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' ", null);
- if (resultSchoolLessons.list.IsNotEmpty())
- {
- list.AddRange(resultSchoolLessons.list);
- newIds= newIds.Except(resultSchoolLessons.list.Select(x => x.id));
- }
- if (newIds!=null && newIds.Count()>0)
- {
- var resultTeacherLessons = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
- .GetList<LessonRecord>($"SELECT value c.id FROM c where c.id in ({string.Join(",", newIds.Select(x => $"'{x}'"))}) and ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>={stime} and c.startTime<{etime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' ", "LessonRecord");
- if (resultTeacherLessons.list.IsNotEmpty())
- {
- list.AddRange(resultTeacherLessons.list);
- }
- }
- }
- List<LessonLocal> lessonLocals = new List<LessonLocal>();
- foreach (var record in list)
- {
- var item = await LessonETLService.GetLessonLocal(record, localIds, _azureStorage, pathLessons);
- string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
- item.lessonRecord.learningCategory= item.lessonBase?.summary?.learningCategory;
- if (item.lessonRecord.learningCategory == null)
- {
- item.lessonRecord.learningCategory = new LearningCategory();
- }
- await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json", item.ToJsonString());
- lessonLocals.Add(item);
- }
- return lessonLocals;
- }
- public static int GetRandomValueByWeight(List<WeightedItem> items)
- {
- Random random = new Random();
- double randomWeight = random.NextDouble();
- double cumulativeWeight = 0.0;
- foreach (var item in items)
- {
- cumulativeWeight += item.Weight;
- if (randomWeight <= cumulativeWeight)
- {
- return item.Value;
- }
- }
- // This should not happen if all weights sum up to 1
- return items[items.Count - 1].Value;
- }
- public static List<CodeBool> GetCodeBools (List<StudentLessonData> studentLessonDatas) {
- List<CodeBool> codeBools = new List<CodeBool>() {
- new CodeBool { code="hd",value=false },//互动
- new CodeBool { code="pc",value=false },//评测
- new CodeBool { code="rw",value=false },//任务
- new CodeBool { code="pj",value=false },//评价
- new CodeBool { code="tp",value=false },//投票
- new CodeBool { code="xg",value=false },//星光
- new CodeBool { code="hp",value=false },//互评
- new CodeBool { code="xz",value=false },//协作
- new CodeBool { code="tr",value=false },//挑人
- new CodeBool { code="xztr",value=false },//小组挑人
- new CodeBool { code="xzxz",value=false },//小组协作
- new CodeBool { code="xzrw",value=false },//小组任务
- };
- foreach (var studentLessonData in studentLessonDatas)
- {
- if (studentLessonData.interactRecord.interactRecords.Count>0)
- {
- codeBools.Find(x => x.code.Equals("hd"))!.value=true;
- }
- if (studentLessonData.examRecords.Count>0)
- {
- codeBools.Find(x => x.code.Equals("pc"))!.value=true;
- }
- if (studentLessonData.taskRecord.itemRecords.Count>0 || studentLessonData.uploadCount.Count>0)
- {
- codeBools.Find(x => x.code.Equals("rw"))!.value=true;
- if (studentLessonData.taskRecord.itemRecords.FindAll(x => x.isGroup==true).IsNotEmpty())
- {
- codeBools.Find(x => x.code.Equals("xzrw"))!.value=true;
- }
- }
- if (studentLessonData.rateingRecord.itemRecords.Count>0)
- {
- codeBools.Find(x => x.code.Equals("pj"))!.value=true;
- if (studentLessonData.rateingRecord.itemRecords.FindAll(x => x.itemType!.Equals("GrandRating")).IsNotEmpty())
- {
- codeBools.Find(x => x.code.Equals("xg"))!.value=true;
- }
- if (studentLessonData.rateingRecord.itemRecords.FindAll(x => x.itemType!.Equals("Voting")).IsNotEmpty())
- {
- codeBools.Find(x => x.code.Equals("tp"))!.value=true;
- }
- if (studentLessonData.rateingRecord.itemRecords.FindAll(x => x.itemType!.Equals("PeerAssessment")).IsNotEmpty())
- {
- codeBools.Find(x => x.code.Equals("hp"))!.value=true;
- }
- }
- if (studentLessonData.coworkRecord.itemRecords.Count>0 || studentLessonData.coworkScore.Count>0 || studentLessonData.group_coworkScore.Count>0)
- {
- codeBools.Find(x => x.code.Equals("xz"))!.value=true;
- if (studentLessonData.group_coworkScore.Count>0)
- {
- codeBools.Find(x => x.code.Equals("xzxz"))!.value=true;
- }
- }
- if (studentLessonData.pickups.FindAll(x => x.Contains("grp", StringComparison.OrdinalIgnoreCase)).IsNotEmpty())
- {
- codeBools.Find(x => x.code.Equals("xztr"))!.value=true;
- }
- if (studentLessonData.pickups.IsNotEmpty())
- {
- codeBools.Find(x => x.code.Equals("tr"))!.value=true;
- }
- }
- return codeBools;
- }
- /// <summary>
- /// 生成学生student-analysis.json
- /// </summary>
- /// <param name="objectiveTypes"></param>
- /// <param name="azureStorage"></param>
- /// <param name="lessonLocal"></param>
- /// <returns></returns>
- public static (List<StudentLessonData> studentLessonDatas, List<StudentLessonItem> lessonItems, List<CodeBool> codeBools)
- DoStudentLessonDataV2(List<string> objectiveTypes, LessonLocal lessonLocal, string location, List<StudentSemesterRecord> studentSemesterRecords, List<OverallEducation> overallEducations,
- LessonDataAnalysisModel lessonDataAnalysis, List<Student> studentsBase, List<School> schools)
- {
- List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
- studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
- studentLessonDatas = LessonETLService.GetIRSData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.irsDatas, studentLessonDatas, lessonLocal.examDatas, lessonLocal?.lessonRecord?.id);
- studentLessonDatas = LessonETLService.GetCoworkData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.coworkDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
- studentLessonDatas = LessonETLService.GetExamData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.examDatas, studentLessonDatas, objectiveTypes, lessonLocal.lessonRecord.id);
- studentLessonDatas = LessonETLService.GetSmartRatingData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.smartRatingDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
- studentLessonDatas = LessonETLService.GetTaskData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.taskDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
- var pickupData = LessonETLService.GetPickupData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, studentLessonDatas, lessonLocal.lessonRecord.id);
- studentLessonDatas= pickupData.studentLessonDatas;
- var codeBools = GetCodeBools(studentLessonDatas);
- List<StudentLessonItem> lessonItems = new List<StudentLessonItem>();
- string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
- if (codeBools.FindAll(x => x.value).IsNotEmpty())
- {
- lessonItems = LessonETLService.ProcessStudentDataV2(studentLessonDatas, lessonDataAnalysis, codeBools);
- 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)
- {
- 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)
- {
-
- 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;
- }
- }
- }
-
- 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)
- {
- 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<StudentLessonRecord>()
- };
- overallEducations.Add(overallEducation);
- }
- if (les.attend==1)
- {
- 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;
- }
- }
- else {
- var lesData= overallEducation.les.Find(x => x.id.Equals(lessonLocal.lessonRecord.id));
- if (lesData== null)
- {
- overallEducation.les.Add(new StuLesson { id=lessonLocal.lessonRecord.id, attend=0, time = lessonLocal.lessonRecord.startTime });
- }
- }
-
- }
- }
- }
- }
- }
- }
- return (studentLessonDatas, lessonItems, codeBools);
- }
- public static async Task GenAnalysisData(string pathAnalysis, long newest, List<TechCount> techCounts,AzureStorageFactory azureStorage)
- {
- var yearMonthDatas = techCounts.GroupBy(x => x.yearMonth).Select(x => new { key = x.Key, list = x.ToList() });
- // lessonDataAnalysisMonths = new List<LessonDataAnalysisMonth>();
- LessonDataAnalysisCluster lessonDataAnalysisCluster = new LessonDataAnalysisCluster();
- foreach (var yearMonthData in yearMonthDatas)
- {
- if (string.IsNullOrWhiteSpace(yearMonthData.key))
- {
- Console.WriteLine(yearMonthData.list.Select(x => x.lessonId).ToJsonString());
- }
- 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<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()}");
- //}
- //IEnumerable<double> all = lessonDataAnalysisCluster.clustersInteract.SelectMany(x => x.Value);
- int pass = 0;
- for (var i = 1; i<n; i++)
- {
- var p = LessonETLService.GetPersent(all, i);
- if (p.persent>=60)
- {
- pass = i;
- break;
- }
- }
- var low = all.Where(x => x<pass).Average();
- int good = 0;
- for (var i = 1; i<n; i++)
- {
- var p = LessonETLService.GetPersent(all, i);
- if (p.persent>=80)
- {
- good = i;
- break;
- }
- }
- var medium = all.Where(x => x>=pass &&x<good).Average();
- var high = all.Where(x => x>=good).Average();
- lessonDataAnalysisCluster.interactGood=good;
- lessonDataAnalysisCluster.interactPass=pass;
- lessonDataAnalysisCluster.interactHigh=high;
- lessonDataAnalysisCluster.interactMedium=medium;
- lessonDataAnalysisCluster.interactLow=low;
- 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>>(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 则为自动规划后得到的数字。
- //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<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());
- 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());
- }
- public static async Task<TechCount> GenTeachCount(LessonLocal lessonLocal, AzureStorageFactory azureStorage, List<string> objectiveTypes, List<string> ignore,string pathLessons,AzureCosmosFactory azureCosmos)
- {
- var data = GenStudentLessonData(lessonLocal,objectiveTypes);
- string yearMonth = DateTimeOffset.FromUnixTimeMilliseconds(lessonLocal.lessonRecord.startTime).ToString("yyyyMM");
- if (data.codeBools.FindAll(x => x.value).IsNotEmpty())
- {
- TechCount count = new TechCount();
- count.lessonId=lessonLocal.lessonRecord.id;
- 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= data.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 data.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 (data.studentLessonDatas.Count>0&& taskCount>0 && maxUpload>0)
- {
- var avgUpload = sumUpload*1.0/(data.studentLessonDatas.Count *taskCount);
- count.upload.Add(new List<double>() { avgUpload, maxUpload });
- }
- 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());
- }
- }
- }
- 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) { }
- }
- return null;
- }
- public static (List<StudentLessonData> studentLessonDatas, List<CodeBool> codeBools,List<string> pickup) GenStudentLessonData(LessonLocal lessonLocal, List<string> objectiveTypes)
- {
- List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
- studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
- 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);
- return (studentLessonDatas,codeBools, pickupData.pickup);
- }
- /// <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);
- }
- if (count!=null)
- {
- return count;
- }
- }
- return null;
- }
- public static async IAsyncEnumerable<TechCount> GetTeachCount(AzureCosmosFactory azureCosmos,List<LessonRecord> lessonRecords, List<string> filesLessons, string pathLessons, List<string> ignore, List<string> objectiveTypes, AzureStorageFactory azureStorage,bool force)
- {
- List<TechCount> techCounts = new List<TechCount>();
- foreach (var item in filesLessons)
- {
- if (item.EndsWith("-local.json"))
- {
- string lessonId = item.Split("\\").Last().Replace("-local.json", "");
- string countFile = item.Replace("-local.json", "-count.json");
- TechCount count = null;
- if (!force)
- {
- if (System.IO.File.Exists(countFile))
- {
- string contjson = await System.IO.File.ReadAllTextAsync(countFile);
- count = contjson.ToObject<TechCount>();
- }
- else
- {
- force=true;
-
- }
- }
- if (force)
- {
- string localjson = await System.IO.File.ReadAllTextAsync(item);
- var lessonLocal = localjson.ToObject<LessonLocal>();
- List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
- studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
- studentLessonDatas = LessonETLService.GetIRSData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.irsDatas, studentLessonDatas, lessonLocal.examDatas, lessonLocal.lessonRecord.id);
- studentLessonDatas = LessonETLService.GetCoworkData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.coworkDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
- studentLessonDatas = LessonETLService.GetExamData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.examDatas, studentLessonDatas, objectiveTypes, lessonLocal.lessonRecord.id);
- studentLessonDatas = LessonETLService.GetSmartRatingData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.smartRatingDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
- studentLessonDatas = LessonETLService.GetTaskData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.taskDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
- var pickupData = LessonETLService.GetPickupData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, studentLessonDatas, lessonLocal.lessonRecord.id);
- studentLessonDatas= pickupData.studentLessonDatas;
- var codeBools = LessonETLService.GetCodeBools(studentLessonDatas);
- string yearMonth=DateTimeOffset.FromUnixTimeMilliseconds(lessonLocal.lessonRecord.startTime).ToString("yyyyMM");
- if (codeBools.FindAll(x => x.value).IsNotEmpty())
- {
- if (count==null) { count= new TechCount(); }
- count.lessonId=item.Split("\\").Last().Replace("-local.json", "");
- count.examCount= lessonLocal.examDatas.Count;
- count.taskCount= lessonLocal.taskDatas.Count;
- count.irsCount= lessonLocal.irsDatas.Count;
- count.interactNormalCount=count.irsCount;
- count.coworkCount= lessonLocal.coworkDatas.Count;
- count.smartRatingCount= lessonLocal.smartRatingDatas.Count;
- count.timeCount=lessonLocal.sokratesDatas.Where(x => !ignore.Contains(x.Event) && !x.Event.Contains("End", StringComparison.OrdinalIgnoreCase)).GroupBy(x => x.Event).Select(x => new CodeLong() { code=x.Key, value= x.ToList().Count }).ToList();
- if (lessonLocal.lessonRecord!=null)
- {
- count.yearMonth=yearMonth;
- if (lessonLocal?.lessonBase?.summary!=null)
- {
- count.smartRatingCountBase=lessonLocal.lessonBase.summary.smartRatingCount;
- count.irsCountBase=lessonLocal.lessonBase.summary.interactionCount;
- count.taskCountBase=lessonLocal.lessonBase.summary.collateTaskCount;
- count.coworkCountBase=lessonLocal.lessonBase.summary.coworkTaskCount;
- count.examCountBase=lessonLocal.lessonBase.summary.examCount;
- count.interactNormalCountBase= count.interactNormalCount;
- }
- if (lessonLocal?.lessonBase?.report?.clientSummaryList!=null)
- {
- count.pscore= lessonLocal.lessonBase.report.clientSummaryList.Where(x => x.score>0).Select(x => x.score);
- count.gscore= lessonLocal.lessonBase.report.clientSummaryList.Where(x => x.groupScore>0).Select(x => x.groupScore);
- count.tscore= lessonLocal.lessonBase.report.clientSummaryList.Where(x => x.interactScore>0).Select(x => x.interactScore);
- }
- {
- count.pickup= pickupData.pickup;
- // var techCount = techCounts.Find(x => !string.IsNullOrWhiteSpace(x.lessonId) && !string.IsNullOrWhiteSpace(lessonLocal?.lessonRecord?.id) && x.lessonId.Equals(lessonLocal.lessonRecord.id));
- int sumUpload = 0;
- int taskCount = 0;
- int maxUpload = 0;
- HashSet<string> pickUp = new HashSet<string>();
- foreach (var stu in studentLessonDatas)
- {
- var countS = stu.taskRecord.itemRecords.Where(x => x.optCount>0);
- if (countS.Count()>0)
- {
- int stuUploadmax = stu.taskRecord.itemRecords.Where(x => x.optCount>0).Max(x => x.optCount);
- if (stuUploadmax> maxUpload)
- {
- maxUpload=stuUploadmax;
- }
- }
- int stuUpload = stu.taskRecord.itemRecords.Where(x => x.optCount>0).Sum(x => x.optCount);
- sumUpload+=stuUpload;
- if (stu.taskRecord.itemRecords.Count()> taskCount)
- {
- taskCount=stu.taskRecord.itemRecords.Count();
- }
- var stu_scores = stu.coworkRecord.itemRecords.Where(x => x.itemScore>0).Select(x => x.itemScore);
- if (stu_scores!=null && stu_scores.Count()>0)
- {
- count.stuCowork.AddRange(stu_scores);
- }
- var grp_scores = stu.group_coworkScore.Where(x => x>0);
- if (grp_scores!=null && grp_scores.Count()>0)
- {
- count.groupCowork.AddRange(grp_scores);
- }
- //if (stu.pickups.IsNotEmpty())
- //{
- // foreach (var pickup in stu.pickups)
- // {
- // pickUp.Add(pickup);
- // }
- //}
- }
- if (studentLessonDatas.Count>0&& taskCount>0 && maxUpload>0)
- {
- var avgUpload = sumUpload*1.0/(studentLessonDatas.Count *taskCount);
- count.upload.Add(new List<double>() { avgUpload, maxUpload });
- }
- //if (pickUp.Count>0)
- //{
- // count.pickup.AddRange(pickUp.ToList());
- //}
- string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
- await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-count.json", count.ToJsonString());
- //if (force)
- //{
- //}
- //else
- //{
- // if (lessonRecords.FindAll(x => x.id.Equals(lessonLocal.lessonRecord.id)).IsNotEmpty())
- // {
- // // await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-stu.json", studentLessonDatas.ToJsonString());
- // //只有不是强制更新的时候再去刷新线上的json文件。
- // await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(studentLessonDatas.ToJsonString(), "records", $"{lessonLocal.lessonRecord.id}/student-analysis.json");
- // await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{count.yearMonth}\\{lessonLocal.lessonRecord.id}-count.json", count.ToJsonString());
- // }
- //}
- }
- }
- }
- else
- {
- lessonLocal.lessonRecord.analysis=-1;
- if (lessonLocal.lessonRecord.scope.Equals("school"))
- {
- await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(lessonLocal.lessonRecord, new PartitionKey(lessonLocal.lessonRecord.code));
- }
- else
- {
- await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(lessonLocal.lessonRecord, new PartitionKey(lessonLocal.lessonRecord.code));
- }
- try
- {
- System.IO.File.Delete($"{pathLessons}\\MM{yearMonth}\\{lessonLocal.lessonRecord!.id}-local.json");
- }
- catch (Exception ex) { }
- try
- {
- System.IO.File.Delete($"{pathLessons}\\MM{yearMonth}\\{lessonLocal.lessonRecord!.id}-count.json");
- }
- catch (Exception ex) { }
- }
- }
- if (count!=null)
- {
- yield return count;
- }
- }
- }
- }
- public static List<StudentLessonData> GetBaseInfo(LessonBase lessonBase, List<StudentLessonData> 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;
- }
- /// <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 owner = lessonRecord.scope.Equals("school") ? lessonRecord.school : lessonRecord.tmdid;
- string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(lessonRecord.startTime).ToString("yyyyMM");
- 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 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;
- }
-
- private static async Task<LessonLocal> GetLessonFiles(LessonLocal lessonLocal, List<string> files, string owner, AzureStorageFactory _azureStorage)
- {
- #if DEBUG
- foreach (var file in files)
- {
- 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<TimeLineData>();
- break;
- case bool when file.Contains("IES/base.json"):
- lessonLocal.lessonBase= blobDownloadResult.Content.ToObjectFromJson<LessonBase>();
- break;
- case bool when file.Contains("IES/Task.json"):
- lessonLocal.taskDatas= blobDownloadResult.Content.ToObjectFromJson<List<TaskData>>();
- break;
- case bool when file.Contains("IES/SmartRating.json"):
- lessonLocal.smartRatingDatas= blobDownloadResult.Content.ToObjectFromJson<List<SmartRatingData>>();
- break;
- case bool when file.Contains("IES/IRS.json"):
- lessonLocal.irsDatas= blobDownloadResult.Content.ToObjectFromJson<List<IRSData>>();
- break;
- case bool when file.Contains("IES/Cowork.json"):
- lessonLocal.coworkDatas= blobDownloadResult.Content.ToObjectFromJson<List<CoworkData>>();
- break;
- case bool when file.Contains("Sokrates/SokratesRecords.json"):
- lessonLocal.sokratesDatas= blobDownloadResult.Content.ToObjectFromJson<List<TimeLineEvent>>();
- break;
- }
- }
- }
- catch (RequestFailedException ex)
- {
- }
- catch (Exception ex)
- {
- }
- }
- #else
- 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<TimeLineData>();
- break;
- case bool when file.Contains("IES/base.json"):
- lessonLocal.lessonBase= blobDownloadResult.Content.ToObjectFromJson<LessonBase>();
- break;
- case bool when file.Contains("IES/Task.json"):
- lessonLocal.taskDatas= blobDownloadResult.Content.ToObjectFromJson<List<TaskData>>();
- break;
- case bool when file.Contains("IES/SmartRating.json"):
- lessonLocal.smartRatingDatas= blobDownloadResult.Content.ToObjectFromJson<List<SmartRatingData>>();
- break;
- case bool when file.Contains("IES/IRS.json"):
- lessonLocal.irsDatas= blobDownloadResult.Content.ToObjectFromJson<List<IRSData>>();
- break;
- case bool when file.Contains("IES/Cowork.json"):
- lessonLocal.coworkDatas= blobDownloadResult.Content.ToObjectFromJson<List<CoworkData>>();
- break;
- case bool when file.Contains("Sokrates/SokratesRecords.json"):
- lessonLocal.sokratesDatas= blobDownloadResult.Content.ToObjectFromJson<List<TimeLineEvent>>();
- break;
- }
- }
- }
- catch (RequestFailedException ex)
- {
-
- }
- catch (Exception ex)
- {
-
- }
- });
- #endif
- return lessonLocal;
- }
- /// <summary>
- /// 处理base.json的数据
- /// </summary>
- /// <param name="lessonRecord"></param>
- /// <param name="lessonBase"></param>
- /// <returns></returns>
- public static (LessonBase lessonBase, List<LocalStudent> studentLessonDatas) GetBaseData(LessonBase lessonBase)
- {
- //处理学生定位数据
- List<LocalStudent> studentLessonDatas = new List<LocalStudent>();
- 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);
- }
- /// <summary>
- ///单独处理挑人的逻辑
- ///是否从小组里面挑人。
- ///不需要去重页面,直接获取挑人大类 PickupResult
- ///小类处理:PickupRight , PickupOption , PickupNthGrp ,PickupEachGrp ,PickupDiff , PickupResult 挑人算不算互动?? 读取PickupMemberId "[\r\n 35\r\n]"
- /// </summary>
- /// <param name="lessonBase"></param>
- /// <param name="timeLineData"></param>
- /// <param name="studentLessonDatas"></param>
- /// <param name="lessonId"></param>
- /// <returns></returns>
- public static (List<StudentLessonData> studentLessonDatas, List<string> pickup) GetPickupData(LessonBase lessonBase, TimeLineData timeLineData, List<StudentLessonData> studentLessonDatas, string lessonId)
- {
- var enventsPickup = timeLineData?.events.Where(x => !string.IsNullOrWhiteSpace(x.Pgid) && x.Event.Equals("PickupResult"));
- List<string> pickup = new List<string>();
- if (enventsPickup.IsNotEmpty())
- {
- foreach (var item in enventsPickup)
- {
- List<int> mbrs = item.PickupMemberId.ToObject<List<int>>();
- // 挑人挑中 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);
- }
- /// <summary>
- ///读取互动信息
- ///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
- /// </summary>
- /// <param name="lessonBase"></param>
- /// <param name="timeLineData"></param>
- /// <param name="irsDatas"></param>
- /// <param name="studentLessonDatas"></param>
- /// <param name="examDatas"></param>
- /// <param name="itemFiles"></param>
- /// <returns></returns>
- public static List<StudentLessonData> GetIRSData(LessonBase lessonBase, TimeLineData timeLineData, List<IRSData> irsDatas, List<StudentLessonData> studentLessonDatas, List<ExamData> examDatas, string lessonId)
- {
- List<string> interactTypes = new List<string>() { "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<StudentLessonData> ProcessIRSPageData(List<IRSData> irsDatas, List<StudentLessonData> studentLessonDatas, List<ExamData> 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<List<string>>();
- //根据题去找对应的试卷和评测信息
- 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<string> answers = new List<string>();
- 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<qitem.Count(); i++)
- {
- qitem[i]!["question"]="";
- }
- }
- double questionScore = 0;
- bool objective = false;
- if (_objective!=null)
- {
- objective = _objective.GetValue<bool>();
- }
- //题型
- string type = string.Empty;
- if (_type!=null)
- {
- //题型
- type = _type.GetValue<string>();
- List<string> types = new List<string>() { "single", "multiple", "judge", "sortmultiple" };
- if (types.Contains(type))
- {
- objective = true;
- }
- else
- {
- objective = false;
- }
- }
- if (_answerType!=null)
- {
- _answerType.GetValue<string>();
- //暂不处理,可能存在依然传文字的情况
- //不是文本作答的处理,题目不是客观题,答案不记录
- //if (!_answerType.Equals("text"))
- //{
- // objective=false;
- // answers=new List<string>();
- //}
- }
- if (scoreNode!=null)
- {
- double.TryParse(scoreNode.ToString(), out questionScore);
- }
- string interactType = string.Empty;
- if (irsDataPage.clientAnswers.IsNotEmpty())
- {
- //第一个list是几轮,一次作答,二次作答, 第二个list是学生的下标, 第三个list是 答案
- List<List<List<string>>> clientAnswers = new List<List<List<string>>>();
- 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<ItemRecord> interactRecords = new List<ItemRecord>();
- 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<string, ItemRecord> buzzParticipants = new Dictionary<string, ItemRecord>();
- 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<string>? answers, List<string> ans0, bool objective, string type, double questionScore, double studentScore)
- {
- //List<string> ans0 = new List<string>();
- //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);
- }
- /// <summary>
- /// C# 代码 如何判断两句话是否一个意思,非机器学习的算法。使用Levenshtein距离来评估两个字符串的相似度,但是不能判断它们是否表达了同一个意思,后续借助AI实现
- /// </summary>
- /// <param name="s1"></param>
- /// <param name="s2"></param>
- /// <returns></returns>
- 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<List<ExamData>> GetExamInfo(LessonRecord item, TimeLineData? timeLineData, AzureStorageFactory _azureStorage/*,ILogger<LessonETLService> _logger*/, string owner)
- {
- //读取ExamData
- List<ExamData> examDatas = new List<ExamData>();
- 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>();
- // examData = examDataDownload.Content.ToObjectFromJson<ExamData>();
- }
- 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<LessonPaper>();
- 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;
- }
- /// <summary>
- /// 获取课中评测数据
- /// </summary>
- /// <param name="lessonBase"></param>
- /// <param name="timeLineData"></param>
- /// <param name="examDatas"></param>
- /// <param name="studentLessonDatas"></param>
- /// <param name="objectiveTypes"></param>
- /// <returns></returns>
- public static List<StudentLessonData> GetExamData(LessonBase lessonBase, TimeLineData timeLineData, List<ExamData> examDatas, List<StudentLessonData> studentLessonDatas, List<string> 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<List<string>> answers = new List<List<string>>();
- if (answersStd!=null)
- {
- answersStd.ForEach(x => //去除[""]此种类型的标准答案,转为[]
- {
- List<string> ans = new List<string>();
- 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<ItemRecord> answerRecords = new List<ItemRecord>();
- //题目下标
- 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;
- }
- /// <summary>
- /// 协作参与率 态度计算
- /// </summary>
- /// <param name="lessonBase"></param>
- /// <param name="timeLineData"></param>
- /// <param name="coworkDatas"></param>
- /// <param name="studentLessonDatas"></param>
- /// <param name="lessonId"></param>
- /// <returns></returns>
- public static List<StudentLessonData> GetCoworkData(LessonBase lessonBase, TimeLineData timeLineData, List<CoworkData> coworkDatas, List<StudentLessonData> 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;
- }
- /// <summary>
- /// 处理学生回推数据,并将回推纳入学习态度计算。
- /// </summary>
- /// <param name="lessonBase"></param>
- /// <param name="timeLineData"></param>
- /// <param name="taskDatas"></param>
- /// <param name="studentLessonDatas"></param>
- /// <returns></returns>
- public static List<StudentLessonData> GetTaskData(LessonBase lessonBase, TimeLineData timeLineData, List<TaskData> taskDatas, List<StudentLessonData> 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;
- }
- /// <summary>
- ///评分参与率 态度计算
- ///读取互评信息
- ///评分相关 在SmartRating.json 处理 GrandRating 星光大评分, 投票Voting 和 PeerAssessment(All每人多件评分,Two随机分配互评, Self自评)
- ///Event 过滤类型 'RatingStart'
- ///smartRateSummary.mutualSummary.mutualType 互评【All(每人多件评分) Two(随机分配互评) Self(自评)】 smartRateSummary.meteor_VoteSummary 投票
- ///读取SmartRating.json
- /// </summary>
- /// <param name="lessonBase"></param>
- /// <param name="timeLineData"></param>
- /// <param name="smartRatingDatas"></param>
- /// <param name="studentLessonDatas"></param>
- /// <returns></returns>
- public static List<StudentLessonData> GetSmartRatingData(LessonBase lessonBase, TimeLineData timeLineData, List<SmartRatingData> smartRatingDatas, List<StudentLessonData> 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<student.rateingRecord.itemRecords.Count && student.rateingRecord.itemRecords[index].itemType!.Equals(type))
- {
- if (student.rateingRecord.itemRecords[index].resultType!.Equals(InteractReultType.T0))
- {
- //T1,只有评论别人,没被别人评论 或者是评论了别人,但是没有被别人评论,
- student.rateingRecord.itemRecords[index].resultType= InteractReultType.T1;
- student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.T1;
- }
- else if (student.rateingRecord.itemRecords[index].resultType!.Equals(InteractReultType.T1))
- {
- //TP 有被别人评论,且评论了别人,
- student.rateingRecord.itemRecords[index].resultType= InteractReultType.TP;
- var data = MinMaxNormalization(min, max, datasD.result);
- //student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.TP;
- student.rateingRecord.itemRecords[index].resultWeight=InteractWeight.T1+ data * 1.0 / 100 * (InteractWeight.TT-InteractWeight.T1);
- //获得的票数
- student.rateingRecord.itemRecords[index].itemScore=datasD.result;
- //TT是评论了别人,且被别人评论次数最高,或者分值最高。
- if (maxItems.Select(x => 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<student.rateingRecord.itemRecords.Count && student.rateingRecord.itemRecords[index].itemType!.Equals(type))
- {
- if (student.rateingRecord.itemRecords[index].resultType!.Equals(InteractReultType.T0))
- {
- //T1,只有评论别人,没被别人评论 或者是评论了别人,但是没有被别人评论,
- student.rateingRecord.itemRecords[index].resultType= InteractReultType.T1;
- student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.T1;
- }
- else if (student.rateingRecord.itemRecords[index].resultType!.Equals(InteractReultType.T1))
- {
- //TP 有被别人评论,且评论了别人,
- student.rateingRecord.itemRecords[index].resultType= InteractReultType.TP;
- var data = MinMaxNormalization(min, max, meteor_ScoreSummary.result);
- //student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.TP;
- student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.T1+ data * 1.0 / 100 * (InteractWeight.TT-InteractWeight.T1);
- //被评论次数
- student.rateingRecord.itemRecords[index].itemScore=meteor_ScoreSummary.result;
- //TT是评论了别人,且被别人评论次数最高,或者分值最高。
- if (maxItems.Select(x => 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<student.rateingRecord.itemRecords.Count && student.rateingRecord.itemRecords[index].itemType!.Equals(type))
- {
- if (student.rateingRecord.itemRecords[index].resultType!.Equals(InteractReultType.T0))
- {
- //T1,只有评论别人,没被别人评论 或者是评论了别人,但是没有被别人评论,
- student.rateingRecord.itemRecords[index].resultType= InteractReultType.T1;
- student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.T1;
- }
- else if (student.rateingRecord.itemRecords[index].resultType!.Equals(InteractReultType.T1))
- {
- //TP 有被别人评论,且评论了别人,
- //最高分和最低分,票数最多和票数最少的占比来计算TP的占比
- student.rateingRecord.itemRecords[index].resultType= InteractReultType.TP;
- var data = MinMaxNormalization(min, max, mutualResult.result);
- //student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.TP;
- student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.T1+ data * 1.0 / 100 * (InteractWeight.TT-InteractWeight.T1);
- student.rateingRecord.itemRecords[index].itemScore=mutualResult.result;
- //TT是评论了别人,且被别人评论次数最高,或者分值最高。
- if (maxItems.Select(x => x.id).Contains(student.seatID))
- {
- student.rateingRecord.itemRecords[index].resultType= InteractReultType.TT;
- student.rateingRecord.itemRecords[index].resultWeight= InteractWeight.TT;
- }
- }
- }
- }
- }
- if (addData)
- {
- index++;
- }
- }
- }
- return studentLessonDatas;
- }
- /// <summary>
- /// 最小-最大归一化(Min-Max Normalization)算法。这种算法通常用于将数据的特征值缩放到一个指定的范围内,通常是0到1之间,或者任何其他指定的范围。
- /// </summary>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 处理学生课中数据
- /// </summary>
- /// <param name="studentLessonDatas"></param>
- /// <param name="lessonDataAnalysis"></param>
- /// <returns></returns>
- public static List<StudentLessonItem> ProcessStudentDataV2(List<StudentLessonData> studentLessonDatas, LessonDataAnalysisModel lessonDataAnalysis, List<CodeBool> codeBools)
- {
- //历史记录的个人计分集合,通过“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<StudentLessonItem> lessonItems = new List<StudentLessonItem>();
- 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;
- {
- //智慧挑人
- var zhPicks = studentLessonData.pickups.Where(x => x.StartsWith("1--"));
- int memberCount = studentLessonDatas.Count;
- var zhPickCount = zhPicks.Count();
- double pickRate = 0;
- foreach (var grppick in zhPicks)
- {
- pickRate+= 1.0 * (1.0/memberCount)* 100;
- }
- if (zhPickCount>0)
- {
- pickRate=100- Math.Round(pickRate/zhPickCount, 4);
- lessonItem.pt_tr=zhPickCount;
- lessonItem.zh_tr=pickRate;
- }
- }
- {
- //互动相关的计分
- //课例互动次数
- 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<double> all = lessonDataAnalysis.levelInteract.SelectMany(x => x.Value);
- var currMacth = lessonDataAnalysis.levelInteract.FindAll(x => x.Value.Min()<=n && x.Value.Max()>=n);
- KeyValuePair<double, List<double>> curr = new KeyValuePair<double, List<double>>();
- if (currMacth!=null && currMacth.Count()>0)
- {
- curr = currMacth.MinBy(x => x.Key);
- }
- else
- {
- curr = lessonDataAnalysis.levelInteract.MaxBy(x => x.Key);
- }
- var p = LessonETLService.GetPersent(lessonDataAnalysis.interactNormal, n);
- var l = n<lessonDataAnalysis.interactPass ? lessonDataAnalysis.interactLow : n>lessonDataAnalysis.interactGood ? lessonDataAnalysis.interactHigh : lessonDataAnalysis.interactMedium;
- //出题系数=当前互动次数与互动通过次数之间的比例*当前互动次数与互动中位数之间的比例*当前互动次数与互动高阶互动频次的比例
- // var m = (n*1.0/l) *(p.persent/100) * (curr.Value.Count*1.0/all.Count());
- var m = (n*1.0/l) *(p.persent/100) * (lessonDataAnalysis.interactNormal.Where(x => x.Value>= curr.Value[0]&& x.Value<=curr.Value[1] ).Sum(x=>x.Value)*1.0/lessonDataAnalysis.interactNormal.Sum(x=>x.Value));
- //学生作答次数
- var w = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Count()*1.0;
- //作答正确数(包括部分正确)
- var r = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.T1).Count()*1.0;
- //有参与的权重集合60≤k(x)≤100
- var kw = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>=InteractWeight.T1).Sum(x => x.resultWeight*1.0);
- //有得分的权重集合60<e(x)≤100
- var er = studentLessonData.interactRecord.interactRecords.Where(x => x.resultWeight>InteractWeight.T1).Sum(x => x.resultWeight*1.0);
- //本节课的所有互动计分
- var i = studentLessonData.interactRecord.interactRecords.Sum(x => x.itemScore*1.0);
- //互动计分指数
- 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);
- }
- }
- if (w>0)
- {//c+a= 个人计分指数+ 个人互动成效指数
- //互动成效
- var f1 = Math.Round(80*1.0/(1+Math.Exp(-(a*m)))+20, 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;
- }
- if (f1>0)
- {
- //智慧挑人有被挑中的
- if (lessonItem.zh_tr>0)
- {
- f1=f1*0.8+lessonItem.zh_tr*0.2;
- }
- }
- else
- {
- //智慧挑人有被挑中的
- if (lessonItem.zh_tr>0)
- {
- f1=lessonItem.zh_tr*0.5;
- }
- }
- //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; }
- //智慧挑人有被挑中的
- if (f2>0)
- {
- if (lessonItem.zh_tr>0)
- {
- f2=f2*0.8+lessonItem.zh_tr*0.2;
- }
- }
- else{
- if (lessonItem.zh_tr>0)
- {
- f2=lessonItem.zh_tr*0.5;
- }
- }
-
- }
- 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;
- double a= lessonItem.xz_sc=groupTasks.Sum(x => x.optCount);
- double n = groupTasks.Count();
- double w = groupTasks.Where(x => x.optCount>0).Count();
- groupTask= Math.Round(80*1.0/(1+Math.Exp(-(w/n+(w/n)*(a/w)-1)))+20, 4);
- }
- double fxGrp = 0;
- if (groupType>0) {
- 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.Select(x=>x.Key).Max();
- double w = studentLessonData.taskRecord.itemRecords.Where(x => x.resultWeight>0).Count()*1.0;
-
- lessonItem.rw_fqc =n;
- lessonItem.rw_cyc =w;
- double a = lessonItem.rw_zpc =studentLessonData.taskRecord.itemRecords.Sum(x=>x.optCount);
- //lessonItem.rw_cx =f4;
- // lessonItem.rw_cy =f5;
- double score = 0;
- if (w>0 && lessonItem.rw_zpc>0)
- {
- score= Math.Round(80*1.0/(1+Math.Exp(-(w/n+(w/n)*(a/w)-1)))+20,4);
- }
- lessonItem.rw_cx =score;
- lessonItem.rw_cy =score;
- }
- // _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(200*1.0/(1+Math.Exp(-(h)))-100, 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 = 75;
- //double k = (wc*wc/n+x)/n+ wc*(ss/max_xzcg)* (wc/n);
- //double k = wc/n +wc*(ss/max_xzcg)* (wc/n);
- var avg = lessonDataAnalysis.stuCowork.Select(x => x.Value* x.Key).Sum()*1.0/lessonDataAnalysis.stuCowork.Sum(x => x.Value);
- double k=(GetPersent(lessonDataAnalysis.stuCowork, ss).persent/100+ ss/ avg)* (wc/n );
- // double f6 = Math.Round(190*1.0/(1+Math.Exp(-(k)))-95, 4);
- double 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 =f7;
- 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 && codeBools.FindAll(x=>x.code.Equals("xz") && x.value==true).IsNotEmpty())
- {
- avg_cx+=1;
- }
- if (lessonItem.pj_nl>0 && codeBools.FindAll(x => x.code.Equals("pj") && x.value==true).IsNotEmpty())
- {
- avg_cx+=1;
- }
- if (lessonItem.rw_cx>0 && codeBools.FindAll(x => x.code.Equals("rw") && x.value==true).IsNotEmpty())
- {
- avg_cx+=1;
- }
- if (lessonItem.pc_df>0 && codeBools.FindAll(x => x.code.Equals("pc") && x.value==true).IsNotEmpty())
- {
- avg_cx+=1;
- }
- if (lessonItem.hd_cx > 0 && codeBools.FindAll(x => x.code.Equals("hd") && x.value == true).IsNotEmpty())
- {
- avg_cx+=1;
- }
- if (lessonItem.hz_nl>0 )
- {
- avg_cx+=1;
- }
- //if (lessonItem.zh_tr>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 && codeBools.FindAll(x => x.code.Equals("xz") && x.value==true).IsNotEmpty())
- {
- avg_cy+=1;
- }
- if (lessonItem.pj_nl>0 && codeBools.FindAll(x => x.code.Equals("pj") && x.value==true).IsNotEmpty())
- {
- avg_cy+=1;
- }
- if (lessonItem.rw_cy>0 && codeBools.FindAll(x => x.code.Equals("rw") && x.value==true).IsNotEmpty())
- {
- avg_cy+=1;
- }
- if (lessonItem.pc_zd>0 && codeBools.FindAll(x => x.code.Equals("pc") && x.value==true).IsNotEmpty())
- {
- avg_cy+=1;
- }
- if (lessonItem.hd_cy>0 && codeBools.FindAll(x => x.code.Equals("hd") && x.value==true).IsNotEmpty())
- {
- avg_cy+=1;
- }
- if (lessonItem.hz_nl>0)
- {
- avg_cy+=1;
- }
- //if (lessonItem.zh_tr>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));
- }
- }
- /// <summary>
- /// 使用标准差定义异常值。如果一个数字与平均值的偏差超过某个标准差倍数(例如2倍或3倍),则可以认为它是异常的。
- /// </summary>
- /// <param name="array"></param>
- /// <returns></returns>
- public static List<double> CleanDataBySDThreshold(IEnumerable<double> array, double thresholdMultiplier = 2)
- {
- if (array.Count() == 0) return new List<double>();
- 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<double> datas = new List<double>();
- foreach (double value in array)
- {
- double deviation = Math.Round(Math.Abs(value - average), 4);
- if (deviation <= threshold)
- {
- datas.Add(value);
- }
- }
- return datas;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="items"></param>
- /// <param name="filePath"></param>
- /// <returns></returns>
- public static async Task ExportToExcelAzureBlob(List<StudentLessonItem> items, AzureStorageFactory azureStorage,string owner , string path , XmlDocument xmlDocument,List<string> summarys, PropertyInfo[] properties)
- {
- ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
- using (var memoryStream = new MemoryStream())
- {
- using (ExcelPackage package = new ExcelPackage())
- {
- ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("学生课中数据");
- // 添加表头
- int currentRow = 1;
- #if !DEBUG
- // 获取类的属性
- if(properties==null || properties.Length==0)
- {
- properties = typeof(StudentLessonItem).GetProperties();
- }
- for (int i = 0; i < properties.Length; i++)
- {
- string summary = Regex.Replace(GetPropertySummary(properties[i], xmlDocument), @"\s+", "");
- worksheet.Cells[currentRow, i + 1].Value = summary;
- }
- #else
- for (int i = 0; i < summarys.Count; i++)
- {
- worksheet.Cells[currentRow, i + 1].Value = summarys[i];
- }
- #endif
- // 填充数据
- 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);
- }
- }
- /// <summary>
- /// 导出Excel
- /// </summary>
- /// <param name="items"></param>
- /// <param name="filePath"></param>
- /// <returns></returns>
- public static async Task ExportToExcelLocal(List<StudentLessonItem> 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);
- }
- }
- public 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;
- }
- /// <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>
- /// <param name="nums"></param>
- /// <param name="curr"></param>
- /// <returns></returns>
- public static (double persent, int count) GetPersent(IEnumerable<double> 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);
- }
- }
- /// <summary>
- /// 学生导出Excel的Entity
- /// </summary>
- public class StudentLessonItem
- {
- /// <summary>
- /// 学生id
- /// </summary>
- public string? studentId { get; set; }
- /// <summary>
- /// 互动发起次数
- /// </summary>
- public double hd_fqc { get; set; } = 0;
-
- /// <summary>
- /// 互动参与次数
- /// </summary>
- public double hd_cyc { get; set; } = 0;
- /// <summary>
- /// 互动正确次数
- /// </summary>
- public double hd_zqc { get; set; } = 0;
- /// <summary>
- /// 普通挑人
- /// </summary>
- public double pt_tr { get; set; } = 0;
- /// <summary>
- /// 智慧挑人
- /// </summary>
- public double zh_tr { get; set; } = 0;
- /// <summary>
- /// 个人计分
- /// </summary>
- public double gr_jf { get; set; } = 0;
- /// <summary>
- /// 互动成效指数
- /// </summary>
- public double hd_cx { get; set; } = 0;
- /// <summary>
- /// 互动专注指数
- /// </summary>
- public double hd_cy { get; set; } = 0;
- /// <summary>
- /// 评测得分率
- /// </summary>
- public double pc_df { get; set; } = 0;
- /// <summary>
- /// 评测作答率
- /// </summary>
- public double pc_zd { get; set; } = 0;
- /// <summary>
- /// 任务发起次数
- /// </summary>
- public double rw_fqc { get; set; } = 0;
- /// <summary>
- /// 任务参与次数
- /// </summary>
- public double rw_cyc { get; set; } = 0;
- /// <summary>
- /// 任务作品数
- /// </summary>
- public double rw_zpc { get; set; } = 0;
- /// <summary>
- /// 任务成效指数
- /// </summary>
- public double rw_cx { get; set; } = 0;
- /// <summary>
- /// 任务专注指数
- /// </summary>
- public double rw_cy { get; set; } = 0;
- /// <summary>
- /// 评价发起次数
- /// </summary>
- public double pj_cs { get; set; } = 0;
- /// <summary>
- /// 投票发起次数
- /// </summary>
- public double pj_vc { get; set; } = 0;
- /// <summary>
- /// 投票得票数
- /// </summary>
- public double pj_vg { get; set; } = 0;
- /// <summary>
- /// 投票次数
- /// </summary>
- public double pj_vo { get; set; } = 0;
- /// <summary>
- /// 星光发起次数
- /// </summary>
- public double pj_gc { get; set; } = 0;
- /// <summary>
- /// 星光得分数
- /// </summary>
- public double pj_gg { get; set; } = 0;
- /// <summary>
- /// 星光评分次数
- /// </summary>
- public double pj_go { get; set; } = 0;
- /// <summary>
- /// 互评发起次数
- /// </summary>
- public double pj_pc { get; set; } = 0;
- /// <summary>
- /// 互评得分数
- /// </summary>
- public double pj_pg { get; set; } = 0;
- /// <summary>
- /// 互评评分次数
- /// </summary>
- public double pj_po { get; set; } = 0;
- /// <summary>
- /// 评价能力
- /// </summary>
- public double pj_nl { get; set; } = 0;
- /// <summary>
- /// 协作发起次数
- /// </summary>
- public double xz_fqc { get; set; } = 0;
- /// <summary>
- /// 协作参与次数
- /// </summary>
- public double xz_cyc { get; set; } = 0;
- /// <summary>
- /// 协作成果分数
- /// </summary>
- public double xz_cgf { get; set; } = 0;
- /// <summary>
- /// 协作能力指数
- /// </summary>
- public double xz_cx { get; set; } = 0;
- /// <summary>
- /// 协作专注指数
- /// </summary>
- public double xz_cy { get; set; } = 0;
-
- /// <summary>
- /// 小组挑人
- /// </summary>
- public double xz_tr { get; set; } = 0;
- /// <summary>
- /// 小组计分
- /// </summary>
- public double xz_jf { get; set; } = 0;
- /// <summary>
- /// 小组协作成果分
- /// </summary>
- public double xz_xz { get; set; } = 0;
- /// <summary>
- /// 组任务上传数
- /// </summary>
- public double xz_sc { get; set; } = 0;
- /// <summary>
- /// 合作能力
- /// </summary>
- public double hz_nl { get; set; } = 0;
- /// <summary>
- /// 学习成效
- /// </summary>
- public double xx_cx { get; set; } = 0;
- /// <summary>
- /// 学习专注度
- /// </summary>
- public double xx_cy { get; set; } = 0;
- }
- public class WeightedItem
- {
- public int Value { get; set; }
- public double Weight { get; set; }
- }
- /// <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>
- public class LessonDataAnalysisCluster : LessonDataAnalysisBase
- {
- /// <summary>
- ///
- /// </summary>
- // public List<KeyValuePair<double, List<double>>> clustersInteract { get; set; } = new List<KeyValuePair<double, List<double>>>();
- ///// <summary>
- /////
- ///// </summary>
- //public List<KeyValuePair<double, List<double>>> clustersPscore { get; set; } = new List<KeyValuePair<double, List<double>>>();
- ///// <summary>
- /////
- ///// </summary>
- //public List<KeyValuePair<double, List<double>>> clustersTscore { get; set; } = new List<KeyValuePair<double, List<double>>>();
- ///// <summary>
- /////
- ///// </summary>
- //public List<KeyValuePair<double, List<double>>> clustersGscore { get; set; } = new List<KeyValuePair<double, List<double>>>();
- public List<KeyValuePair<double, List<double>>> levelInteract { get; set; } = new List<KeyValuePair<double, List<double>>>();
- 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; }
- }
- /// <summary>
- ///
- /// </summary>
- public abstract class LessonDataAnalysisBase
- {
- ///// <summary>
- ///// 协作次数
- ///// </summary>
- //public IEnumerable<double> cowork { get; set; } = new List<double>();
- ///// <summary>
- /////
- ///// </summary>
- //public IEnumerable<double> coworkBase { get; set; } = new List<double>();
- /// <summary>
- ///
- /// </summary>
- public List<double> task { get; set; } = new List<double>();
- ///// <summary>
- /////
- ///// </summary>
- //public IEnumerable<double> taskBase { get; set; } = new List<double>();
- ///// <summary>
- /////
- ///// </summary>
- //public IEnumerable<double> exam { get; set; } = new List<double>();
- ///// <summary>
- /////
- ///// </summary>
- //public IEnumerable<double> examBase { get; set; } = new List<double>();
- ///// <summary>
- /////
- ///// </summary>
- //public IEnumerable<double> smartRating { get; set; } = new List<double>();
- ///// <summary>
- /////
- ///// </summary>
- //public IEnumerable<double> smartRatingBase { get; set; } = new List<double>();
- /// <summary>
- ///
- /// </summary>
- public List<double> irs { get; set; } = new List<double>();
- /// <summary>
- ///
- /// </summary>
- public List<double> interactNormal { get; set; } = new List<double>();
- /// <summary>
- /// 个人计分
- /// </summary>
- public List<double> pscore { get; set; } = new List<double>();
- /// <summary>
- /// 小组计分
- /// </summary>
- public List<double> gscore { get; set; } = new List<double>();
- /// <summary>
- /// 互动计分
- /// </summary>
- public List<double> tscore { get; set; } = new List<double>();
- /// <summary>
- /// 作品上传数
- /// </summary>
- public List<List<double>> upload { get; set; } = new List<List<double>>();
- /// <summary>
- /// 学生协作成果数
- /// </summary>
- public List<double> stuCowork { get; set; } = new List<double>();
- /// <summary>
- /// 小组协作成果数
- /// </summary>
- public List<double> groupCowork { get; set; } = new List<double>();
- /// <summary>
- /// 挑人集合
- /// </summary>
- public List<List<string>> pickup { get; set; } = new List<List<string>>();
- ///// <summary>
- ///// 挑人集合-小组
- ///// </summary>
- //public List<List<string>> pickup_group { get; set; } = new List<List<string>>();
- }
- /// <summary>
- /// 每月的课例模型数据
- /// </summary>
- public class LessonDataAnalysisMonth : LessonDataAnalysisBase
- {
- /// <summary>
- /// 时间戳
- /// </summary>
- public long updateTime { get; set; }
- /// <summary>
- /// yyyyMM
- /// </summary>
- public string? yearMonth { get; set; }
- }
-
- /// <summary>
- ///
- /// </summary>
- public class LessonLocal
- {
- /// <summary>
- ///
- /// </summary>
- public LessonBase? lessonBase { get; set; }
- /// <summary>
- ///
- /// </summary>
- public TimeLineData? timeLineData { get; set; }
- /// <summary>
- ///
- /// </summary>
- public LessonRecord? lessonRecord { get; set; }
- /// <summary>
- ///
- /// </summary>
- public List<LocalStudent> studentLessonDatas { get; set; } = new List<LocalStudent>();
- /// <summary>
- ///
- /// </summary>
- public List<TaskData> taskDatas { get; set; } = new List<TaskData>();
- /// <summary>
- ///
- /// </summary>
- public List<SmartRatingData> smartRatingDatas { get; set; } = new List<SmartRatingData>();
- /// <summary>
- ///
- /// </summary>
- public List<IRSData> irsDatas { get; set; } = new List<IRSData>();
- /// <summary>
- ///
- /// </summary>
- public List<CoworkData> coworkDatas { get; set; } = new List<CoworkData>();
- /// <summary>
- ///
- /// </summary>
- public List<ExamData> examDatas { get; set; } = new List<ExamData>();
- /// <summary>
- ///
- /// </summary>
- public List<TimeLineEvent> sokratesDatas { get; set; } = new List<TimeLineEvent>();
- }
- /// <summary>
- ///
- /// </summary>
- public class TechCount
- {
- public string? yearMonth { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string? lessonId { get; set; }
- /// <summary>
- /// 评测数量
- /// </summary>
- public int examCount { get; set; }
- /// <summary>
- /// 任务数量
- /// </summary>
- public int taskCount { get; set; }
- /// <summary>
- /// IRS次数
- /// </summary>
- public int irsCount { get; set; }
- /// <summary>
- /// 互动次数
- /// </summary>
- //public int interactExamCount { get; set; }
- /// <summary>
- /// 互动次数
- /// </summary>
- public int interactNormalCount { get; set; }
- /// <summary>
- /// 协作次数
- /// </summary>
- public int coworkCount { get; set; }
- /// <summary>
- /// 智能评分次数
- /// </summary>
- public int smartRatingCount { get; set; }
- /// <summary>
- ///
- /// </summary>
- public List<CodeLong> timeCount { get; set; } = new List<CodeLong>();
- /// <summary>
- ///
- /// </summary>
- public IEnumerable<double> pscore { get; set; } = new List<double>();
- /// <summary>
- ///
- /// </summary>
- public IEnumerable<double> gscore { get; set; } = new List<double>();
- /// <summary>
- ///
- /// </summary>
- public IEnumerable<double> tscore { get; set; } = new List<double>();
- /// <summary>
- /// 评测数量
- /// </summary>
- public int examCountBase { get; set; }
- /// <summary>
- /// 任务数量
- /// </summary>
- public int taskCountBase { get; set; }
- /// <summary>
- /// IRS次数
- /// </summary>
- public int irsCountBase { get; set; }
- /// <summary>
- /// 互动次数
- /// </summary>
- //public int interactExamCountBase { get; set; }
- /// <summary>
- /// 互动次数
- /// </summary>
- public int interactNormalCountBase { get; set; }
- /// <summary>
- /// 协作次数
- /// </summary>
- public int coworkCountBase { get; set; }
- /// <summary>
- /// 智能评分次数
- /// </summary>
- public int smartRatingCountBase { get; set; }
- /// <summary>
- /// 作品上传数
- /// </summary>
- public List<List<double>> upload { get; set; } = new List<List<double>>();
- /// <summary>
- /// 学生协作成果数
- /// </summary>
- public List<double> stuCowork { get; set; } = new List<double>();
- /// <summary>
- /// 小组协作成果数
- /// </summary>
- public List<double> groupCowork { get; set; } = new List<double>();
- public List<string> pickup { get; set; } = new List<string>();
- }
- }
|