using Azure.Cosmos; using Azure.Storage.Blobs.Models; using Azure.Storage.Sas; using DocumentFormat.OpenXml.Bibliography; using DocumentFormat.OpenXml.Drawing; using DocumentFormat.OpenXml.Drawing.Charts; using DocumentFormat.OpenXml.Math; using DocumentFormat.OpenXml.Spreadsheet; using DocumentFormat.OpenXml.Wordprocessing; using HTEXLib.COMM.Helpers; using OpenXmlPowerTools; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Net.NetworkInformation; using System.Text; using System.Text.Json; using System.Threading.Tasks; using TEAMModelOS.Models; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models; using TEAMModelOS.Services; using static TEAMModelOS.SDK.Models.Cosmos.Student.StudentAnalysis; using Activity = TEAMModelOS.SDK.Models.Activity; namespace TEAMModelOS.SDK { public static class ActivityService { public static async Task> ListExperts(AzureCosmosFactory _azureCosmos ,CoreAPIHttpService _coreAPIHttpService,DingDing _dingDing, Option _option, string _activityId) { List expertTasks = new List(); ActivityExpert activityExpert = null; Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync($"{_activityId}", new PartitionKey("ActivityExpert")); if (response.Status == 200) { bool change = false; activityExpert = JsonDocument.Parse(response.Content).RootElement.Deserialize(); var experts = activityExpert.experts.FindAll(z => string.IsNullOrWhiteSpace(z.id)); var tmdids = experts.Where(x => !string.IsNullOrWhiteSpace(x.tmdid)).Select(z => z.tmdid); var phones = experts.Where(x => !string.IsNullOrWhiteSpace(x.mobile)).Select(z => z.mobile); var emails = experts.Where(x => !string.IsNullOrWhiteSpace(x.email)).Select(z => z.email); List keys = new List(); if (tmdids.Any()) { keys.AddRange(tmdids); } if (phones.Any()) { keys.AddRange(phones); } if (emails.Any()) { keys.AddRange(emails); } List coreUsers = new List(); if (keys.Any()) { try { var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json"); string json = await _coreAPIHttpService.GetUserInfos(content); if (!string.IsNullOrWhiteSpace(json)) { coreUsers = json.ToObject>(); } } catch (Exception ex) { await _dingDing.SendBotMsg($"{_option.Location},导入名单时,查验key信息错误{ex.Message}\n{ex.StackTrace}\n\n{keys.ToJsonString()}", GroupNames.醍摩豆服務運維群組); } } if (coreUsers.IsNotEmpty()) { foreach (var t in experts) { if (!string.IsNullOrWhiteSpace(t.tmdid)) { CoreUser coreUser = coreUsers.Find(x => x.id.Equals(t.tmdid)); if (coreUser != null) { change=true; t.id = coreUser.id; t.name = coreUser.name; t.picture = coreUser.picture; t.tmdid = coreUser.id; if (!string.IsNullOrWhiteSpace(coreUser.mobile)) { t.mobile = coreUser.mobile; } if (!string.IsNullOrWhiteSpace(coreUser.mail)) { t.email = coreUser.mail; } } } if (string.IsNullOrWhiteSpace(t.id)) { if (!string.IsNullOrWhiteSpace(t.mobile)) { CoreUser coreUser = coreUsers.Find(x => !string.IsNullOrWhiteSpace(x.mobile) && x.mobile.Equals(t.mobile)); if (coreUser != null) { change=true; t.id = coreUser.id; t.name = coreUser.name; t.picture = coreUser.picture; t.tmdid = coreUser.id; if (!string.IsNullOrWhiteSpace(coreUser.mobile)) { t.mobile = coreUser.mobile; } if (!string.IsNullOrWhiteSpace(coreUser.mail)) { t.email = coreUser.mail; } } } } if (string.IsNullOrWhiteSpace(t.id)) { if (!string.IsNullOrWhiteSpace(t.email)) { CoreUser coreUser = coreUsers.Find(x => !string.IsNullOrWhiteSpace(x.mail) && x.mail.Equals(t.email)); if (coreUser != null) { change=true; t.id = coreUser.id; t.name = coreUser.name; t.picture = coreUser.picture; t.tmdid = coreUser.id; if (!string.IsNullOrWhiteSpace(coreUser.mobile)) { t.mobile = coreUser.mobile; } if (!string.IsNullOrWhiteSpace(coreUser.mail)) { t.email = coreUser.mail; } } } } } } if (change) { await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(activityExpert, new PartitionKey("ActivityExpert")); } Contest contest = null; Azure.Response contestResponse = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(_activityId, new PartitionKey("Contest")); if (contestResponse.Status==200) { contest = JsonDocument.Parse(contestResponse.Content).RootElement.ToObject(); } List expertDtos = activityExpert.experts.Select(z => z.ToJsonString().ToObject()).ToList(); long now = DateTimeOffset.Now.ToUnixTimeMilliseconds(); //进入评审环节 if (contest.review!= null && now > contest.review.stime) { if (expertDtos!=null && expertDtos.Count()>0) { var hasIds = expertDtos.Where(x => !string.IsNullOrWhiteSpace(x.id)); if (hasIds!=null && hasIds.Count()>0) { string taskSql = $"select value c from c where c.id in ({string.Join(",", hasIds.Select(z => $"'{z.id}'"))})"; var taskResults = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(taskSql, $"ActivityExpertTask-{_activityId}"); foreach (var item in taskResults.list) { var dto = expertDtos.Find(z => !string.IsNullOrWhiteSpace(z.id) && z.id.Equals(item.id)); if (dto!=null) { dto.taskCount =item.contestTasks.Count(); dto.teacherCount=item.contestTasks.SelectMany(z => z.members).Count(); dto.completeCount=item.contestTasks.Where(z => z.status==1).Count(); dto.uploads= item.contestTasks.Select(z => new ContestUploadData { name = z.name, id=z.uploadId, code=string.Join(",", z.uploadTypes), count=z.count, status= z.status, score=z.score, detailScore=z.detailScore }).ToList(); } } } } } expertTasks.AddRange(expertDtos); } return expertTasks; } public static async Task> ActivityScores (AzureCosmosFactory _azureCosmos,JsonElement _activityId,string teacherId= null) { List scoreLevels = new List(); Azure.Response responseContest = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(_activityId.GetString(), new PartitionKey("Contest")); if (responseContest.Status == 200) { long now = DateTimeOffset.Now.ToUnixTimeMilliseconds(); Contest contest = JsonDocument.Parse(responseContest.Content).RootElement.ToObject(); string sql = $"select value c from c "; if (!string.IsNullOrWhiteSpace(teacherId)) { sql=$"{sql} where c.id ='{teacherId}'"; } var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(sql, $"ActivityEnroll-{_activityId}"); //List teacherScoreLevels = new List(); List teacherScores = new List(); if (result.list.IsNotEmpty()) { if (contest.sign.type==1) { var teams = result.list.Where(x => !string.IsNullOrEmpty(x.contest?.cipher)).GroupBy(z => z.contest.cipher); foreach (var team in teams) { var members = team.ToList(); var leader = members.FindAll(z => z.contest.leader==1)?.FirstOrDefault(); if (leader==null) { leader=members.First(); } double score = leader.upload?.score??-1; if (leader.upload?.showScore==1) { score= leader.upload.maskScore; } teacherScores.Add(new ActivityTeacherScore { uploadId=leader.upload?.uploadId, uploadName=!string.IsNullOrWhiteSpace(leader.upload?.name) ? leader.upload?.name : $"{leader.contest.teamName}", score=score, tmdid=leader.id, nickname=leader.tmdName, name=leader.contest.enrollInfos.Find(z => z.code.Equals("name"))?.val, picture=leader.tmdPicture, school=leader.schoolId, schoolName=leader.schoolName, schoolPicture=leader.schoolPicture, cipher=leader.contest.cipher, teamName=leader.contest.teamName, type=leader.contest.type, members=members.Select(z => new IdNameCode { id=z.id, name=z.contest.enrollInfos.Find(x => x.code.Equals("name"))?.val, picture=z.tmdPicture, nickname=z.tmdName }).ToList(), }); } } else { ///个人组 foreach (var item in result.list) { double score = item.upload?.score??-1; if (item.upload?.showScore==1) { score= item.upload.maskScore; } teacherScores.Add(new ActivityTeacherScore { uploadId=item.upload?.uploadId, uploadName=!string.IsNullOrWhiteSpace(item.upload?.name) ? item.upload?.name : $"{item.contest.enrollInfos.Find(z => z.code.Equals("name"))?.val}", score=score, tmdid=item.id, nickname=item.tmdName, name=item.contest.enrollInfos.Find(z => z.code.Equals("name"))?.val, picture=item.tmdPicture, school=item.schoolId, schoolName=item.schoolName, schoolPicture=item.schoolPicture, type=item.contest.type, }); } } if(contest.modules.Contains("score") && contest.score!= null) { if (contest.score.showType==1) { teacherScores= teacherScores.Where(x => x.score>=0).OrderByDescending(x => x.score).ToList(); if (contest.score.levelType==1) { var levels = contest.score.scoreLevels.OrderBy(x => x.order).ToList(); foreach (var level in levels) { var datas = teacherScores.Take(level.top); var scores = datas.ToJsonString().ToObject>(); scores.ForEach(z => { z.scoreLevel=level.lable; }); scoreLevels.Add(new ActivityScoreLevel { lable=level.lable, scores=scores }); teacherScores.RemoveAll(x => scores.Select(v => v.uploadId).Contains(x.uploadId)); } } else { var levels = contest.score.scoreLevels.OrderByDescending(x => x.max); foreach (var level in levels) { scoreLevels.Add(new ActivityScoreLevel { lable=level.lable }); foreach (var item in teacherScores) { if (item.score==80) { Console.Write(1); } string label = string.Empty; if (level.max==100) { if (item.score>=level.min && item.score<=level.max) { label=level.lable; } } else { if (item.score>=level.min && item.score(); score.scoreLevel=label; score.score=item.score; var data = scoreLevels.Find(x => x.lable.Equals(label)); if (data!=null) { data.scores.Add(score); } else { scoreLevels.Add(new ActivityScoreLevel { lable=label, scores= new List() { score } }); } } } } } } else { if (contest.score.top>-1) { teacherScores= teacherScores.Where(x => x.score>=0).OrderByDescending(x => x.score).Take(contest.score.top).ToList(); } else { teacherScores= teacherScores.Where(x => x.score>=0).ToList(); } var scores = new List(); foreach (var item in teacherScores) { double score = item.score; var teacher = item.ToJsonString().ToObject(); teacher.scoreLevel=$"{score}"; teacher.score=score; scores.Add(teacher); } scoreLevels.Add(new ActivityScoreLevel { lable="", scores=scores }); } } } } return scoreLevels; } public static async Task<(List expertContestTasks, List activityEnrollsInvalid, List expertContestTasksDB)> AllocationTask(AzureCosmosFactory _azureCosmos, IEnumerable experts, Contest contest, HashSet periodSubjectKeys, string distribute, int taskCount) { //先获取已经分配完成的 List worksDB = new List(); IEnumerable complete = new List(); string taskSQL = $"select value c from c where c.pk='ActivityExpertTask'"; var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(taskSQL, $"ActivityExpertTask-{contest.id}"); if (result.list.IsNotEmpty()) { foreach (var item in result.list) { worksDB.AddRange(item.contestTasks.Select(z => new ExpertContestTaskDto { expertName=item.name , expertPicture=item.picture, expertTmdname=item.tmdname, expertId = item.id, available = 1, uploadId = z.uploadId, name = z.name, uploadTypes = z.uploadTypes, count = z.count, cipher=z.cipher, type=z.type, leader=z.leader, members=z.members, tmdid=z.tmdid, score=z.score, status=z.status, detailScore=z.detailScore, activityId=contest.id })); } //处理已经分配完成(taskCount)的作品 complete = worksDB.GroupBy(task => task.uploadId).Where(group => group.Count() >= taskCount).SelectMany(group => group); } string enrollSQL = "select value c from c where c.pk='ActivityEnroll'"; //已经满足分配的无需再去处理检查。 if (complete!=null && complete.Count()>0) { var uploadIds = complete.Select(z => z.uploadId).ToHashSet(); enrollSQL =$"{enrollSQL} where c.upload.uploadId not in ({string.Join(",", uploadIds.Select(z => $"'{z}'"))})"; } //检查报名,学段和科目是否匹配 var resultActivityEnroll = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(enrollSQL, $"ActivityEnroll-{contest.id}"); List expertContestTasks = new List(); foreach (ActivityEnroll enroll in resultActivityEnroll.list) { //如果是队长统一上传 if (contest.upload.captainUpload == 1 && !string.IsNullOrWhiteSpace(enroll.contest?.cipher)) { var team = resultActivityEnroll.list.FindAll(z => z.contest != null && z.contest.type == 1 && enroll.contest?.type == 1 && z.contest.cipher.Equals(enroll.contest.cipher)); //获取队长信息 var leaders = team.FindAll(z => z.contest.leader == 1); if (leaders.IsNotEmpty()) { leaders = new List() { enroll }; } List members = team.Select(z => new IdNameCode { id = z.id, code = z.schoolId, picture = z.tmdPicture, nickname = z.tmdName, name = z.contest?.enrollInfos?.Find(e => e.code.Equals("name")).val }).ToList(); //队长的报名信息 var leader = leaders?.First(); string name = leader?.contest?.teamName; var period = leader?.contest?.enrollInfos?.Find(z => z.code.Equals("period")); var subject = leader?.contest?.enrollInfos?.Find(z => z.code.Equals("subject")); string uploadId = string.Empty; if (string.IsNullOrEmpty(name)) { name = $"{leader?.contest?.enrollInfos?.Find(z => z.code.Equals("name"))?.val}({team.Count})"; } int count = 0; int available = -1; var checkResult = ActivityService.CheckPeriodSubject(distribute, period, subject, periodSubjectKeys); if (checkResult.available == 0) { if (leader?.upload != null && leader.upload.sokrates.IsNotEmpty()) { count += leader.upload.sokrates.Count; } if (leader?.upload != null && leader.upload.files.IsNotEmpty()) { count += leader.upload.files.Count; } if (leader?.upload != null && leader.upload.lessons.IsNotEmpty()) { count += leader.upload.lessons.Count; } if (leader?.upload!=null && leader.upload.complexes.IsNotEmpty()) { count+=leader.upload.complexes.Count(); } if (count <= 0) { uploadId = enroll.contest.cipher; available = 5; } else { uploadId = leader?.upload?.uploadId; available = checkResult.available; } } else { uploadId = enroll.contest.cipher; available = checkResult.available; } ExpertContestTaskDto expertContestTask = expertContestTasks.Find(z => !string.IsNullOrWhiteSpace(z.uploadId) && z.uploadId.Equals(leader.upload)); if (expertContestTask == null) { expertContestTasks.Add(new ExpertContestTaskDto { uploadId = leader.upload?.uploadId, name = $"{leader.schoolName}-{name}", // uploadTypes = new List { leader?.upload.type }, uploadTypes =leader.upload.uploadType, count = count, cipher = leader.contest?.cipher, type = 1, leader = 1, tmdid = leader.id, status = -1, score = -1, //detailScore=new List() members = members, periodSubjectKey = checkResult.periodSubjectKey, period = period?.val, subject = subject?.val, available = available, activityId=contest.id, }); } else { expertContestTask.available = available; expertContestTask.name = name; expertContestTask.count = count; expertContestTask.members = members; expertContestTask.periodSubjectKey = checkResult.periodSubjectKey; expertContestTask.activityId=contest?.id; } } else { if (enroll.upload!= null) { //如果不是队长统一上传 //学段 var period = enroll.contest?.enrollInfos?.Find(z => z.code.Equals("period")); //科目 var subject = enroll.contest?.enrollInfos?.Find(z => z.code.Equals("subject")); string periodSubjectKey = string.Empty; string name = enroll.contest?.enrollInfos?.Find(z => z.code.Equals("name"))?.val; string uploadId = string.Empty; if (!string.IsNullOrEmpty(name)) { name = $"({name})"; } else { name = string.Empty; } int count = 0; int available = -1; var checkResult = ActivityService.CheckPeriodSubject(distribute, period, subject, periodSubjectKeys); if (checkResult.available == 0) { if (enroll.upload != null && enroll.upload.sokrates.IsNotEmpty()) { count += enroll.upload.sokrates.Count; } if (enroll.upload != null && enroll.upload.files.IsNotEmpty()) { count += enroll.upload.files.Count; } if (enroll.upload != null && enroll.upload.lessons.IsNotEmpty()) { count += enroll.upload.lessons.Count; } if (enroll.upload != null && enroll.upload.complexes.IsNotEmpty()) { count+=enroll.upload.complexes.Count(); } if (count <= 0) { available = 5; uploadId = enroll.id; } else { available = checkResult.available; uploadId = enroll.upload.uploadId; } } else { uploadId = enroll.id; available = checkResult.available; } ExpertContestTaskDto expertContestTask = expertContestTasks.Find(z => !string.IsNullOrWhiteSpace(z.uploadId) && z.uploadId.Equals(enroll.upload)); if (expertContestTask == null) { expertContestTasks.Add(new ExpertContestTaskDto { uploadId = uploadId, name = $"{enroll.schoolName}-{name}", //uploadTypes = new List { enroll.upload?.type }, uploadTypes =enroll.upload.uploadType, count = count, cipher = enroll.contest?.cipher, type = 1, leader = 1, tmdid = enroll.id, status = -1, score = -1, periodSubjectKey = checkResult.periodSubjectKey, period = period?.val, subject = subject?.val, available = available, activityId = contest?.id, }); } else { expertContestTask.available = available; expertContestTask.name = name; expertContestTask.count = count; expertContestTask.periodSubjectKey = checkResult.periodSubjectKey; expertContestTask.activityId=contest?.id; } } } } List invalids = expertContestTasks.FindAll(z => z.available!=0); List works = expertContestTasks.FindAll(z => z.available==0); var data = AssignWorksToExperts(works, worksDB, experts, taskCount); if (invalids.IsNotEmpty()) { invalids.AddRange(data.assignmentsInvalid); } List okTask = new List(); okTask.AddRange(data.assignmentsAdd); okTask.AddRange(worksDB); var groups= okTask.GroupBy(z => z.uploadId).Select(x => new { key = x.Key, list = x.ToList() }); foreach (var item in groups) { if (item.list.Count()(); taskDto.expertName=null; taskDto.expertId=null; taskDto.expertPicture=null; taskDto.expertTmdname=null; //,8分配次数不足 taskDto.available=8; invalids.Add(taskDto); } } return (data.assignmentsAdd, invalids, worksDB); } public static (int available, string periodSubjectKey) CheckPeriodSubject(string distribute , EnrollInfo period, EnrollInfo subject, HashSet periodSubjectKeys) { int available = -1; string periodSubjectKey= string.Empty; if (distribute.Equals("period")) { if (period != null) { periodSubjectKey = $"{period.val}-"; } else { available = 2; } } else if (distribute.Equals("subject")) { if (subject != null) { periodSubjectKey = $"-{subject.val}"; } else { available = 3; } } else if (distribute.Equals("periodAndSubject")) { if (period != null && subject != null) { periodSubjectKey = $"{period.val}-{subject.val}"; } else { available = 4; } } else { periodSubjectKey = "-"; } if (!string.IsNullOrWhiteSpace(periodSubjectKey)) { if (periodSubjectKeys.Contains(periodSubjectKey)) { available = 0; } else { //学段学科不匹配 available = 6; } } return (available, periodSubjectKey); } /// /// 将作品按分配次数,分配给不同的专家 /// /// /// /// /// static (List assignmentsAdd, List assignmentsInvalid) AssignWorksToExperts(List works,List worksDB, IEnumerable experts, int N) { //增加的 var assignmentsAdd = new List(); //未分配到的 var assignmentsInvalid = new List(); var random = new Random(); //用于处理数据库和新分配的结果中检查已经分配过的作品和专家 var assignmentsAll = worksDB.ToJsonString().ToObject>(); foreach (var work in works) { for (int i = 0; i < N; i++) { //分配次数已经Ok,分配结果完善的,不需要再去处理 if (assignmentsAll.Count(z => z.uploadId.Equals(work.uploadId))>=N) { continue; } var availableExperts = experts .OrderBy(expert => assignmentsAll.Count(a => a.expertId == expert.expertId)) .Where(expert => expert.periodSubjects.Contains(work.periodSubjectKey) && !assignmentsAll.Any(a => a.uploadId == work.uploadId && a.expertId == expert.expertId)) .ToList(); if (availableExperts.Count > 0) { var selectedExpert = availableExperts[random.Next(availableExperts.Count)]; var newWork= work.DeepCopy(); newWork.expertId = selectedExpert.expertId; newWork.expertName = selectedExpert.expertName; newWork.expertPicture = selectedExpert.expertPicture; newWork.expertTmdname = selectedExpert.expertTmdname; newWork.available = 1; newWork.turn = i + 1; assignmentsAdd.Add(newWork); assignmentsAll.Add(newWork); } else { var newWork = work.DeepCopy(); newWork.expertId =null; newWork.available = 7; newWork.turn = i + 1; //作品在第几轮未匹配到 assignmentsInvalid.Add(newWork); //Console.WriteLine($"No available expert for WorkId {work.uploadId} and subject {work.periodSubjectKey} in attempt {i + 1}."); break; } } } return (assignmentsAdd, assignmentsInvalid); } /// /// 删除活动关联的数据 /// /// /// /// public static async Task DeleteActivityRelated(AzureCosmosFactory _azureCosmos,Activity activity) { //删除模块,Contest, Training ,Research, ReviewRule规则(ReviewRule-disposable"; 存为活动) await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).DeleteItemStreamAsync(activity.id, new PartitionKey("Contest")); await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).DeleteItemStreamAsync(activity.id, new PartitionKey("Training")); await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).DeleteItemStreamAsync(activity.id, new PartitionKey("Research")); await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).DeleteItemStreamAsync(activity.id, new PartitionKey("ReviewRule-disposable")); //删除邀请教师 ActivityTeacher, var resultTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher) .GetList("select c.id ,c.code from c where c.pk='ActivityEnroll' and c.", $"ActivityTeacher-{activity.id}"); if (resultTeacher.list.IsNotEmpty()) { await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).DeleteItemsStreamAsync(resultTeacher.list.Select(z => z.id).ToList(), $"ActivityTeacher-{activity.id}"); } //删除报名数据 ActivityEnroll var resultEnroll = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher) .GetList("select c.id ,c.code from c where c.pk='ActivityEnroll' and c.", $"ActivityEnroll-{activity.id}"); if (resultEnroll.list.IsNotEmpty()) { await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).DeleteItemsStreamAsync(resultEnroll.list.Select(z => z.id).ToList(), $"ActivityEnroll-{activity.id}"); } //删除专家数据 ActivityExpert await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).DeleteItemStreamAsync(activity.id, new PartitionKey("ActivityExpert")); } /// /// 生成组队口令 /// /// /// /// /// /// /// public static async Task GenCipher(CosmosClient client, DingDing _dingDing, TEAMModelOS.Models.Option _option, string _activityId) { string _num09 = "123456789"; string no = $"{Utils.CreatSaltString(7, _num09)}"; for (int i = 0; i < 10; i++) { List sheets = new List(); bool hasCurrFrom = false; string cipherSQL = $"select value c.id from c where c.contest!=null and c.activityId='{_activityId}' and c.contest.type=1 and c.contest.cipher='{no}' "; var cipherResult = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(cipherSQL, $"ActivityEnroll-{_activityId}"); if (cipherResult.list.IsNotEmpty() && cipherResult.list.Count>0) { hasCurrFrom = true; } if (hasCurrFrom) { if (i == 9) { string msg = $"{_option.Location},ActivityService/GenCipher\n 组队口令生成异常,重复生成次数超过10次"; await _dingDing.SendBotMsg($"OS,{_option.Location},{msg}", GroupNames.醍摩豆服務運維群組); throw new Exception(msg); } else { no = $"{Utils.CreatSaltString(7, _num09)}"; } } else { break; } } return no; } public static async Task> AreaActivityList(AzureCosmosFactory _azureCosmos, AzureStorageFactory _azureStorage, JsonElement request, string _areaId, int isCount = 0) { string yearSql = string.Empty; if (isCount==0) { yearSql = $" and c.year={DateTimeOffset.Now.Year}"; if (request.TryGetProperty("year", out JsonElement _year)) { yearSql = $" and c.year={_year}"; } } string sql = $"select value c from c where c.owner='{_areaId}' {yearSql} "; var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sql, "Activity"); result.list.ForEach(z => { var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(z.owner, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List); z.sas=blob_sas; z.url=blob_uri; }); return result.list.OrderByDescending(z => z.stime); } public static async Task> SchoolActivityList(AzureCosmosFactory _azureCosmos, AzureStorageFactory _azureStorage, JsonElement request, string school, int isCount = 0) { School schoolbase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(school, new PartitionKey("Base")); List activities = new List(); string yearSql = string.Empty; if (isCount==0) { yearSql = $" and c.year={DateTimeOffset.Now.Year}"; if (request.TryGetProperty("year", out JsonElement _year)) { yearSql = $" and c.year={_year}"; } } //获取开放的 { //完全开放 所有的学校 string sqlOpen = $"select value c from c where c.scope='public' {yearSql} and (c.publish=1 or c.publish=2 ) and( ARRAY_LENGTH(c.invitedSchools)=0 or IS_DEFINED(c.invitedSchools) = false ) "; var resultOpen = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlOpen, "Activity"); activities.AddRange(resultOpen.list); //部分学校 string sqlSchool = $"select value c from c join s in c.invitedSchools where c.scope='public' {yearSql} and (c.publish=1 or c.publish=2 ) and s.id='{school}' "; var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlSchool, "Activity"); resultSchool.list.ForEach(z => { var confirmedSchool = z.confirmedSchools.Find(z => z.id.Equals(school)); if (confirmedSchool==null) { z.confirmedSchools.Add(new ActivityConfirmedSchool { id=schoolbase.id, name=schoolbase.name, picture=schoolbase.picture, status=0 }); } }); activities.AddRange(resultSchool.list); } //获取区级下放的 { if (!string.IsNullOrWhiteSpace(schoolbase.areaId)) { //区级所有学校 string sqlOpen = $"select value c from c where c.scope='area'{yearSql} and (c.publish=1 or c.publish=2 ) and c.owner='{schoolbase.areaId}' and( ARRAY_LENGTH(c.invitedSchools)=0 or IS_DEFINED(c.invitedSchools) = false) "; var resultOpen = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlOpen, "Activity"); resultOpen.list.ForEach(z => { var confirmedSchool = z.confirmedSchools.Find(z => z.id.Equals(school)); if (confirmedSchool==null) { z.confirmedSchools.Add(new ActivityConfirmedSchool { id=schoolbase.id, name=schoolbase.name, picture=schoolbase.picture, status=0 }); } }); activities.AddRange(resultOpen.list); //区级部分学校 string sqlSchool = $"select value c from c join s in c.invitedSchools where c.scope='area'{yearSql} and (c.publish=1 or c.publish=2 ) and c.owner='{schoolbase.areaId}' and s.id='{school}' "; var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlSchool, "Activity"); resultSchool.list.ForEach(z => { var confirmedSchool = z.confirmedSchools.Find(z => z.id.Equals(school)); if (confirmedSchool==null) { z.confirmedSchools.Add(new ActivityConfirmedSchool { id=schoolbase.id, name=schoolbase.name, picture=schoolbase.picture, status=0 }); } }); activities.AddRange(resultSchool.list); } } //获取学校自己的 { string sqlSchool = $"select value c from c where c.scope='school'{yearSql} and c.owner='{school}' "; var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlSchool, "Activity"); activities.AddRange(resultSchool.list); } long now = DateTimeOffset.Now.ToUnixTimeMilliseconds(); activities.ForEach(z => { var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(z.owner, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List); z.sas=blob_sas; z.url = blob_uri; if (z.etime> TeacherActivityList(AzureCosmosFactory _azureCosmos,AzureStorageFactory _azureStorage, JsonElement request, string tmdid, int isCount = 0) { List activities = new List(); HashSet inviteActivityIds = new HashSet(); string yearSql = string.Empty; if (isCount==0) { yearSql = $" and c.year={DateTimeOffset.Now.Year}"; if (request.TryGetProperty("year", out JsonElement _year) && int.TryParse($"{_year}", out int year)) { yearSql = $" and c.year={year}"; } } //先获取邀请制的 string sqlInvite = $"select value c from c join t in c.inviteTeachers where t.id='{tmdid}' and c.pk='ActivityTeacher'"; var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(sqlInvite); inviteActivityIds= result.list.Where(x=>!string.IsNullOrWhiteSpace(x.activityId)).Select(z => z.activityId).ToHashSet(); if (inviteActivityIds.Count>0) { string sqlActivity = $"select value c from c where c.id in ({string.Join(",", inviteActivityIds.Select(z => $"'{z}'"))}) {yearSql} "; var resultActivity = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlActivity, "Activity"); if (resultActivity.list.IsNotEmpty()) { activities.AddRange(resultActivity.list); } } Teacher teacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync(tmdid, new PartitionKey("Base")); string schoolOwnerIn = string.Empty; string schoolIdIn = string.Empty; if (teacher.schools.IsNotEmpty()) { schoolIdIn = $"and i.id in ({string.Join(",", teacher.schools.Select(z => $"'{z.schoolId}'"))})"; schoolOwnerIn= $"and c.owner in ({string.Join(",", teacher.schools.Select(z => $"'{z.schoolId}'"))})"; } //获取开放的 { //完全开放 所有的学校 string sqlOpen = $"select value c from c where c.scope='public' and (c.publish=1 or c.publish=2 ) and( ARRAY_LENGTH(c.invitedSchools)=0 or IS_DEFINED(c.invitedSchools) = false ) {yearSql} "; var resultOpen = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlOpen, "Activity"); activities.AddRange(resultOpen.list); if (!string.IsNullOrWhiteSpace(schoolIdIn)) { //部分学校 string sqlSchool = $"select value c from c join i in c.confirmedSchools where c.scope='public' and c.joinMode='enroll' and (c.publish=1 or c.publish=2 ) and i.status=1 {yearSql} {schoolIdIn} "; var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlSchool, "Activity"); activities.AddRange(resultSchool.list); } } string areaOwnerIn = string.Empty; var hasAreaSchools = teacher.schools.FindAll(z => !string.IsNullOrWhiteSpace(z.areaId)); if (hasAreaSchools.IsNotEmpty()) { areaOwnerIn = $"and c.owner in ({string.Join(",", hasAreaSchools.Select(z => $"'{z.areaId}'"))})"; schoolIdIn = $"and i.id in ({string.Join(",", hasAreaSchools.Select(z => $"'{z.schoolId}'"))})"; } //获取所有区级的 if (!string.IsNullOrWhiteSpace(areaOwnerIn) && !string.IsNullOrEmpty(schoolIdIn)) { string sqlOpen = $"select value c from c join i in c.confirmedSchools where c.scope='area' and c.joinMode='enroll' and (c.publish=1 or c.publish=2 ) and i.status=1 {yearSql} {areaOwnerIn} {schoolIdIn} "; var resultOpen = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlOpen, "Activity"); activities.AddRange(resultOpen.list); } //获取所有学校的 if (!string.IsNullOrWhiteSpace(schoolOwnerIn)) { string sqlSchool = $"select value c from c where c.scope='school' and c.joinMode='enroll' and (c.publish=1 or c.publish=2 ) {yearSql} {schoolOwnerIn} "; var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList(sqlSchool, "Activity"); activities.AddRange(resultSchool.list); } long now=DateTimeOffset.Now.ToUnixTimeMilliseconds(); activities.ForEach(z => { var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(z.owner, BlobContainerSasPermissions.Read); z.sas=blob_sas; z.url=blob_uri; if (z.etime $"'{z.id}'"))})"; var resultEnroll = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList(sql); foreach (var enroll in resultEnroll.list) { var activityDto = activities.Find(z => z.id.Equals(enroll.activityId)); if (activityDto!=null) { if (enroll.contest!=null && enroll.contest.enrollTime>0) { activityDto.contestSign=1; activityDto.signTime=enroll.contest.enrollTime; activityDto.contestType=enroll.contest.type; } //if (enroll.upload!=null && (enroll.upload.files.IsNotEmpty() || enroll.upload.sokrates.IsNotEmpty() || enroll.upload.lessons.IsNotEmpty()) ) //{ // activityDto.contestUpload=1; // activityDto.uploadTime=enroll.upload.uploadTime; // activityDto.uploadType=enroll.upload.type; //} if (enroll.upload!=null &&enroll.upload.complexes.IsNotEmpty()) { activityDto.contestUpload=1; activityDto.uploadTime=enroll.upload.uploadTime; activityDto.uploadTypes=enroll.upload.uploadType; } } } } return activities; } public static async Task<(ReviewRule reviewRule, int invalidCode, string msg)> UpsertReviewRule(ReviewRuleTree reviewRuleTree,Activity activity, Contest contest, AzureCosmosFactory _azureCosmos) { var nodes = new List(); nodes= TreeToList(reviewRuleTree.trees, nodes); ReviewRule reviewRule = new ReviewRule() { id= activity.id, code="ReviewRule-disposable", pk="ReviewRule", name=reviewRuleTree.name, desc=reviewRuleTree.desc, owner=activity.owner, type="disposable", configs=nodes, sourceName=activity.name, taskCount=reviewRuleTree.taskCount, scoreRule=reviewRuleTree.scoreRule, distribute=reviewRuleTree.distribute, scoreDetail=reviewRuleTree.scoreDetail, }; //代码顺序不能动 var checkReult = CheckReviewRule(reviewRule, contest); if (checkReult.invalidCode==200) { await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).UpsertItemAsync(reviewRule, new Azure.Cosmos.PartitionKey(reviewRule.code)); if (reviewRuleTree.upsertAsTemplate==1) { reviewRule.code="ReviewRule-template"; reviewRule.type="template"; reviewRule.taskCount = reviewRuleTree.taskCount; reviewRule.scoreRule = reviewRuleTree.scoreRule; reviewRule.distribute = reviewRuleTree.distribute; reviewRule.scoreDetail = reviewRuleTree.scoreDetail; await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).UpsertItemAsync(reviewRule, new Azure.Cosmos.PartitionKey(reviewRule.code)); } } return (reviewRule,checkReult.invalidCode,checkReult.msg); } public static (int invalidCode, string msg) CheckReviewRule(ReviewRule reviewRule,Contest contest) { int invalidCode = -1; string msg = ""; if (reviewRule.taskCount<=0) { invalidCode=28; msg="作品分配次数至少一次!"; } if (reviewRule.taskCount==1 ) { if (reviewRule.scoreRule.Equals("only")) { invalidCode=200; } else { invalidCode=21;//分配次数一次,必须匹配only msg="分配次数1次,必须匹配【默认统分】规则"; } } if (reviewRule.taskCount>=2 ) { if ((reviewRule.scoreRule.Equals("avg")||reviewRule.scoreRule.Equals("top"))) { invalidCode=200; } else { invalidCode=22;//分配次数2次,必须匹配avg,top msg="分配次数2次,必须匹配【按平均分】,【按最高分】"; } } if (reviewRule.taskCount>=3 ) {if ((reviewRule.scoreRule.Equals("avg")||reviewRule.scoreRule.Equals("top")||reviewRule.scoreRule.Equals("rmLowAvg")||reviewRule.scoreRule.Equals("rmTopAvg"))) { invalidCode=200; } else { invalidCode=23;//分配次数2次,必须匹配avg,top,rmLowAvg,rmTopAvg msg="分配次数3次,必须匹配必须匹配【按平均分】,【按最高分】,【去掉最低分的平均分】,【去掉最高分的平均分】"; } } if (reviewRule.taskCount>=4 ) { if ((reviewRule.scoreRule.Equals("avg")||reviewRule.scoreRule.Equals("top")||reviewRule.scoreRule.Equals("rmLowAvg")||reviewRule.scoreRule.Equals("rmTopAvg")||reviewRule.scoreRule.Equals("rmLowTopAvg"))) { invalidCode=200; } else { invalidCode=24;//分配次数2次,必须匹配avg,top,rmLowAvg,rmTopAvg,rmLowTopAvg msg="分配次数4次,必须匹配必须匹配【按平均分】,【按最高分】,【去掉最低分的平均分】,【去掉最高分的平均分】,【去掉最高分和最低分的平均分】"; } } if (invalidCode==200) { if (!string.IsNullOrWhiteSpace(reviewRule.distribute)) { if (reviewRule.distribute.Equals("period")) { var period = contest.sign?.fields?.Find(z => z.field.Equals("period")); if (period!= null) { invalidCode = 200; } else { invalidCode=25; msg="作品分配匹配规则为【学段】,但报名填写表单未配置。"; } } else if (reviewRule.distribute.Equals("subject")) { var subject = contest.sign?.fields?.Find(z => z.field.Equals("subject")); if (subject!= null) { invalidCode = 200; } else { invalidCode=26; msg="作品分配匹配规则为【学科】,但报名填写表单未配置。"; } } else if (reviewRule.distribute.Equals("periodAndSubject")) { var period = contest.sign?.fields?.Find(z => z.field.Equals("period")); var subject = contest.sign?.fields?.Find(z => z.field.Equals("subject")); if (subject!= null && period!= null) { invalidCode = 200; } else { invalidCode=27; msg="作品分配匹配规则为【学段,学科】,但报名填写表单未配置。"; } } else if (reviewRule.distribute.Equals("none")) { invalidCode=200; } else { invalidCode=30; msg=$"作品分配匹配规则未识别【{reviewRule.distribute}】。"; } } else { invalidCode=29; msg="作品分配匹配规则不能为空。"; } } return (invalidCode,msg); } public static List TreeToList(List trees, List nodes) { trees = trees.OrderBy(x => x.order).ToList(); List list = new List(); trees.ForEach(x => { List cids = new List(); if (x.children.IsNotEmpty()) { x.children.ForEach(y => cids.Add(y.id)); } var node = new RuleConfig { id = x.id, pid = x.pid, cids= cids, label = x.label, desc = x.desc, score = x.score, order = x.order, }; list.Add(node); }); nodes.AddRange(list); foreach (RuleConfigTree tree in trees) { if (null != tree.children && tree.children.Count > 0) { TreeToList(tree.children, nodes); } } return nodes; } public static List ListToTree(List noes) { List list = noes.ToJsonString().ToObject>(); var res = from r in list group r by r.id into g select g; Dictionary blockDict = new Dictionary(); foreach (var s in res) { blockDict.TryAdd(s.First().id, s.First()); } return GetChild(list, blockDict); } private static List GetChild(List list, Dictionary dict) { List trees = new List(); trees = trees.OrderBy(x => x.order).ToList(); foreach (RuleConfigTree node in list) { bool flag = dict.TryGetValue(node.pid, out RuleConfigTree syllabus); if (flag && syllabus != null) { syllabus.children.Add(node); } else { trees.Add(node); } } return trees; } } }