|
@@ -585,6 +585,241 @@ namespace TEAMModelOS.SDK.Models.Service
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 計算統測活動各報名班級的各活動階段進行狀況
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="jointEventId"></param>
|
|
|
+ /// <param name="jointGroupId"></param>
|
|
|
+ /// <param name="creatorId"></param>
|
|
|
+ /// <param name="jointEventGroupDb">要取得的報名課程,若給null則會從DB取</param>
|
|
|
+ /// <param name="schedule">若給null則所有schedule的status(報名、熱身賽、決賽)都計算</param>
|
|
|
+ /// <param name="update">是否更新DB true:更新 false:不更新</param>
|
|
|
+ public static async Task<JointEventGroupDb> CalJointCourseGroupScheduleStatusAsync(CosmosClient client, string jointEventId, string jointGroupId, string creatorId, JointEventGroupDb jointEventGroupDb = null, JointEventSchedule schedule = null)
|
|
|
+ {
|
|
|
+ long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
+ string scope = "private"; //先只指定個人
|
|
|
+ string container = (scope.Equals("school")) ? Constant.School : Constant.Teacher;
|
|
|
+ //取得統測活動
|
|
|
+ JointEvent jointEvent = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<JointEvent>(jointEventId, new PartitionKey("JointEvent"));
|
|
|
+ if (jointEvent == null)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ //取得報名名單
|
|
|
+ if (jointEventGroupDb == null)
|
|
|
+ {
|
|
|
+ StringBuilder stringBuilder = new($"SELECT * FROM c WHERE c.jointEventId = '{jointEventId}' AND c.jointGroupId = '{jointGroupId}' AND c.creatorId = '{creatorId}' AND c.type = 'regular' ");
|
|
|
+ await foreach (var item in client.GetContainer(Constant.TEAMModelOS, container).GetItemQueryStreamIteratorSql(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("JointCourse") }))
|
|
|
+ {
|
|
|
+ using var json = await JsonDocument.ParseAsync(item.Content);
|
|
|
+ if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
|
|
|
+ {
|
|
|
+ foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
|
|
|
+ {
|
|
|
+ jointEventGroupDb = obj.ToObject<JointEventGroupDb>();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (jointEventGroupDb == null)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ //計算各階段Status
|
|
|
+ List<JointEventSchedule> jointScheduleList = new List<JointEventSchedule>(); //要計算的活動階段
|
|
|
+ if (schedule != null) jointScheduleList.Add(schedule);
|
|
|
+ else jointScheduleList = jointEvent.schedule;
|
|
|
+ ///計算邏輯
|
|
|
+ foreach (JointEventGroupBase.JointEventGroupCourse courseRow in jointEventGroupDb.courseLists) //各報名課程
|
|
|
+ {
|
|
|
+ string courseId = courseRow.courseId;
|
|
|
+ foreach (JointEventGroupBase.JointEventGroupCourseGroup courseGroup in courseRow.groupLists) //各報名課程名單(各班)
|
|
|
+ {
|
|
|
+ string groupId = courseGroup.id;
|
|
|
+ foreach (JointEventSchedule eventSchedule in jointScheduleList) //各活動階段
|
|
|
+ {
|
|
|
+ //活動階段篩選:報名、熱身賽、決賽 才記入
|
|
|
+ if(eventSchedule.type.Equals("join") || eventSchedule.type.Equals("exam"))
|
|
|
+ {
|
|
|
+ JointEventGroupBase.JointEventGroupCourseGroup.JointEventGroupCourseGroupSchedule courseGroupSchedule = courseGroup.schedule.FirstOrDefault(s => s.id.Equals(eventSchedule.id));
|
|
|
+ if (courseGroupSchedule == null) //不存在 > 新建
|
|
|
+ {
|
|
|
+ courseGroupSchedule = new JointEventGroupBase.JointEventGroupCourseGroup.JointEventGroupCourseGroupSchedule()
|
|
|
+ {
|
|
|
+ id = eventSchedule.id,
|
|
|
+ status = "undo"
|
|
|
+ };
|
|
|
+ courseGroup.schedule.Add(courseGroupSchedule);
|
|
|
+ courseGroupSchedule = courseGroup.schedule.FirstOrDefault(s => s.id.Equals(eventSchedule.id));
|
|
|
+ }
|
|
|
+ courseGroupSchedule.status = await GetGroupJointScheduleStatus(client, jointEventId, jointGroupId, groupId, eventSchedule, jointEventGroupDb, creatorId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return jointEventGroupDb;
|
|
|
+ }
|
|
|
+
|
|
|
+ //判斷某groupId在某JointSchedule是否完成
|
|
|
+ /// <summary>
|
|
|
+ /// 判斷某groupId在某JointSchedule是否完成
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="jointEventId"></param>
|
|
|
+ /// <param name="jointGroupId"></param>
|
|
|
+ /// <param name="groupId"></param>
|
|
|
+ /// <param name="schedule"></param>
|
|
|
+ /// <param name="jointCourse">統測報名班級DB document 若為null則由DB取</param>
|
|
|
+ /// <param name="creatorId"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private static async Task<string> GetGroupJointScheduleStatus(CosmosClient client, string jointEventId, string jointGroupId, string groupId, JointEventSchedule schedule, JointEventGroupDb jointCourse, string creatorId)
|
|
|
+ {
|
|
|
+ long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
+ string result = "undo";
|
|
|
+ string scope = "private"; //先只指定個人
|
|
|
+ string container = (scope.Equals("school")) ? Constant.School : Constant.Teacher;
|
|
|
+ if (schedule.startTime <= now && now <= schedule.endTime) //活動階段在進行中才續行做Status判斷
|
|
|
+ {
|
|
|
+ switch (schedule.type)
|
|
|
+ {
|
|
|
+ //報名
|
|
|
+ ///算出邏輯:(1)可取得該報名課程名單 -> complete (2)無法取得 -> undo
|
|
|
+ case "join":
|
|
|
+ if (jointCourse == null)
|
|
|
+ {
|
|
|
+ StringBuilder stringBuilderJointCourse = new($"SELECT * FROM c WHERE c.jointEventId = '{jointEventId}' AND c.jointGroupId = '{jointGroupId}' AND c.creatorId = '{creatorId}' AND c.type = 'regular' ");
|
|
|
+ await foreach (var item in client.GetContainer(Constant.TEAMModelOS, container).GetItemQueryStreamIteratorSql(queryText: stringBuilderJointCourse.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("JointCourse") }))
|
|
|
+ {
|
|
|
+ using var json = await JsonDocument.ParseAsync(item.Content);
|
|
|
+ if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
|
|
|
+ {
|
|
|
+ foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
|
|
|
+ {
|
|
|
+ jointCourse = obj.ToObject<JointEventGroupDb>();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (jointCourse == null)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ foreach (JointEventGroupBase.JointEventGroupCourse courseInfo in jointCourse.courseLists)
|
|
|
+ {
|
|
|
+ JointEventGroupBase.JointEventGroupCourseGroup groupExist = courseInfo.groupLists.FirstOrDefault(g => g.id.Equals(groupId));
|
|
|
+ if (groupExist != null)
|
|
|
+ {
|
|
|
+ result = "complete";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ //競賽
|
|
|
+ ///算出邏輯: (1)無法取得報名班級(決賽班級) -> 資格不符(disqualify)
|
|
|
+ /// (2)統測評量數 > 0 && 個人評量完成數(學生有一人有作答則是為完成) == 統測評量數 -> 完成(complete)
|
|
|
+ /// (3)統測評量數 > 0 && 個人評量完成數 > 0 && 統測評量數 > 個人評量完成數 -> 進行中(doing)
|
|
|
+ /// (4)default -> undo
|
|
|
+ case "exam":
|
|
|
+ //取得老師報名課程或決賽老師課程
|
|
|
+ List<JointEventGroupDb> jointEventGroup = new List<JointEventGroupDb>(); //個人課程
|
|
|
+ StringBuilder stringBuilderEventGroup = new($"SELECT * FROM c WHERE c.jointEventId = '{jointEventId}' AND c.jointGroupId = '{jointGroupId}' ");
|
|
|
+ if (schedule.examType.Equals("regular")) //熱身賽
|
|
|
+ {
|
|
|
+ stringBuilderEventGroup.Append($" AND (c.type = 'regular' OR NOT IS_DEFINED(c.type) OR IS_NULL(c.type)) ");
|
|
|
+ }
|
|
|
+ else if (schedule.examType.Equals("custom")) //決賽
|
|
|
+ {
|
|
|
+ stringBuilderEventGroup.Append($" AND c.type = 'custom' AND c.jointScheduleId = '{schedule.id}' ");
|
|
|
+ }
|
|
|
+ if (!string.IsNullOrWhiteSpace(creatorId))
|
|
|
+ {
|
|
|
+ stringBuilderEventGroup.Append($" AND c.creatorId = '{creatorId}' ");
|
|
|
+ }
|
|
|
+ await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryStreamIteratorSql(queryText: stringBuilderEventGroup.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("JointCourse") }))
|
|
|
+ {
|
|
|
+ using var json = await JsonDocument.ParseAsync(item.Content);
|
|
|
+ if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
|
|
|
+ {
|
|
|
+ foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
|
|
|
+ {
|
|
|
+ jointEventGroup.Add(obj.ToObject<JointEventGroupDb>());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //取得本Schedule的所有JointExam
|
|
|
+ List<string> jointExamIdList = new List<string>();
|
|
|
+ StringBuilder stringBuilderJointExam = new($"SELECT DISTINCT VALUE c.id FROM c WHERE c.jointEventId = '{jointEventId}' AND c.jointGroupId = '{jointGroupId}' AND c.jointScheduleId = '{schedule.id}' ");
|
|
|
+ var resultJointExam = await client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetList<string>(stringBuilderJointExam.ToString(), $"JointExam");
|
|
|
+ if (resultJointExam.list.IsNotEmpty())
|
|
|
+ {
|
|
|
+ jointExamIdList = new List<string>(resultJointExam.list);
|
|
|
+ }
|
|
|
+ //取得所有個人評量
|
|
|
+ List<string> examIdList = new List<string>();
|
|
|
+ string sqlExam = $"SELECT DISTINCT VALUE c.id FROM c WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(jointExamIdList)}, c.jointExamId) AND ARRAY_CONTAINS(c.stuLists, '{groupId}') AND CONTAINS(c.code, 'Exam-')";
|
|
|
+ await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetItemQueryIteratorSql<string>(queryText: sqlExam, requestOptions: new QueryRequestOptions { }))
|
|
|
+ {
|
|
|
+ examIdList.Add(item);
|
|
|
+ }
|
|
|
+ //取得所有考試的作答結果
|
|
|
+ List<string> finishExamIdList = new List<string>();
|
|
|
+ string sqlExamClassResult = $"SELECT c.examId, c.info.id as classId, c.studentAnswers FROM c WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(examIdList)}, c.examId) AND c.info.id = '{groupId}' AND c.progress=true AND CONTAINS(c.code, 'ExamClassResult')";
|
|
|
+ await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetItemQueryStreamIteratorSql(queryText: sqlExamClassResult, requestOptions: new QueryRequestOptions() { }))
|
|
|
+ {
|
|
|
+ using var json = await JsonDocument.ParseAsync(item.Content);
|
|
|
+ if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
|
|
|
+ {
|
|
|
+ foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
|
|
|
+ {
|
|
|
+ string examId = obj.GetProperty("examId").ToString();
|
|
|
+ string classId = obj.GetProperty("classId").ToString();
|
|
|
+ List<List<string>> studentAnswers = obj.GetProperty("studentAnswers").ToObject<List<List<string>>>();
|
|
|
+ bool isFinish = false; //評量是否已完成 ※有任一學生有作答則視為已完成
|
|
|
+ foreach (List<string> studentAnswer in studentAnswers)
|
|
|
+ {
|
|
|
+ if (studentAnswer.Count > 0) { isFinish = true; break; }
|
|
|
+ }
|
|
|
+ if (isFinish)
|
|
|
+ {
|
|
|
+ finishExamIdList.Add(examId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //結果判斷
|
|
|
+ JointEventGroupBase.JointEventGroupCourseGroup classInGroup = new JointEventGroupBase.JointEventGroupCourseGroup(); //取得該班級的報名/決賽資訊
|
|
|
+ foreach (JointEventGroupDb eventGroup in jointEventGroup)
|
|
|
+ {
|
|
|
+ foreach (JointEventGroupBase.JointEventGroupCourse eventCourse in eventGroup.courseLists)
|
|
|
+ {
|
|
|
+ foreach (JointEventGroupBase.JointEventGroupCourseGroup group in eventCourse.groupLists)
|
|
|
+ {
|
|
|
+ if (group.id.Equals(groupId))
|
|
|
+ {
|
|
|
+ classInGroup = group;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (jointEventGroup.Count.Equals(0) || string.IsNullOrWhiteSpace(classInGroup.id)) //資格不符
|
|
|
+ {
|
|
|
+ result = "disqualify";
|
|
|
+ }
|
|
|
+ else if (jointExamIdList.Count > 0 && jointExamIdList.Count.Equals(finishExamIdList.Count))
|
|
|
+ {
|
|
|
+ result = "complete";
|
|
|
+ }
|
|
|
+ else if (jointExamIdList.Count > 0 && finishExamIdList.Count > 0 && jointExamIdList.Count > finishExamIdList.Count)
|
|
|
+ {
|
|
|
+ result = "doing";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 計算決賽通過的老師課程名單用中間model
|
|
|
/// </summary>
|