1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267 |
- using Azure.Cosmos;
- using Newtonsoft.Json;
- using StackExchange.Redis;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Text.Json;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.Extension;
- using TEAMModelOS.SDK.Models.Cosmos;
- using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
- using TEAMModelOS.SDK.Models.Cosmos.Common;
- namespace TEAMModelOS.SDK.Models.Service.BI
- {
- public static class BIProdAnalysis
- {
- /// <summary>
- /// 1.取得某日CS IOT 資料
- /// 2.生成IES5各校產品分析統計資料
- /// 3.生成TMID產品分析統計資料
- /// 4.生成DeviceID產品分析統計資料
- /// </summary>
- /// <param name="_azureRedis"></param>
- /// <param name="_dingDing"></param>
- /// <param name="y">年</param>
- /// <param name="m">月(2位數)</param>
- /// <param name="d">日(2位數)</param>
- /// <returns></returns>
- public static async Task BICreatDailyAnalData(AzureRedisFactory _azureRedis, CosmosClient _azureCosmosClient, CosmosClient _azureCosmosClientCsv2, CosmosClient _azureCosmosClientCsv2CnRead, DingDing _dingDing, string y, string m, string d)
- {
- List<IotTeachingData> IotTeachingDataList = await BIGetDailyRedisProdAnalData(_azureRedis, _azureCosmosClientCsv2, _dingDing, y, m, d); //取得Redis IOT 每日資訊
- await CreatIes5ProdAnalData(_azureRedis, _azureCosmosClient, _azureCosmosClientCsv2CnRead, _dingDing, y, m, d, IotTeachingDataList); //生成學校CosmosDB年月日統計資料
- await CreatTmidProdAnalData(_azureRedis, _azureCosmosClient, _dingDing, y, m, d, IotTeachingDataList); //生成TMID CosmosDB年月日統計資料
- }
- /// <summary>
- /// 取得某日CS IOT 資料
- /// </summary>
- /// <param name="_azureRedis"></param>
- /// <param name="_dingDing"></param>
- /// <param name="y">年</param>
- /// <param name="m">月(2位數)</param>
- /// <param name="d">日(2位數)</param>
- /// <returns></returns>
- public static async Task<List<IotTeachingData>> BIGetDailyRedisProdAnalData(AzureRedisFactory _azureRedis, CosmosClient _azureCosmosClientCsv2, DingDing _dingDing, string y, string m, string d)
- {
- List<IotTeachingData> IotTeachingDataList = new List<IotTeachingData>();
- try
- {
- var redisClinet2 = _azureRedis.GetRedisClient(2);
- var datetime = DateTimeOffset.UtcNow;
- var ynow = datetime.Year;
- HashSet<string> tmids = new HashSet<string>();
- Dictionary<string, string> tmidSchidDic = new Dictionary<string, string>();
- //取得CS Redis TeachingData (IOT紀錄只有三個月分)
- if (y.Equals(ynow.ToString()))
- {
- bool TeachingDataExist = await redisClinet2.KeyExistsAsync($"TeachingData:{m}{d}");
- if (TeachingDataExist)
- {
- RedisValue[] TeachingData = redisClinet2.ListRange($"TeachingData:{m}{d}");
- foreach (RedisValue tdataRow in TeachingData)
- {
- string[] tdata = tdataRow.ToString().Split(',');
- IotTeachingData IotTeachingData = new IotTeachingData();
- IotTeachingData.timestamp = Convert.ToInt64(tdata[0]);
- IotTeachingData.deviceId = tdata[1];
- IotTeachingData.channel = tdata[2];
- IotTeachingData.tmid = tdata[3];
- IotTeachingData.schoolId = tdata[4];
- IotTeachingData.useIES = tdata[5];
- IotTeachingData.useIES5Resource = (!string.IsNullOrWhiteSpace(tdata[6])) ? Convert.ToInt32(tdata[6]) : 0;
- IotTeachingData.useWebIrs = tdata[7];
- IotTeachingData.useDeviceIrs = tdata[8];
- IotTeachingData.useHaboard = tdata[9];
- IotTeachingData.useHita = tdata[10];
- IotTeachingData.lessonLengMin = (!string.IsNullOrWhiteSpace(tdata[11])) ? Convert.ToInt32(tdata[11]) : 0;
- IotTeachingData.stuShow = (!string.IsNullOrWhiteSpace(tdata[12])) ? Convert.ToInt32(tdata[12]) : 0;
- IotTeachingData.tPoint = (!string.IsNullOrWhiteSpace(tdata[13])) ? Convert.ToInt32(tdata[13]) : 0;
- IotTeachingData.lTypeCoop = tdata[14];
- IotTeachingData.lTypeIact = tdata[15];
- IotTeachingData.lTypeMis = tdata[16];
- IotTeachingData.lTypeTst = tdata[17];
- IotTeachingData.lTypeDif = tdata[18];
- IotTeachingData.authType = tdata[19];
- IotTeachingData.mission = (!string.IsNullOrWhiteSpace(tdata[20])) ? Convert.ToInt32(tdata[20]) : 0;
- IotTeachingData.missionFin = (!string.IsNullOrWhiteSpace(tdata[21])) ? Convert.ToInt32(tdata[21]) : 0;
- IotTeachingData.item = (!string.IsNullOrWhiteSpace(tdata[22])) ? Convert.ToInt32(tdata[22]) : 0;
- IotTeachingData.interact = (!string.IsNullOrWhiteSpace(tdata[23])) ? Convert.ToInt32(tdata[23]) : 0;
- IotTeachingData.ip = (tdata.Length > 24) ? tdata[24] : "";
- IotTeachingData.version = (tdata.Length > 25) ? tdata[25] : "";
- IotTeachingData.sendSok = (tdata.Length > 26 && !string.IsNullOrWhiteSpace(tdata[26])) ? tdata[26] : "0";
- IotTeachingData.learnPeer = (tdata.Length > 27 && !string.IsNullOrWhiteSpace(tdata[27])) ? tdata[27] : "0";
- IotTeachingData.learnCoop = (tdata.Length > 28 && !string.IsNullOrWhiteSpace(tdata[28])) ? tdata[28] : "0";
- IotTeachingData.useWordCloud = (tdata.Length > 29 && !string.IsNullOrWhiteSpace(tdata[29])) ? tdata[29] : "0";
- IotTeachingData.useClouDAS = (tdata.Length > 30 && !string.IsNullOrWhiteSpace(tdata[30])) ? tdata[30] : "0";
- IotTeachingData.useGPT = (tdata.Length > 31 && !string.IsNullOrWhiteSpace(tdata[31])) ? tdata[31] : "0";
- IotTeachingData.useIes5Test = (tdata.Length > 32 && !string.IsNullOrWhiteSpace(tdata[32])) ? tdata[32] : "0";
- IotTeachingData.usePaperTest = (tdata.Length > 33 && !string.IsNullOrWhiteSpace(tdata[33])) ? tdata[33] : "0";
- IotTeachingData.useExcelTest = (tdata.Length > 34 && !string.IsNullOrWhiteSpace(tdata[34])) ? tdata[34] : "0";
- IotTeachingData.useScoreBoard = (tdata.Length > 35 && !string.IsNullOrWhiteSpace(tdata[35])) ? tdata[35] : "0"; //課堂中使用記分板
- IotTeachingData.learnParticipation = (tdata.Length > 36 && !string.IsNullOrWhiteSpace(tdata[36])) ? Convert.ToInt32(tdata[36]) : 0; //學習參與度指數
- IotTeachingData.learnParticipationCnt = (IotTeachingData.learnParticipation > 0) ? "1" : "0"; //是否計算學習參與度
- IotTeachingData.coopMission = (tdata.Length > 37 && !string.IsNullOrWhiteSpace(tdata[37])) ? Convert.ToInt32(tdata[37]) : 0; //協作任務數
- IotTeachingData.coopWork = (tdata.Length > 38 && !string.IsNullOrWhiteSpace(tdata[38])) ? Convert.ToInt32(tdata[38]) : 0; //協作作品數
- IotTeachingData.coopContributionT = (tdata.Length > 39 && !string.IsNullOrWhiteSpace(tdata[39])) ? Convert.ToInt32(tdata[39]) : 0; //協作總貢獻度
- IotTeachingData.peerAct = (tdata.Length > 40 && !string.IsNullOrWhiteSpace(tdata[40])) ? Convert.ToInt32(tdata[40]) : 0; //互評活動次數
- IotTeachingData.peerStuParticipationT = (tdata.Length > 41 && !string.IsNullOrWhiteSpace(tdata[41])) ? Convert.ToInt32(tdata[41]) : 0; //互評學生參與總次數
- IotTeachingData.useTransMode = (tdata.Length > 42 && !string.IsNullOrWhiteSpace(tdata[42])) ? tdata[42] : "0"; //有使用透明模式
- IotTeachingData.useMiniMode = (tdata.Length > 43 && !string.IsNullOrWhiteSpace(tdata[43])) ? tdata[43] : "0"; //有使用最小化模式
- IotTeachingDataList.Add(IotTeachingData);
- if(!string.IsNullOrWhiteSpace(IotTeachingData.tmid))
- {
- tmids.Add(IotTeachingData.tmid);
- }
- }
- }
- }
- //取得TMID進階資料,以弱強歸戶學校補足學校ID
- QueryDefinition querye = new QueryDefinition(@"SELECT c.id, c.schoolCode, c.schoolCodeW FROM c WHERE (ARRAY_CONTAINS(@key, c.id) AND ( (IS_DEFINED(c.schoolCode) AND IS_STRING(c.schoolCode)) OR (IS_DEFINED(c.schoolCodeW) AND IS_STRING(c.schoolCodeW)) ))").WithParameter("@key", tmids);
- await foreach (var item in _azureCosmosClientCsv2.GetContainer("Core", "ID2")
- .GetItemQueryStreamIterator(querye, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("base-ex")}))
- {
- using var json = await JsonDocument.ParseAsync(item.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- foreach (var doc in json.RootElement.GetProperty("Documents").EnumerateArray())
- {
- string id = doc.GetProperty("id").GetString();
- string schoolCode = (doc.TryGetProperty("schoolCode", out JsonElement _tmidSchoolCode)) ? _tmidSchoolCode.GetString() : string.Empty;
- string schoolCodeW = (doc.TryGetProperty("schoolCodeW", out JsonElement _tmidSchoolCodeW)) ? _tmidSchoolCodeW.GetString() : string.Empty;
- List<IotTeachingData> IotTeachingDatas = IotTeachingDataList.Where(x => x.tmid.Equals(id) && string.IsNullOrWhiteSpace(x.schoolId)).ToList();
- if(IotTeachingDatas.Count > 0)
- {
- foreach(IotTeachingData IotTeachingDataRow in IotTeachingDatas)
- {
- if (!string.IsNullOrWhiteSpace(schoolCode))
- {
- IotTeachingDataRow.schoolId = schoolCode;
- }
- else if (!string.IsNullOrWhiteSpace(schoolCodeW))
- {
- IotTeachingDataRow.schoolId = schoolCodeW;
- }
- }
- }
- }
- }
- }
- return IotTeachingDataList;
- }
- catch (Exception ex)
- {
- _ = _dingDing.SendBotMsg($"BI,{Environment.GetEnvironmentVariable("Option:Location")},BIGetDailyRedisProdAnalData() 取得每日CoreServiceIOT資料錯誤\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
- return IotTeachingDataList;
- }
- }
- //年月日 IES5學校IOT產品分析數據生成
- ///參數:某日IOT 教學資料列
- ///1.生成 Redis ProdAnalysis:Month
- ///2.生成 CosmosDB Month
- ///3.生成 CosmosDB 系統所有學校數值加總
- private static async Task CreatIes5ProdAnalData(AzureRedisFactory _azureRedis, CosmosClient _azureCosmosClient, CosmosClient _azureCosmosClientCsv2CnRead, DingDing _dingDing, string y, string m, string d, List<IotTeachingData> IotTeachingDataList)
- {
- try
- {
- var redisClinet8 = _azureRedis.GetRedisClient(8);
- List<string> crtVirtualSchoolId = new List<string>(); //虛擬學校創建ID列表
- List<string> calPropList = new List<string>() { "lessonRecord", "useIES", "useIES5Resource", "useWebIrs", "useDeviceIrs", "useHaboard", "useHita", "lessonLengMin", "lessonLeng0", "stuShow", "stuLessonLengMin", "tGreen", "tLesson", "lTypeCoop", "lTypeIact", "lTypeMis", "lTypeTst", "lTypeDif", "lTypeNone", "lessonCnt928", "lessonCntId", "lessonCntDevice", "lessonCntIdDevice", "mission", "missionFin", "item", "interact", "sendSok", "learnPeer", "learnCoop", "useWordCloud", "useClouDAS", "useGPT", "useIes5Test", "usePaperTest", "useExcelTest", "useScoreBoard", "learnParticipationCnt", "learnParticipationT", "coopMission", "coopWork", "coopContributionT", "peerAct", "peerStuParticipationT", "useTransMode", "useMiniMode" }; //要計算的ProdAnalysis欄位列表
- List<ProdAnalysis> ProdAnalysisList = new List<ProdAnalysis>();
- if (IotTeachingDataList.Count > 0)
- {
- foreach (IotTeachingData IotTeachingDatRow in IotTeachingDataList)
- {
- string schoolId = (!string.IsNullOrWhiteSpace(IotTeachingDatRow.schoolId)) ? IotTeachingDatRow.schoolId.ToLower() : "noschoolid"; //noschoolid:無任何學校ID
- if (!schoolId.Equals("noschoolid") && !schoolId.Equals("allschool") && !crtVirtualSchoolId.Contains(schoolId))
- {
- crtVirtualSchoolId.Add(schoolId);
- }
- string toolType = string.Empty;
- if (!string.IsNullOrWhiteSpace(IotTeachingDatRow.deviceId))
- {
- if (IotTeachingDatRow.deviceId.Contains("HiTeachCC-")) toolType = "HiTeachCC";
- else if (IotTeachingDatRow.deviceId.Contains("HiTeach-")) toolType = "HiTeach";
- else if (IotTeachingDatRow.deviceId.Contains("HiTA-")) toolType = "HiTA";
- }
- //學校數據生成
- if (!string.IsNullOrWhiteSpace(schoolId) && !string.IsNullOrWhiteSpace(toolType))
- {
- bool addFlg = false;
- ProdAnalysis prodAnalysisRow = ProdAnalysisList.Where(s => s.schoolId.Equals(schoolId) && s.toolType.Equals(toolType)).FirstOrDefault();
- //無此校數據=>創建
- if (prodAnalysisRow == null)
- {
- prodAnalysisRow = new ProdAnalysis();
- prodAnalysisRow.schoolId = schoolId;
- prodAnalysisRow.toolType = toolType;
- addFlg = true;
- }
- //欄位加總
- if (!string.IsNullOrWhiteSpace(IotTeachingDatRow.deviceId) && !prodAnalysisRow.deviceList.Contains(IotTeachingDatRow.deviceId))
- {
- prodAnalysisRow.deviceList.Add(IotTeachingDatRow.deviceId);
- }
- prodAnalysisRow.deviceCnt = prodAnalysisRow.deviceList.Count;
- switch (IotTeachingDatRow.authType)
- {
- case "0": //928授權
- if (!prodAnalysisRow.deviceNoAuthList.Contains(IotTeachingDatRow.deviceId)) prodAnalysisRow.deviceNoAuthList.Add(IotTeachingDatRow.deviceId);
- prodAnalysisRow.lessonCnt928++;
- break;
- case "1": //ID授權
- if (!prodAnalysisRow.deviceNoAuthList.Contains(IotTeachingDatRow.deviceId)) prodAnalysisRow.deviceNoAuthList.Add(IotTeachingDatRow.deviceId);
- prodAnalysisRow.lessonCntId++;
- break;
- case "2": //機器授權
- if (!prodAnalysisRow.deviceAuthList.Contains(IotTeachingDatRow.deviceId)) prodAnalysisRow.deviceAuthList.Add(IotTeachingDatRow.deviceId);
- prodAnalysisRow.lessonCntDevice++;
- break;
- case "3": //ID+機器授權
- if (!prodAnalysisRow.deviceAuthList.Contains(IotTeachingDatRow.deviceId)) prodAnalysisRow.deviceAuthList.Add(IotTeachingDatRow.deviceId);
- prodAnalysisRow.lessonCntIdDevice++;
- break;
- }
- prodAnalysisRow.deviceNoAuth = prodAnalysisRow.deviceNoAuthList.Count;
- prodAnalysisRow.deviceAuth = prodAnalysisRow.deviceAuthList.Count;
- if (!string.IsNullOrWhiteSpace(IotTeachingDatRow.tmid) && !prodAnalysisRow.tmidList.Contains(IotTeachingDatRow.tmid))
- {
- prodAnalysisRow.tmidList.Add(IotTeachingDatRow.tmid);
- }
- prodAnalysisRow.tmidCnt = prodAnalysisRow.tmidList.Count;
- prodAnalysisRow.lessonRecord++;
- if (IotTeachingDatRow.useIES.Equals("1")) prodAnalysisRow.useIES++;
- prodAnalysisRow.useIES5Resource += IotTeachingDatRow.useIES5Resource;
- if (IotTeachingDatRow.useWebIrs.Equals("1")) prodAnalysisRow.useWebIrs++;
- if (IotTeachingDatRow.useDeviceIrs.Equals("1")) prodAnalysisRow.useDeviceIrs++;
- if (IotTeachingDatRow.useHaboard.Equals("1")) prodAnalysisRow.useHaboard++;
- if (IotTeachingDatRow.useHita.Equals("1")) prodAnalysisRow.useHita++;
- prodAnalysisRow.lessonLengMin += IotTeachingDatRow.lessonLengMin;
- if (IotTeachingDatRow.lessonLengMin.Equals(0)) prodAnalysisRow.lessonLeng0++;
- prodAnalysisRow.stuShow += IotTeachingDatRow.stuShow;
- prodAnalysisRow.stuLessonLengMin += IotTeachingDatRow.lessonLengMin * IotTeachingDatRow.stuShow;
- if (IotTeachingDatRow.tPoint >= 70) prodAnalysisRow.tGreen++;
- if (IotTeachingDatRow.lessonLengMin >= 10 && IotTeachingDatRow.tPoint > 0) prodAnalysisRow.tLesson++;
- if (IotTeachingDatRow.lTypeCoop.Equals("1")) prodAnalysisRow.lTypeCoop++;
- if (IotTeachingDatRow.lTypeIact.Equals("1")) prodAnalysisRow.lTypeIact++;
- if (IotTeachingDatRow.lTypeMis.Equals("1")) prodAnalysisRow.lTypeMis++;
- if (IotTeachingDatRow.lTypeTst.Equals("1")) prodAnalysisRow.lTypeTst++;
- if (IotTeachingDatRow.lTypeDif.Equals("1")) prodAnalysisRow.lTypeDif++;
- if (IotTeachingDatRow.lTypeCoop.Equals("0") && IotTeachingDatRow.lTypeIact.Equals("0") && IotTeachingDatRow.lTypeMis.Equals("0") && IotTeachingDatRow.lTypeTst.Equals("0") && IotTeachingDatRow.lTypeDif.Equals("0")) prodAnalysisRow.lTypeNone++;
- prodAnalysisRow.mission += IotTeachingDatRow.mission;
- prodAnalysisRow.missionFin += IotTeachingDatRow.missionFin;
- prodAnalysisRow.item += IotTeachingDatRow.item;
- prodAnalysisRow.interact += IotTeachingDatRow.interact;
- if (IotTeachingDatRow.sendSok.Equals("1")) prodAnalysisRow.sendSok++;
- if (IotTeachingDatRow.learnPeer.Equals("1")) prodAnalysisRow.learnPeer++;
- if (IotTeachingDatRow.learnCoop.Equals("1")) prodAnalysisRow.learnCoop++;
- if (IotTeachingDatRow.useWordCloud.Equals("1")) prodAnalysisRow.useWordCloud++;
- if (IotTeachingDatRow.useClouDAS.Equals("1")) prodAnalysisRow.useClouDAS++;
- if (IotTeachingDatRow.useGPT.Equals("1")) prodAnalysisRow.useGPT++;
- if (IotTeachingDatRow.useIes5Test.Equals("1")) prodAnalysisRow.useIes5Test++;
- if (IotTeachingDatRow.usePaperTest.Equals("1")) prodAnalysisRow.usePaperTest++;
- if (IotTeachingDatRow.useExcelTest.Equals("1")) prodAnalysisRow.useExcelTest++;
- if (IotTeachingDatRow.useScoreBoard.Equals("1")) prodAnalysisRow.useScoreBoard++; //課堂中使用記分板
- if (IotTeachingDatRow.learnParticipationCnt.Equals("1")) prodAnalysisRow.learnParticipationCnt++; //學習參與度次數
- prodAnalysisRow.learnParticipationT += IotTeachingDatRow.learnParticipation; //學習參與度指數(總和)
- decimal learnParticipationTmp = (prodAnalysisRow.learnParticipationCnt > 0) ? (decimal)prodAnalysisRow.learnParticipationT / (decimal)prodAnalysisRow.learnParticipationCnt : 0;
- prodAnalysisRow.learnParticipation = Math.Round(learnParticipationTmp, 2); //學習參與度指數(平均)
- prodAnalysisRow.coopMission += IotTeachingDatRow.coopMission; //協作任務數
- prodAnalysisRow.coopWork += IotTeachingDatRow.coopWork; //協作作品數
- prodAnalysisRow.coopContributionT += IotTeachingDatRow.coopContributionT; //協作總貢獻度
- prodAnalysisRow.peerAct += IotTeachingDatRow.peerAct; //互評活動次數
- prodAnalysisRow.peerStuParticipationT += IotTeachingDatRow.peerStuParticipationT; //互評學生參與總次數
- if (IotTeachingDatRow.useTransMode.Equals("1")) prodAnalysisRow.useTransMode++; //有使用透明模式
- if (IotTeachingDatRow.useMiniMode.Equals("1")) prodAnalysisRow.useMiniMode++; //有使用最小化模式
- if (addFlg)
- {
- ProdAnalysisList.Add(prodAnalysisRow);
- }
- }
- }
- }
- //1.記入IES5 Redis ProdAnalysis:Day
- //2.記入IES5 CosmosDB Day
- if (ProdAnalysisList.Count > 0)
- {
- //資料整形
- Dictionary<string, Dictionary<string, string>> redisSchFieldDic = new Dictionary<string, Dictionary<string, string>>(); //架構: key => schId => schJsonContent
- List<ProdAnalysisCosmos> cosmosSchList = new List<ProdAnalysisCosmos>();
- Dictionary<string, ProdAnalysisCosmos> cosmosAllSchSumDayDic = new Dictionary<string, ProdAnalysisCosmos>();
- foreach (ProdAnalysis prodAnalysisRow in ProdAnalysisList)
- {
- //Redis整形
- string toolType = prodAnalysisRow.toolType;
- string schoolId = prodAnalysisRow.schoolId;
- string hkey = $"ProdAnalysis:Day:{toolType}:{y}{m}{d}";
- string fieldContent = prodAnalysisRow.ToJsonString();
- if (redisSchFieldDic.ContainsKey(hkey)) redisSchFieldDic[hkey].Add(schoolId, fieldContent);
- else redisSchFieldDic.Add(hkey, new Dictionary<string, string>() { { schoolId, fieldContent } });
- //CosmosDB整形
- ProdAnalysisCosmos ProdAnalysisCosmosRow = prodAnalysisRow.ToJsonString().ToObject<ProdAnalysisCosmos>();
- ProdAnalysisCosmosRow.date = $"{y}{m}{d}";
- ProdAnalysisCosmosRow.year = Convert.ToInt32(y, 10);
- ProdAnalysisCosmosRow.month = Convert.ToInt32(m, 10);
- ProdAnalysisCosmosRow.day = Convert.ToInt32(d, 10);
- DateTimeOffset dateTime = new DateTimeOffset(ProdAnalysisCosmosRow.year, ProdAnalysisCosmosRow.month, ProdAnalysisCosmosRow.day, 0, 0, 0, TimeSpan.Zero);
- ProdAnalysisCosmosRow.dateTime = dateTime.ToUnixTimeSeconds();
- ProdAnalysisCosmosRow.id = $"{ProdAnalysisCosmosRow.toolType}-{ProdAnalysisCosmosRow.date}-{schoolId}";
- ProdAnalysisCosmosRow.dateUnit = "day";
- ProdAnalysisCosmosRow.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- cosmosSchList.Add(ProdAnalysisCosmosRow);
- }
- //記入Redis
- if (redisSchFieldDic.Count > 0)
- {
- foreach (KeyValuePair<string, Dictionary<string, string>> hkeyItem in redisSchFieldDic)
- {
- //記入Redis
- string hkey = hkeyItem.Key;
- List<HashEntry> hvalList = new List<HashEntry>();
- Dictionary<string, string> fieldDic = hkeyItem.Value;
- foreach (KeyValuePair<string, string> schItem in fieldDic)
- {
- string schoolId = schItem.Key;
- string fieldContent = schItem.Value;
- hvalList.Add(new HashEntry($"{schoolId}", fieldContent));
- }
- await redisClinet8.HashSetAsync(hkey, hvalList.ToArray());
- }
- }
- //記入CosmosDB
- if (cosmosSchList.Count > 0)
- {
- foreach (ProdAnalysisCosmos cosmosSchRow in cosmosSchList)
- {
- //各校每日CosmosDB記入
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<ProdAnalysisCosmos>(cosmosSchRow);
- //所有學校數值加總 數值生成 cosmosAllSchSumDayDic -> key:toolType val:cosmosAllSchSumDay
- cosmosAllSchSumDayDic = GenAnalysisRowSumData(cosmosAllSchSumDayDic, cosmosSchRow, calPropList, "day");
- }
- //每日所有學校數據總計CosmosDB記入
- foreach (KeyValuePair<string, ProdAnalysisCosmos> schItem in cosmosAllSchSumDayDic)
- {
- string toolType = schItem.Key;
- ProdAnalysisCosmos cosmosAllSchSumDay = schItem.Value;
- cosmosAllSchSumDay.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<ProdAnalysisCosmos>(cosmosAllSchSumDay);
- }
- }
- }
- //取 Redis 該月所有 ProdAnalysis:Day
- //1.生成 Redis ProdAnalysis:Month
- //2.生成 CosmosDB Month
- Dictionary<string, Dictionary<string, ProdAnalysis>> ProdAnalysisListMonth = new Dictionary<string, Dictionary<string, ProdAnalysis>>();
- Dictionary<string, ProdAnalysisCosmos> cosmosAllSchSumMonthDic = new Dictionary<string, ProdAnalysisCosmos>();
- List<ProdAnalysisCosmos> cosmosSchListMonth = new List<ProdAnalysisCosmos>();
- string patternD = $"ProdAnalysis:Day:HiT*:{y}{m}*";
- List<string> keysDayList = ScanRedisKeysByPattern(_azureRedis, patternD);
- if (keysDayList.Count > 0)
- {
- foreach (string keyDay in keysDayList)
- {
- string[] keyItemList = keyDay.Split(':'); //ProdAnalysis:Day:HiTeach:20230326
- string toolType = keyItemList[2];
- string dateStrD = keyItemList[3];
- string dateStrD_y = string.Empty;
- string dateStrD_m = string.Empty;
- string dateStrD_d = string.Empty;
- Regex rgx = new Regex(@"[0-9]{8}");
- if (rgx.IsMatch(dateStrD))
- {
- dateStrD_y = dateStrD.Substring(0, 4);
- dateStrD_m = dateStrD.Substring(4, 2);
- dateStrD_d = dateStrD.Substring(6, 2);
- }
- string prodAnalMonthKey = $"ProdAnalysis:Month:{toolType}:{dateStrD_y}{dateStrD_m}";
- bool ProdAnalysisDayExist = await redisClinet8.KeyExistsAsync(keyDay);
- if (ProdAnalysisDayExist && !string.IsNullOrWhiteSpace(dateStrD_y) && !string.IsNullOrWhiteSpace(dateStrD_m) && !string.IsNullOrWhiteSpace(dateStrD_d))
- {
- HashEntry[] hsetDay = redisClinet8.HashGetAll(keyDay); //某日 ProdAnalysis:Day所有學校的統計項目
- foreach (HashEntry hset in hsetDay)
- {
- string keySchId = hset.Name;
- string valSchDataJson = hset.Value;
- ProdAnalysis SchDataTodo = valSchDataJson.ToObject<ProdAnalysis>();
- //Redis Month 資料生成
- if (ProdAnalysisListMonth.ContainsKey(prodAnalMonthKey)) //月Dic已有此key => 分校累加
- {
- if (ProdAnalysisListMonth[$"{prodAnalMonthKey}"].ContainsKey($"{keySchId}"))
- {
- ProdAnalysis SchDataNow = ProdAnalysisListMonth[$"{prodAnalMonthKey}"][$"{keySchId}"];
- foreach (PropertyInfo propertyInfo in SchDataNow.GetType().GetProperties())
- {
- if (calPropList.Contains(propertyInfo.Name))
- {
- var propType = propertyInfo.PropertyType;
- var valNow = propertyInfo.GetValue(SchDataNow);
- var valTodo = SchDataTodo.GetType().GetProperty(propertyInfo.Name).GetValue(SchDataTodo);
- if (propType.Equals(typeof(long))) propertyInfo.SetValue(SchDataNow, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
- else propertyInfo.SetValue(SchDataNow, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
- }
- }
- SchDataNow.deviceList = SchDataNow.deviceList.Union(SchDataTodo.deviceList).ToList();
- SchDataNow.deviceCnt = SchDataNow.deviceList.Count;
- SchDataNow.deviceAuthList = SchDataNow.deviceAuthList.Union(SchDataTodo.deviceAuthList).ToList();
- SchDataNow.deviceAuth = SchDataNow.deviceAuthList.Count;
- SchDataNow.deviceNoAuthList = SchDataNow.deviceNoAuthList.Union(SchDataTodo.deviceNoAuthList).ToList();
- SchDataNow.deviceNoAuth = SchDataNow.deviceNoAuthList.Count;
- SchDataNow.tmidList = SchDataNow.tmidList.Union(SchDataTodo.tmidList).ToList();
- SchDataNow.tmidCnt = SchDataNow.tmidList.Count;
- }
- //無此校資料 => 該校資料放入
- else
- {
- ProdAnalysisListMonth[$"{prodAnalMonthKey}"][$"{keySchId}"] = SchDataTodo;
- }
- }
- else //無此月資料 => 所有學校資料放入
- {
- ProdAnalysisListMonth.Add(prodAnalMonthKey, new Dictionary<string, ProdAnalysis>() { { keySchId, SchDataTodo } });
- }
- }
- }
- }
- }
- if (ProdAnalysisListMonth.Count > 0)
- {
- foreach (KeyValuePair<string, Dictionary<string, ProdAnalysis>> item in ProdAnalysisListMonth)
- {
- string monthRedisKey = item.Key;
- List<HashEntry> hvalList = new List<HashEntry>();
- Dictionary<string, ProdAnalysis> monthRedisSchDIc = item.Value;
- foreach (KeyValuePair<string, ProdAnalysis> monthRedisSchItem in monthRedisSchDIc)
- {
- string monthRedisSchId = monthRedisSchItem.Key;
- ProdAnalysis monthRedisSchData = monthRedisSchItem.Value;
- //Redis資料製作
- hvalList.Add(new HashEntry(monthRedisSchId, monthRedisSchData.ToJsonString()));
- //CosmosDB資料製作
- ProdAnalysisCosmos cosmosSchRow = monthRedisSchData.ToJsonString().ToObject<ProdAnalysisCosmos>();
- cosmosSchRow.date = $"{y}{m}";
- cosmosSchRow.year = Convert.ToInt32(y, 10);
- cosmosSchRow.month = Convert.ToInt32(m, 10);
- DateTimeOffset dateTime = new DateTimeOffset(cosmosSchRow.year, cosmosSchRow.month, 1, 0, 0, 0, TimeSpan.Zero);
- cosmosSchRow.dateTime = dateTime.ToUnixTimeSeconds();
- cosmosSchRow.id = $"{monthRedisSchData.toolType}-{cosmosSchRow.date}-{monthRedisSchId}";
- cosmosSchRow.dateUnit = "month";
- cosmosSchRow.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- cosmosSchListMonth.Add(cosmosSchRow);
- }
- //記入Redis
- await redisClinet8.HashSetAsync($"{monthRedisKey}", hvalList.ToArray());
- }
- //記入CosmosDB
- if (cosmosSchListMonth.Count > 0)
- {
- foreach (ProdAnalysisCosmos cosmosSchRow in cosmosSchListMonth)
- {
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<ProdAnalysisCosmos>(cosmosSchRow);
- //所有學校數值加總 數值生成 cosmosAllSchSumDayDic -> key:toolType val:cosmosAllSchSumDay
- cosmosAllSchSumMonthDic = GenAnalysisRowSumData(cosmosAllSchSumMonthDic, cosmosSchRow, calPropList, "month");
- }
- //每月所有學校數據總計CosmosDB記入
- foreach (KeyValuePair<string, ProdAnalysisCosmos> schItem in cosmosAllSchSumMonthDic)
- {
- string toolType = schItem.Key;
- ProdAnalysisCosmos cosmosAllSchSumMonth = schItem.Value;
- cosmosAllSchSumMonth.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<ProdAnalysisCosmos>(cosmosAllSchSumMonth);
- }
- }
- }
- //取該年所有 CosmosDB 該年所有月份 生成CosmosDB年資料
- Dictionary<string, Dictionary<string, ProdAnalysisCosmos>> ProdAnalysisListYear = new Dictionary<string, Dictionary<string, ProdAnalysisCosmos>>();
- Dictionary<string, ProdAnalysisCosmos> cosmosAllSchSumYearDic = new Dictionary<string, ProdAnalysisCosmos>();
- var query = $"SELECT * FROM c WHERE c.year = {y} AND c.dateUnit = 'month' AND c.schoolId != 'allschool'";
- await foreach (var itemcr in _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("ProdAnalysis") }))
- {
- var json = await JsonDocument.ParseAsync(itemcr.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
- {
- ProdAnalysisCosmos SchDataTodo = obj.ToObject<ProdAnalysisCosmos>();
- string toolType = SchDataTodo.toolType;
- string schId = SchDataTodo.schoolId;
- //年Dic已有此key => 分校累加
- if (ProdAnalysisListYear.ContainsKey(toolType))
- {
- if (ProdAnalysisListYear[$"{toolType}"].ContainsKey($"{schId}"))
- {
- ProdAnalysisCosmos SchDataNow = ProdAnalysisListYear[$"{toolType}"][$"{schId}"];
- foreach (PropertyInfo propertyInfo in SchDataNow.GetType().GetProperties())
- {
- if (calPropList.Contains(propertyInfo.Name))
- {
- var propType = propertyInfo.PropertyType;
- var valNow = propertyInfo.GetValue(SchDataNow);
- var valTodo = SchDataTodo.GetType().GetProperty(propertyInfo.Name).GetValue(SchDataTodo);
- if (propType.Equals(typeof(long))) propertyInfo.SetValue(SchDataNow, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
- else propertyInfo.SetValue(SchDataNow, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
- }
- }
- SchDataNow.deviceList = SchDataNow.deviceList.Union(SchDataTodo.deviceList).ToList();
- SchDataNow.deviceCnt = SchDataNow.deviceList.Count;
- SchDataNow.deviceAuthList = SchDataNow.deviceAuthList.Union(SchDataTodo.deviceAuthList).ToList();
- SchDataNow.deviceAuth = SchDataNow.deviceAuthList.Count;
- SchDataNow.deviceNoAuthList = SchDataNow.deviceNoAuthList.Union(SchDataTodo.deviceNoAuthList).ToList();
- SchDataNow.deviceNoAuth = SchDataNow.deviceNoAuthList.Count;
- SchDataNow.tmidList = SchDataNow.tmidList.Union(SchDataTodo.tmidList).ToList();
- SchDataNow.tmidCnt = SchDataNow.tmidList.Count;
- }
- //無此校資料 => 該校資料放入
- else
- {
- ProdAnalysisCosmos SchDataNow = SchDataTodo;
- SchDataNow.date = $"{y}";
- SchDataNow.year = Convert.ToInt32(y, 10);
- SchDataNow.month = 0;
- DateTimeOffset dateTime = new DateTimeOffset(SchDataNow.year, 1, 1, 0, 0, 0, TimeSpan.Zero);
- SchDataNow.dateTime = dateTime.ToUnixTimeSeconds();
- SchDataNow.id = $"{toolType}-{y}-{schId}";
- SchDataNow.dateUnit = "year";
- ProdAnalysisListYear[$"{toolType}"][$"{schId}"] = SchDataNow;
- }
- }
- //無此年資料 => 所有學校資料放入
- else
- {
- ProdAnalysisCosmos SchDataNow = SchDataTodo;
- SchDataNow.date = $"{y}";
- SchDataNow.year = Convert.ToInt32(y, 10);
- SchDataNow.month = 0;
- DateTimeOffset dateTime = new DateTimeOffset(SchDataNow.year, 1, 1, 0, 0, 0, TimeSpan.Zero);
- SchDataNow.dateTime = dateTime.ToUnixTimeSeconds();
- SchDataNow.id = $"{toolType}-{y}-{schId}";
- SchDataNow.dateUnit = "year";
- ProdAnalysisListYear.Add(toolType, new Dictionary<string, ProdAnalysisCosmos>() { { schId, SchDataNow } });
- }
- }
- }
- }
- if (ProdAnalysisListYear.Count > 0)
- {
- foreach (KeyValuePair<string, Dictionary<string, ProdAnalysisCosmos>> item in ProdAnalysisListYear)
- {
- //string toolType = item.Key;
- ProdAnalysisCosmos SchDataNow = new ProdAnalysisCosmos(); //當年某產品所有學校總和
- Dictionary<string, ProdAnalysisCosmos> yearCosmosSchDIc = item.Value;
- foreach (KeyValuePair<string, ProdAnalysisCosmos> yearCosmosSchItem in yearCosmosSchDIc)
- {
- string schId = yearCosmosSchItem.Key;
- ProdAnalysisCosmos cosmosSchRow = yearCosmosSchItem.Value;
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<ProdAnalysisCosmos>(cosmosSchRow);
- //每年所有學校數據總計CosmosDB記入
- cosmosAllSchSumYearDic = GenAnalysisRowSumData(cosmosAllSchSumYearDic, cosmosSchRow, calPropList, "year");
- }
- //每年所有學校數據總計CosmosDB記入
- foreach (KeyValuePair<string, ProdAnalysisCosmos> schItem in cosmosAllSchSumYearDic)
- {
- string toolType = schItem.Key;
- ProdAnalysisCosmos cosmosAllSchSumYear = schItem.Value;
- cosmosAllSchSumYear.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<ProdAnalysisCosmos>(cosmosAllSchSumYear);
- }
- //await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<ProdAnalysisCosmos>(SchDataNow);
- }
- }
- //虛擬學校創建
- if (crtVirtualSchoolId.Count > 0)
- {
- //取得IES5 school Base
- string schIdListStr = JsonConvert.SerializeObject(crtVirtualSchoolId);
- string schBaseQueryText = $"SELECT c.id FROM c where ARRAY_CONTAINS({schIdListStr}, c.id, true)";
- await foreach (var itemsr in _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: schBaseQueryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
- {
- using var json = await JsonDocument.ParseAsync(itemsr.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
- {
- string existSchid = obj.GetProperty("id").GetString();
- if (crtVirtualSchoolId.Contains(existSchid))
- {
- crtVirtualSchoolId.Remove(existSchid);
- }
- }
- }
- }
- //取得IES5 school VirtualBase
- schIdListStr = JsonConvert.SerializeObject(crtVirtualSchoolId);
- schBaseQueryText = $"SELECT c.id FROM c where ARRAY_CONTAINS({schIdListStr}, c.id, true)";
- await foreach (var itemsr in _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: schBaseQueryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"VirtualBase") }))
- {
- using var json = await JsonDocument.ParseAsync(itemsr.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
- {
- string existSchid = obj.GetProperty("id").GetString();
- if (crtVirtualSchoolId.Contains(existSchid))
- {
- crtVirtualSchoolId.Remove(existSchid);
- }
- }
- }
- }
- //VirtualBase school 建立
- if (crtVirtualSchoolId.Count > 0)
- {
- //取得CSV2 School,存在者建立IES5 VirtualBase school
- List<School> crtVSchoolList = new List<School>();
- string csv2SchIdListStr = JsonConvert.SerializeObject(crtVirtualSchoolId);
- string schCsv2QueryText = $"SELECT c.shortCode, c.name, c.countryName, c.provinceName, c.cityName, c.distName, c.address FROM c where ARRAY_CONTAINS({csv2SchIdListStr}, c.shortCode, true)";
- await foreach (var item in _azureCosmosClientCsv2CnRead.GetContainer("Core", "School").GetItemQueryStreamIterator(queryText: schCsv2QueryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("base") }))
- {
- using var json = await JsonDocument.ParseAsync(item.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
- {
- VirtualBase crtVSchool = new VirtualBase();
- crtVSchool.code = "VirtualBase";
- crtVSchool.id = obj.GetProperty("shortCode").GetString();
- crtVSchool.pk = "School";
- crtVSchool.schoolCode = obj.GetProperty("shortCode").GetString();
- crtVSchool.name = obj.GetProperty("name").GetString();
- crtVSchool.region = (obj.TryGetProperty("countryName", out JsonElement countryNameJ)) ? Convert.ToString(countryNameJ) : null;
- crtVSchool.province = (obj.TryGetProperty("provinceName", out JsonElement provinceNameJ)) ? Convert.ToString(provinceNameJ) : null;
- crtVSchool.city = (obj.TryGetProperty("cityName", out JsonElement cityNameJ)) ? Convert.ToString(cityNameJ) : null;
- crtVSchool.dist = (obj.TryGetProperty("distName", out JsonElement distNameJ)) ? Convert.ToString(distNameJ) : null;
- crtVSchool.address = (obj.TryGetProperty("address", out JsonElement addressJ)) ? Convert.ToString(addressJ) : null;
- crtVSchool.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<VirtualBase>(crtVSchool);
- }
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- _ = _dingDing.SendBotMsg($"BI,{Environment.GetEnvironmentVariable("Option:Location")},CreatIes5ProdAnalData() 生成學校年月日日IOT統計資料錯誤\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
- }
- }
- //年月日 TMID IOT產品分析數據生成
- ///1.生成 Redis TmidAnalysis:Month
- ///2.生成 CosmosDB Month
- ///3.生成 CosmosDB 系統所有TMID數值加總
- private static async Task CreatTmidProdAnalData(AzureRedisFactory _azureRedis, CosmosClient _azureCosmosClient, DingDing _dingDing, string y, string m, string d, List<IotTeachingData> IotTeachingDataList)
- {
- try
- {
- var redisClinet8 = _azureRedis.GetRedisClient(8);
- List<string> calPropList = new List<string>() { "lessonRecord", "useIES", "useIES5Resource", "useWebIrs", "useDeviceIrs", "useHaboard", "useHita", "lessonLengMin", "lessonLeng0", "stuShow", "stuLessonLengMin", "tGreen", "tLesson", "lTypeCoop", "lTypeIact", "lTypeMis", "lTypeTst", "lTypeDif", "lTypeNone", "lessonCnt928", "lessonCntId", "lessonCntDevice", "lessonCntIdDevice", "mission", "missionFin", "item", "interact", "sendSok", "learnPeer", "learnCoop", "useWordCloud", "useClouDAS", "useGPT", "useIes5Test", "usePaperTest", "useExcelTest", "useScoreBoard", "learnParticipationCnt", "learnParticipationT", "coopMission", "coopWork", "coopContributionT", "peerAct", "peerStuParticipationT", "useTransMode", "useMiniMode" }; //要計算的ProdAnalysis欄位列表
- List<TmidAnalysis> TmidAnalysisList = new List<TmidAnalysis>();
- if (IotTeachingDataList.Count > 0)
- {
- foreach (IotTeachingData IotTeachingDatRow in IotTeachingDataList)
- {
- bool addTmidFlg = false;
- string tmid = (!string.IsNullOrWhiteSpace(IotTeachingDatRow.tmid)) ? IotTeachingDatRow.tmid.ToString() : string.Empty;
- string deviceId = (!string.IsNullOrWhiteSpace(IotTeachingDatRow.deviceId)) ? IotTeachingDatRow.deviceId.ToString() : string.Empty;
- string ver = (!string.IsNullOrWhiteSpace(IotTeachingDatRow.version)) ? IotTeachingDatRow.version : string.Empty;
- string toolType = string.Empty;
- if (!string.IsNullOrWhiteSpace(IotTeachingDatRow.deviceId))
- {
- if (IotTeachingDatRow.deviceId.Contains("HiTeachCC-")) toolType = "HiTeachCC";
- else if (IotTeachingDatRow.deviceId.Contains("HiTeach-")) toolType = "HiTeach";
- else if (IotTeachingDatRow.deviceId.Contains("HiTA-")) toolType = "HiTA";
- }
- if (!string.IsNullOrWhiteSpace(tmid) && !string.IsNullOrWhiteSpace(deviceId) && !string.IsNullOrWhiteSpace(toolType))
- {
- bool addFlg = false;
- TmidAnalysis tmidAnalysisRow = TmidAnalysisList.Where(s => s.tmid.Equals(tmid) && s.toolType.Equals(toolType)).FirstOrDefault();
- //無此tmid數據=>創建
- if (tmidAnalysisRow == null)
- {
- tmidAnalysisRow = new TmidAnalysis();
- tmidAnalysisRow.tmid = tmid;
- tmidAnalysisRow.toolType = toolType;
- addFlg = true;
- }
- //欄位加總
- if (!tmidAnalysisRow.deviceList.Contains(IotTeachingDatRow.deviceId))
- {
- tmidAnalysisRow.deviceList.Add(IotTeachingDatRow.deviceId);
- }
- tmidAnalysisRow.deviceCnt = tmidAnalysisRow.deviceList.Count;
- switch (IotTeachingDatRow.authType)
- {
- case "0": //928授權
- if (!tmidAnalysisRow.deviceNoAuthList.Contains(IotTeachingDatRow.deviceId)) tmidAnalysisRow.deviceNoAuthList.Add(IotTeachingDatRow.deviceId);
- tmidAnalysisRow.lessonCnt928++;
- break;
- case "1": //ID授權
- if (!tmidAnalysisRow.deviceNoAuthList.Contains(IotTeachingDatRow.deviceId)) tmidAnalysisRow.deviceNoAuthList.Add(IotTeachingDatRow.deviceId);
- tmidAnalysisRow.lessonCntId++;
- break;
- case "2": //機器授權
- if (!tmidAnalysisRow.deviceAuthList.Contains(IotTeachingDatRow.deviceId)) tmidAnalysisRow.deviceAuthList.Add(IotTeachingDatRow.deviceId);
- tmidAnalysisRow.lessonCntDevice++;
- break;
- case "3": //ID+機器授權
- if (!tmidAnalysisRow.deviceAuthList.Contains(IotTeachingDatRow.deviceId)) tmidAnalysisRow.deviceAuthList.Add(IotTeachingDatRow.deviceId);
- tmidAnalysisRow.lessonCntIdDevice++;
- break;
- }
- tmidAnalysisRow.deviceNoAuth = tmidAnalysisRow.deviceNoAuthList.Count;
- tmidAnalysisRow.deviceAuth = tmidAnalysisRow.deviceAuthList.Count;
- if (!tmidAnalysisRow.tmidList.Contains(IotTeachingDatRow.tmid))
- {
- tmidAnalysisRow.tmidList.Add(IotTeachingDatRow.tmid);
- }
- tmidAnalysisRow.tmidCnt = tmidAnalysisRow.tmidList.Count;
- tmidAnalysisRow.lessonRecord++;
- if (IotTeachingDatRow.useIES.Equals("1")) tmidAnalysisRow.useIES++;
- tmidAnalysisRow.useIES5Resource += IotTeachingDatRow.useIES5Resource;
- if (IotTeachingDatRow.useWebIrs.Equals("1")) tmidAnalysisRow.useWebIrs++;
- if (IotTeachingDatRow.useDeviceIrs.Equals("1")) tmidAnalysisRow.useDeviceIrs++;
- if (IotTeachingDatRow.useHaboard.Equals("1")) tmidAnalysisRow.useHaboard++;
- if (IotTeachingDatRow.useHita.Equals("1")) tmidAnalysisRow.useHita++;
- tmidAnalysisRow.lessonLengMin += IotTeachingDatRow.lessonLengMin;
- if (IotTeachingDatRow.lessonLengMin.Equals(0)) tmidAnalysisRow.lessonLeng0++;
- tmidAnalysisRow.stuShow += IotTeachingDatRow.stuShow;
- tmidAnalysisRow.stuLessonLengMin += IotTeachingDatRow.lessonLengMin * IotTeachingDatRow.stuShow;
- if (IotTeachingDatRow.tPoint >= 70) tmidAnalysisRow.tGreen++;
- if (IotTeachingDatRow.lessonLengMin >= 10 && IotTeachingDatRow.tPoint > 0) tmidAnalysisRow.tLesson++;
- if (IotTeachingDatRow.lTypeCoop.Equals("1")) tmidAnalysisRow.lTypeCoop++;
- if (IotTeachingDatRow.lTypeIact.Equals("1")) tmidAnalysisRow.lTypeIact++;
- if (IotTeachingDatRow.lTypeMis.Equals("1")) tmidAnalysisRow.lTypeMis++;
- if (IotTeachingDatRow.lTypeTst.Equals("1")) tmidAnalysisRow.lTypeTst++;
- if (IotTeachingDatRow.lTypeDif.Equals("1")) tmidAnalysisRow.lTypeDif++;
- if (IotTeachingDatRow.lTypeCoop.Equals("0") && IotTeachingDatRow.lTypeIact.Equals("0") && IotTeachingDatRow.lTypeMis.Equals("0") && IotTeachingDatRow.lTypeTst.Equals("0") && IotTeachingDatRow.lTypeDif.Equals("0")) tmidAnalysisRow.lTypeNone++;
- tmidAnalysisRow.mission += IotTeachingDatRow.mission;
- tmidAnalysisRow.missionFin += IotTeachingDatRow.missionFin;
- tmidAnalysisRow.item += IotTeachingDatRow.item;
- tmidAnalysisRow.interact += IotTeachingDatRow.interact;
- if (IotTeachingDatRow.sendSok.Equals("1")) tmidAnalysisRow.sendSok++;
- if (IotTeachingDatRow.learnPeer.Equals("1")) tmidAnalysisRow.learnPeer++;
- if (IotTeachingDatRow.learnCoop.Equals("1")) tmidAnalysisRow.learnCoop++;
- if (IotTeachingDatRow.useWordCloud.Equals("1")) tmidAnalysisRow.useWordCloud++;
- if (IotTeachingDatRow.useClouDAS.Equals("1")) tmidAnalysisRow.useClouDAS++;
- if (IotTeachingDatRow.useGPT.Equals("1")) tmidAnalysisRow.useGPT++;
- if (IotTeachingDatRow.useIes5Test.Equals("1")) tmidAnalysisRow.useIes5Test++;
- if (IotTeachingDatRow.usePaperTest.Equals("1")) tmidAnalysisRow.usePaperTest++;
- if (IotTeachingDatRow.useExcelTest.Equals("1")) tmidAnalysisRow.useExcelTest++;
- if (IotTeachingDatRow.useScoreBoard.Equals("1")) tmidAnalysisRow.useScoreBoard++; //課堂中使用記分板
- if (IotTeachingDatRow.learnParticipationCnt.Equals("1")) tmidAnalysisRow.learnParticipationCnt++; //學習參與度次數
- tmidAnalysisRow.learnParticipationT += IotTeachingDatRow.learnParticipation; //學習參與度指數(總和)
- decimal learnParticipationTmp = (tmidAnalysisRow.learnParticipationCnt > 0) ? (decimal)tmidAnalysisRow.learnParticipationT / (decimal)tmidAnalysisRow.learnParticipationCnt : 0;
- tmidAnalysisRow.learnParticipation = Math.Round(learnParticipationTmp, 2); //學習參與度指數(平均)
- tmidAnalysisRow.coopMission += IotTeachingDatRow.coopMission; //協作任務數
- tmidAnalysisRow.coopWork += IotTeachingDatRow.coopWork; //協作作品數
- tmidAnalysisRow.coopContributionT += IotTeachingDatRow.coopContributionT; //協作總貢獻度
- tmidAnalysisRow.peerAct += IotTeachingDatRow.peerAct; //互評活動次數
- tmidAnalysisRow.peerStuParticipationT += IotTeachingDatRow.peerStuParticipationT; //互評學生參與總次數
- if (IotTeachingDatRow.useTransMode.Equals("1")) tmidAnalysisRow.useTransMode++; //有使用透明模式
- if (IotTeachingDatRow.useMiniMode.Equals("1")) tmidAnalysisRow.useMiniMode++; //有使用最小化模式
- if (!string.IsNullOrWhiteSpace(ver) && !tmidAnalysisRow.verList.Contains(ver))
- {
- tmidAnalysisRow.verList.Add(ver);
- }
- if (addFlg)
- {
- TmidAnalysisList.Add(tmidAnalysisRow);
- }
- }
- }
- }
- //1.記入CSV2 Redis TmidAnalysis:Day
- //2.記入CSV2 CosmosDB Day
- if (TmidAnalysisList.Count > 0)
- {
- //資料整形
- Dictionary<string, Dictionary<string, string>> redisTmidFieldDic = new Dictionary<string, Dictionary<string, string>>(); //架構: key => tmid => JsonContent
- List<TmidAnalysisCosmos> cosmosTmidList = new List<TmidAnalysisCosmos>();
- Dictionary<string, TmidAnalysisCosmos> cosmosAllTmidSumDayDic = new Dictionary<string, TmidAnalysisCosmos>();
- foreach (TmidAnalysis tmidAnalysisRow in TmidAnalysisList)
- {
- //Redis整形
- string toolType = tmidAnalysisRow.toolType;
- string tmid = tmidAnalysisRow.tmid;
- string hkey = $"TmidAnalysis:Day:{toolType}:{y}{m}{d}";
- string fieldContent = tmidAnalysisRow.ToJsonString();
- if (redisTmidFieldDic.ContainsKey(hkey)) redisTmidFieldDic[hkey].Add(tmid, fieldContent);
- else redisTmidFieldDic.Add(hkey, new Dictionary<string, string>() { { tmid, fieldContent } });
- //CosmosDB整形
- TmidAnalysisCosmos TmidAnalysisCosmosRow = tmidAnalysisRow.ToJsonString().ToObject<TmidAnalysisCosmos>();
- TmidAnalysisCosmosRow.date = $"{y}{m}{d}";
- TmidAnalysisCosmosRow.year = Convert.ToInt32(y, 10);
- TmidAnalysisCosmosRow.month = Convert.ToInt32(m, 10);
- TmidAnalysisCosmosRow.day = Convert.ToInt32(d, 10);
- DateTimeOffset dateTime = new DateTimeOffset(TmidAnalysisCosmosRow.year, TmidAnalysisCosmosRow.month, TmidAnalysisCosmosRow.day, 0, 0, 0, TimeSpan.Zero);
- TmidAnalysisCosmosRow.dateTime = dateTime.ToUnixTimeSeconds();
- TmidAnalysisCosmosRow.id = $"{TmidAnalysisCosmosRow.toolType}-{TmidAnalysisCosmosRow.date}-{tmid}";
- TmidAnalysisCosmosRow.dateUnit = "day";
- TmidAnalysisCosmosRow.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- cosmosTmidList.Add(TmidAnalysisCosmosRow);
- }
- //記入Redis
- if (redisTmidFieldDic.Count > 0)
- {
- foreach (KeyValuePair<string, Dictionary<string, string>> hkeyItem in redisTmidFieldDic)
- {
- string hkey = hkeyItem.Key;
- List<HashEntry> hvalList = new List<HashEntry>();
- Dictionary<string, string> fieldDic = hkeyItem.Value;
- foreach (KeyValuePair<string, string> tmidItem in fieldDic)
- {
- string tmid = tmidItem.Key;
- string fieldContent = tmidItem.Value;
- hvalList.Add(new HashEntry($"{tmid}", fieldContent));
- }
- await redisClinet8.HashSetAsync(hkey, hvalList.ToArray());
- }
- }
- //記入CosmosDB
- if (cosmosTmidList.Count > 0)
- {
- foreach (TmidAnalysisCosmos cosmosTmidRow in cosmosTmidList)
- {
- //各TMID每日CosmosDB記入
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TmidAnalysisCosmos>(cosmosTmidRow);
- //所有TMID每日數值加總 數值生成 cosmosAllSchSumDayDic -> key:toolType val:cosmosAllSchSumDay
- cosmosAllTmidSumDayDic = GenAnalysisRowSumData(cosmosAllTmidSumDayDic, cosmosTmidRow, calPropList, "day");
- }
- //每日所有TMID數據總計CosmosDB記入
- foreach (KeyValuePair<string, TmidAnalysisCosmos> tmidItem in cosmosAllTmidSumDayDic)
- {
- string toolType = tmidItem.Key;
- TmidAnalysisCosmos cosmosAllTmidSumDay = tmidItem.Value;
- cosmosAllTmidSumDay.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TmidAnalysisCosmos>(cosmosAllTmidSumDay);
- }
- }
- }
- //取 Redis 該月所有 TmidAnalysis:Day
- //1.生成 Redis TmidAnalysis:Month
- //2.生成 CosmosDB Month
- Dictionary<string, Dictionary<string, TmidAnalysis>> TmidAnalysisListMonth = new Dictionary<string, Dictionary<string, TmidAnalysis>>();
- Dictionary<string, TmidAnalysisCosmos> cosmosAllTmidSumMonthDic = new Dictionary<string, TmidAnalysisCosmos>();
- List<TmidAnalysisCosmos> cosmosTmidListMonth = new List<TmidAnalysisCosmos>();
- string patternD = $"TmidAnalysis:Day:HiT*:{y}{m}*";
- List<string> keysDayList = ScanRedisKeysByPattern(_azureRedis, patternD);
- if (keysDayList.Count > 0)
- {
- foreach (string keyDay in keysDayList)
- {
- string[] keyItemList = keyDay.Split(':'); //TmidAnalysis:Day:HiTeach:20230326
- string toolType = keyItemList[2];
- string dateStrD = keyItemList[3];
- string dateStrD_y = string.Empty;
- string dateStrD_m = string.Empty;
- string dateStrD_d = string.Empty;
- Regex rgx = new Regex(@"[0-9]{8}");
- if (rgx.IsMatch(dateStrD))
- {
- dateStrD_y = dateStrD.Substring(0, 4);
- dateStrD_m = dateStrD.Substring(4, 2);
- dateStrD_d = dateStrD.Substring(6, 2);
- }
- string tmidAnalMonthKey = $"TmidAnalysis:Month:{toolType}:{dateStrD_y}{dateStrD_m}";
- bool tmidAnalysisDayExist = await redisClinet8.KeyExistsAsync(keyDay);
- if (tmidAnalysisDayExist && !string.IsNullOrWhiteSpace(dateStrD_y) && !string.IsNullOrWhiteSpace(dateStrD_m) && !string.IsNullOrWhiteSpace(dateStrD_d))
- {
- HashEntry[] hsetDay = redisClinet8.HashGetAll(keyDay); //某日 ProdAnalysis:Day所有學校的統計項目
- foreach (HashEntry hset in hsetDay)
- {
- string keyTMID = hset.Name;
- string valTmidDataJson = hset.Value;
- TmidAnalysis tmidDataTodo = valTmidDataJson.ToObject<TmidAnalysis>();
- //Redis Month 資料生成
- if (TmidAnalysisListMonth.ContainsKey(tmidAnalMonthKey)) //月Dic已有此key => TMID累加
- {
- if (TmidAnalysisListMonth[$"{tmidAnalMonthKey}"].ContainsKey($"{keyTMID}"))
- {
- TmidAnalysis TmidDataNow = TmidAnalysisListMonth[$"{tmidAnalMonthKey}"][$"{keyTMID}"];
- foreach (PropertyInfo propertyInfo in TmidDataNow.GetType().GetProperties())
- {
- if (calPropList.Contains(propertyInfo.Name))
- {
- var propType = propertyInfo.PropertyType;
- var valNow = propertyInfo.GetValue(TmidDataNow);
- var valTodo = tmidDataTodo.GetType().GetProperty(propertyInfo.Name).GetValue(tmidDataTodo);
- if (propType.Equals(typeof(long))) propertyInfo.SetValue(TmidDataNow, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
- else propertyInfo.SetValue(TmidDataNow, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
- }
- }
- TmidDataNow.deviceList = TmidDataNow.deviceList.Union(tmidDataTodo.deviceList).ToList();
- TmidDataNow.deviceCnt = TmidDataNow.deviceList.Count;
- TmidDataNow.deviceAuthList = TmidDataNow.deviceAuthList.Union(tmidDataTodo.deviceAuthList).ToList();
- TmidDataNow.deviceAuth = TmidDataNow.deviceAuthList.Count;
- TmidDataNow.deviceNoAuthList = TmidDataNow.deviceNoAuthList.Union(tmidDataTodo.deviceNoAuthList).ToList();
- TmidDataNow.deviceNoAuth = TmidDataNow.deviceNoAuthList.Count;
- TmidDataNow.tmidList = TmidDataNow.tmidList.Union(tmidDataTodo.tmidList).ToList();
- TmidDataNow.tmidCnt = TmidDataNow.tmidList.Count;
- TmidDataNow.verList = TmidDataNow.verList.Union(tmidDataTodo.verList).ToList();
- }
- //無TMID資料 => 該TMID資料放入
- else
- {
- TmidAnalysisListMonth[$"{tmidAnalMonthKey}"][$"{keyTMID}"] = tmidDataTodo;
- }
- }
- else //無此月資料 => 所有TMID資料放入
- {
- TmidAnalysisListMonth.Add(tmidAnalMonthKey, new Dictionary<string, TmidAnalysis>() { { keyTMID, tmidDataTodo } });
- }
- }
- }
- }
- }
- if (TmidAnalysisListMonth.Count > 0)
- {
- foreach (KeyValuePair<string, Dictionary<string, TmidAnalysis>> item in TmidAnalysisListMonth)
- {
- string monthRedisKey = item.Key;
- List<HashEntry> hvalList = new List<HashEntry>();
- Dictionary<string, TmidAnalysis> monthRedisTmidDIc = item.Value;
- foreach (KeyValuePair<string, TmidAnalysis> monthRedisTmidItem in monthRedisTmidDIc)
- {
- string monthRedisTmid = monthRedisTmidItem.Key;
- TmidAnalysis monthRedisTmidData = monthRedisTmidItem.Value;
- //Redis資料製作
- hvalList.Add(new HashEntry(monthRedisTmid, monthRedisTmidData.ToJsonString()));
- //CosmosDB資料製作
- TmidAnalysisCosmos cosmosTmidRow = monthRedisTmidData.ToJsonString().ToObject<TmidAnalysisCosmos>();
- cosmosTmidRow.date = $"{y}{m}";
- cosmosTmidRow.year = Convert.ToInt32(y, 10);
- cosmosTmidRow.month = Convert.ToInt32(m, 10);
- DateTimeOffset dateTime = new DateTimeOffset(cosmosTmidRow.year, cosmosTmidRow.month, 1, 0, 0, 0, TimeSpan.Zero);
- cosmosTmidRow.dateTime = dateTime.ToUnixTimeSeconds();
- cosmosTmidRow.id = $"{monthRedisTmidData.toolType}-{cosmosTmidRow.date}-{monthRedisTmid}";
- cosmosTmidRow.dateUnit = "month";
- cosmosTmidRow.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- cosmosTmidListMonth.Add(cosmosTmidRow);
- }
- //記入Redis
- await redisClinet8.HashSetAsync($"{monthRedisKey}", hvalList.ToArray());
- }
- //記入CosmosDB
- if (cosmosTmidListMonth.Count > 0)
- {
- foreach (TmidAnalysisCosmos cosmosTmidRow in cosmosTmidListMonth)
- {
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TmidAnalysisCosmos>(cosmosTmidRow);
- //所有學校數值加總 數值生成 cosmosAllSchSumDayDic -> key:toolType val:cosmosAllSchSumDay
- cosmosAllTmidSumMonthDic = GenAnalysisRowSumData(cosmosAllTmidSumMonthDic, cosmosTmidRow, calPropList, "day");
- }
- //每月所有TMID數據總計CosmosDB記入
- foreach (KeyValuePair<string, TmidAnalysisCosmos> tmidItem in cosmosAllTmidSumMonthDic)
- {
- string toolType = tmidItem.Key;
- TmidAnalysisCosmos cosmosAllTmidSumMonth = tmidItem.Value;
- cosmosAllTmidSumMonth.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TmidAnalysisCosmos>(cosmosAllTmidSumMonth);
- }
- }
- }
- //取該年所有 CosmosDB 該年所有月份 生成CosmosDB年資料
- Dictionary<string, Dictionary<string, TmidAnalysisCosmos>> TmidAnalysisListYear = new Dictionary<string, Dictionary<string, TmidAnalysisCosmos>>();
- Dictionary<string, TmidAnalysisCosmos> cosmosAllTmidSumYearDic = new Dictionary<string, TmidAnalysisCosmos>();
- var query = $"SELECT * FROM c WHERE c.year = {y} AND c.dateUnit = 'month' AND c.tmid != 'alltmid'";
- await foreach (var itemcr in _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("TmidAnalysis") }))
- {
- var json = await JsonDocument.ParseAsync(itemcr.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
- {
- TmidAnalysisCosmos TmidDataTodo = obj.ToObject<TmidAnalysisCosmos>();
- string toolType = TmidDataTodo.toolType;
- string tmid = TmidDataTodo.tmid;
- //年Dic已有此key => 分校累加
- if (TmidAnalysisListYear.ContainsKey(toolType))
- {
- if (TmidAnalysisListYear[$"{toolType}"].ContainsKey($"{tmid}"))
- {
- TmidAnalysisCosmos TmidDataNow = TmidAnalysisListYear[$"{toolType}"][$"{tmid}"];
- foreach (PropertyInfo propertyInfo in TmidDataNow.GetType().GetProperties())
- {
- if (calPropList.Contains(propertyInfo.Name))
- {
- var propType = propertyInfo.PropertyType;
- var valNow = propertyInfo.GetValue(TmidDataNow);
- var valTodo = TmidDataTodo.GetType().GetProperty(propertyInfo.Name).GetValue(TmidDataTodo);
- if (propType.Equals(typeof(long))) propertyInfo.SetValue(TmidDataNow, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
- else propertyInfo.SetValue(TmidDataNow, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
- }
- }
- TmidDataNow.deviceList = TmidDataNow.deviceList.Union(TmidDataTodo.deviceList).ToList();
- TmidDataNow.deviceCnt = TmidDataNow.deviceList.Count;
- TmidDataNow.deviceAuthList = TmidDataNow.deviceAuthList.Union(TmidDataTodo.deviceAuthList).ToList();
- TmidDataNow.deviceAuth = TmidDataNow.deviceAuthList.Count;
- TmidDataNow.deviceNoAuthList = TmidDataNow.deviceNoAuthList.Union(TmidDataTodo.deviceNoAuthList).ToList();
- TmidDataNow.deviceNoAuth = TmidDataNow.deviceNoAuthList.Count;
- TmidDataNow.tmidList = TmidDataNow.tmidList.Union(TmidDataTodo.tmidList).ToList();
- TmidDataNow.tmidCnt = TmidDataNow.tmidList.Count;
- TmidDataNow.verList = TmidDataNow.verList.Union(TmidDataTodo.verList).ToList();
- }
- //無此校資料 => 該校資料放入
- else
- {
- TmidAnalysisCosmos TmidDataNow = TmidDataTodo;
- TmidDataNow.date = $"{y}";
- TmidDataNow.year = Convert.ToInt32(y, 10);
- TmidDataNow.month = 0;
- DateTimeOffset dateTime = new DateTimeOffset(TmidDataNow.year, 1, 1, 0, 0, 0, TimeSpan.Zero);
- TmidDataNow.dateTime = dateTime.ToUnixTimeSeconds();
- TmidDataNow.id = $"{toolType}-{y}-{tmid}";
- TmidDataNow.dateUnit = "year";
- TmidAnalysisListYear[$"{toolType}"][$"{tmid}"] = TmidDataNow;
- }
- }
- //無此年資料 => 所有學校資料放入
- else
- {
- TmidAnalysisCosmos TmidDataNow = TmidDataTodo;
- TmidDataNow.date = $"{y}";
- TmidDataNow.year = Convert.ToInt32(y, 10);
- TmidDataNow.month = 0;
- DateTimeOffset dateTime = new DateTimeOffset(TmidDataNow.year, 1, 1, 0, 0, 0, TimeSpan.Zero);
- TmidDataNow.dateTime = dateTime.ToUnixTimeSeconds();
- TmidDataNow.id = $"{toolType}-{y}-{tmid}";
- TmidDataNow.dateUnit = "year";
- TmidAnalysisListYear.Add(toolType, new Dictionary<string, TmidAnalysisCosmos>() { { tmid, TmidDataNow } });
- }
- }
- }
- }
- if (TmidAnalysisListYear.Count > 0)
- {
- foreach (KeyValuePair<string, Dictionary<string, TmidAnalysisCosmos>> item in TmidAnalysisListYear)
- {
- //string toolType = item.Key;
- TmidAnalysisCosmos TmidDataNow = new TmidAnalysisCosmos(); //當年某產品所有學校總和
- Dictionary<string, TmidAnalysisCosmos> yearCosmosTmidDIc = item.Value;
- foreach (KeyValuePair<string, TmidAnalysisCosmos> yearCosmosTmidItem in yearCosmosTmidDIc)
- {
- string tmid = yearCosmosTmidItem.Key;
- TmidAnalysisCosmos cosmosTmidRow = yearCosmosTmidItem.Value;
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TmidAnalysisCosmos>(cosmosTmidRow);
- //每年所有學校數據總計CosmosDB記入
- cosmosAllTmidSumYearDic = GenAnalysisRowSumData(cosmosAllTmidSumYearDic, cosmosTmidRow, calPropList, "year");
- }
- //每年所有學校數據總計CosmosDB記入
- foreach (KeyValuePair<string, TmidAnalysisCosmos> tmidItem in cosmosAllTmidSumYearDic)
- {
- string toolType = tmidItem.Key;
- TmidAnalysisCosmos cosmosAllTmidSumYear = tmidItem.Value;
- cosmosAllTmidSumYear.createDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TmidAnalysisCosmos>(cosmosAllTmidSumYear);
- }
- //await _azureCosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TmidAnalysisCosmos>(TmidDataNow);
- }
- }
- }
- catch (Exception ex)
- {
- _ = _dingDing.SendBotMsg($"BI,{Environment.GetEnvironmentVariable("Option:Location")},CreatTmidProdAnalData() 生成TMID年月日日IOT統計資料錯誤\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.研發C組);
- }
- }
- //生成年月日 Device IOT產品分析數據 [待做]
- private static async Task CreatDeviceAnalData(AzureRedisFactory _azureRedis, CosmosClient _azureCosmosClient, DingDing _dingDing, string y, string m, string d, List<IotTeachingData> IotTeachingDataList)
- {
- try
- {
- var redisClinet8 = _azureRedis.GetRedisClient(8);
- //1. 從IOT 取得DeviceID 或 IP
- //2. 從DeviceID 或 IP 算出地理位置(國省市區)
- //3. 依照各地理位置進行項目統計;統計項目和學校及TMID統計項目相同
- }
- catch (Exception ex)
- {
- _ = _dingDing.SendBotMsg($"BI,{Environment.GetEnvironmentVariable("Option:Location")},CreatDeviceAnalData() 生成TMID年月日日IOT統計資料錯誤\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.研發C組);
- }
- }
- //累加各校每日/月總計資料,生成所有學校每日/月總計資料
- private static Dictionary<string, ProdAnalysisCosmos> GenAnalysisRowSumData(Dictionary<string, ProdAnalysisCosmos> cosmosAllSumDic, ProdAnalysisCosmos cosmosRow, List<string> calPropList, string dataType) //dataType:"day","month","year"
- {
- try
- {
- string toolType = cosmosRow.toolType;
- string schoolId = "allschool";
- int year = 0;
- int month = 1;
- int day = 1;
- switch (dataType)
- {
- case "day":
- year = cosmosRow.year;
- month = cosmosRow.month;
- day = cosmosRow.day;
- break;
- case "month":
- year = cosmosRow.year;
- month = cosmosRow.month;
- break;
- case "year":
- year = cosmosRow.year;
- break;
- }
- ProdAnalysisCosmos cosmosAllSum = new ProdAnalysisCosmos();
- if (cosmosAllSumDic.ContainsKey(toolType)) cosmosAllSum = cosmosAllSumDic[toolType];
- foreach (PropertyInfo propertyInfo in cosmosAllSum.GetType().GetProperties()) //累加項目
- {
- if (calPropList.Contains(propertyInfo.Name))
- {
- var propType = propertyInfo.PropertyType;
- var valNow = propertyInfo.GetValue(cosmosAllSum);
- var valTodo = cosmosRow.GetType().GetProperty(propertyInfo.Name).GetValue(cosmosRow);
- if (propType.Equals(typeof(long))) propertyInfo.SetValue(cosmosAllSum, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
- else propertyInfo.SetValue(cosmosAllSum, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
- }
- }
- cosmosAllSum.schoolId = schoolId;
- cosmosAllSum.toolType = cosmosRow.toolType;
- cosmosAllSum.date = cosmosRow.date;
- cosmosAllSum.id = $"{cosmosAllSum.toolType}-{cosmosAllSum.date}-{schoolId}";
- cosmosAllSum.dateUnit = dataType;
- cosmosAllSum.year = year;
- cosmosAllSum.month = month;
- cosmosAllSum.day = day;
- DateTimeOffset dateTime = new DateTimeOffset(year, month, day, 0, 0, 0, TimeSpan.Zero);
- cosmosAllSum.dateTime = dateTime.ToUnixTimeSeconds();
- cosmosAllSum.deviceList = cosmosAllSum.deviceList.Union(cosmosRow.deviceList).ToList();
- cosmosAllSum.deviceCnt = cosmosAllSum.deviceList.Count;
- cosmosAllSum.deviceAuthList = cosmosAllSum.deviceAuthList.Union(cosmosRow.deviceAuthList).ToList();
- cosmosAllSum.deviceAuth = cosmosAllSum.deviceAuthList.Count;
- cosmosAllSum.deviceNoAuthList = cosmosAllSum.deviceNoAuthList.Union(cosmosRow.deviceNoAuthList).ToList();
- cosmosAllSum.deviceNoAuth = cosmosAllSum.deviceNoAuthList.Count;
- cosmosAllSum.tmidList = cosmosAllSum.tmidList.Union(cosmosRow.tmidList).ToList();
- cosmosAllSum.tmidCnt = cosmosAllSum.tmidList.Count;
- decimal learnParticipationTmp = (cosmosAllSum.learnParticipationCnt > 0) ? (decimal)cosmosAllSum.learnParticipationT / (decimal)cosmosAllSum.learnParticipationCnt : 0;
- cosmosAllSum.learnParticipation = Math.Round(learnParticipationTmp, 2); //學習參與度指數(平均)
- if (cosmosAllSumDic.ContainsKey(toolType)) cosmosAllSumDic[toolType] = cosmosAllSum;
- else cosmosAllSumDic.Add(toolType, cosmosAllSum);
- return cosmosAllSumDic;
- }
- catch (Exception ex)
- {
- return cosmosAllSumDic;
- }
- }
- //累加各TMID每日/月總計資料,生成所有TMID每日/月總計資料
- private static Dictionary<string, TmidAnalysisCosmos> GenAnalysisRowSumData(Dictionary<string, TmidAnalysisCosmos> cosmosAllSumDic, TmidAnalysisCosmos cosmosRow, List<string> calPropList, string dataType) //dataType:"day","month","year"
- {
- try
- {
- string toolType = cosmosRow.toolType;
- string tmid = "alltmid";
- int year = 0;
- int month = 1;
- int day = 1;
- switch (dataType)
- {
- case "day":
- year = cosmosRow.year;
- month = cosmosRow.month;
- day = cosmosRow.day;
- break;
- case "month":
- year = cosmosRow.year;
- month = cosmosRow.month;
- break;
- case "year":
- year = cosmosRow.year;
- break;
- }
- TmidAnalysisCosmos cosmosAllSum = new TmidAnalysisCosmos();
- if (cosmosAllSumDic.ContainsKey(toolType)) cosmosAllSum = cosmosAllSumDic[toolType];
- foreach (PropertyInfo propertyInfo in cosmosAllSum.GetType().GetProperties()) //累加項目
- {
- if (calPropList.Contains(propertyInfo.Name))
- {
- var propType = propertyInfo.PropertyType;
- var valNow = propertyInfo.GetValue(cosmosAllSum);
- var valTodo = cosmosRow.GetType().GetProperty(propertyInfo.Name).GetValue(cosmosRow);
- if (propType.Equals(typeof(long))) propertyInfo.SetValue(cosmosAllSum, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
- else propertyInfo.SetValue(cosmosAllSum, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
- }
- }
- cosmosAllSum.tmid = tmid;
- cosmosAllSum.toolType = cosmosRow.toolType;
- cosmosAllSum.date = cosmosRow.date;
- cosmosAllSum.id = $"{cosmosAllSum.toolType}-{cosmosAllSum.date}-{tmid}";
- cosmosAllSum.dateUnit = dataType;
- cosmosAllSum.year = year;
- cosmosAllSum.month = month;
- cosmosAllSum.day = day;
- DateTimeOffset dateTime = new DateTimeOffset(year, month, day, 0, 0, 0, TimeSpan.Zero);
- cosmosAllSum.dateTime = dateTime.ToUnixTimeSeconds();
- cosmosAllSum.deviceList = cosmosAllSum.deviceList.Union(cosmosRow.deviceList).ToList();
- cosmosAllSum.deviceCnt = cosmosAllSum.deviceList.Count;
- cosmosAllSum.deviceAuthList = cosmosAllSum.deviceAuthList.Union(cosmosRow.deviceAuthList).ToList();
- cosmosAllSum.deviceAuth = cosmosAllSum.deviceAuthList.Count;
- cosmosAllSum.deviceNoAuthList = cosmosAllSum.deviceNoAuthList.Union(cosmosRow.deviceNoAuthList).ToList();
- cosmosAllSum.deviceNoAuth = cosmosAllSum.deviceNoAuthList.Count;
- cosmosAllSum.tmidList = cosmosAllSum.tmidList.Union(cosmosRow.tmidList).ToList();
- cosmosAllSum.tmidCnt = cosmosAllSum.tmidList.Count;
- cosmosAllSum.verList = cosmosAllSum.verList.Union(cosmosRow.verList).ToList();
- decimal learnParticipationTmp = (cosmosAllSum.learnParticipationCnt > 0) ? (decimal)cosmosAllSum.learnParticipationT / (decimal)cosmosAllSum.learnParticipationCnt : 0;
- cosmosAllSum.learnParticipation = Math.Round(learnParticipationTmp, 2); //學習參與度指數(平均)
- if (cosmosAllSumDic.ContainsKey(toolType)) cosmosAllSumDic[toolType] = cosmosAllSum;
- else cosmosAllSumDic.Add(toolType, cosmosAllSum);
- return cosmosAllSumDic;
- }
- catch (Exception ex)
- {
- return cosmosAllSumDic;
- }
- }
- /// <summary>
- /// 取得Redis(8)符合搜尋模式的key
- /// </summary>
- /// <param name="pattern"></param>
- /// <returns></returns>
- public static List<string> ScanRedisKeysByPattern(AzureRedisFactory _azureRedis, string pattern)
- {
- var redisClinet8 = _azureRedis.GetRedisClient(8);
- var keys = new HashSet<RedisKey>();
- int nextCursor = 0;
- do
- {
- RedisResult redisResult = redisClinet8.Execute("SCAN", nextCursor.ToString(), "MATCH", pattern, "COUNT", "1000");
- var innerResult = (RedisResult[])redisResult;
- nextCursor = int.Parse((string)innerResult[0]);
- List<RedisKey> resultLines = ((RedisKey[])innerResult[1]).ToList();
- keys.UnionWith(resultLines);
- }
- while (nextCursor != 0);
- List<string> result = new List<string>();
- if (keys.Count > 0)
- {
- foreach (RedisKey key in keys)
- {
- result.Add(key.ToString());
- }
- }
- return result;
- }
- }
- }
|