using Azure.Cosmos; using Azure.Storage.Blobs.Models; using Azure.Storage.Sas; using HTEXLib.COMM.Helpers; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models; using TEAMModelOS.Services; using Activity = TEAMModelOS.SDK.Models.Activity; namespace TEAMModelOS.SDK { public static class ActivityService { /// /// 删除活动关联的数据 /// /// /// /// 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> TeacherActivityList(AzureCosmosFactory _azureCosmos,AzureStorageFactory _azureStorage, JsonElement request, string tmdid) { List activities = new List(); HashSet inviteActivityIds = new HashSet(); string 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.Common).GetList(sqlInvite); inviteActivityIds= result.list.Select(z => z.id).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(sqlInvite, "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); } activities.ForEach(z => { var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(z.owner, BlobContainerSasPermissions.Read); z.sas=blob_sas; }); if (activities.IsNotEmpty()) { string sql = $"select value c from c where c.pk='ActivityEnroll' and contains(c.code,'ActivityEnroll-') and c.id='{tmdid}' and c.activityId in ({string.Join(",", activities.Select(z => $"'{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 && !string.IsNullOrWhiteSpace(enroll.contest.cipher)) { 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())) { activityDto.contestUpload=1; activityDto.uploadTime=enroll.upload.uploadTime; activityDto.uploadType=enroll.upload.type; } } } } 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"; 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 && reviewRule.scoreRule.Equals("only")) { invalidCode=200; } else { invalidCode=21;//分配次数一次,必须匹配only msg="分配次数1次,必须匹配【默认统分】规则"; } if (reviewRule.taskCount>=2 && (reviewRule.scoreRule.Equals("avg")||reviewRule.scoreRule.Equals("top"))) { invalidCode=200; } else { invalidCode=22;//分配次数2次,必须匹配avg,top msg="分配次数2次,必须匹配【按平均分】,【按最高分】"; } if (reviewRule.taskCount>=3 && (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 && (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 { 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; } } }