123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- using Azure.Storage.Blobs.Models;
- using IES.ExamServer.Models;
- using Microsoft.Azure.Cosmos;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.Http;
- using System.Reflection.Metadata.Ecma335;
- using System.Text;
- using System.Text.Json;
- using System.Text.Json.Nodes;
- using System.Threading.Tasks;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.Extension;
- using TEAMModelOS.SDK.Models.Cosmos;
- using TEAMModelOS.SDK.Models.Cosmos.Normal;
- using TEAMModelOS.SDK.Models.Cosmos.Student;
- using TEAMModelOS.SDK.Models.Dtos;
- namespace TEAMModelOS.SDK.Models.Service
- {
- public sealed class EvaluationSyncInfoService
- {
- /// <summary>
- /// 重新对名单的hash值计算,因为可能会存在临时将学生加入名单,而没有修改评测信息的情况。
- /// </summary>
- /// <param name="evaluationSyncInfo"></param>
- /// <param name="_coreAPIHttpService"></param>
- /// <param name="_azureCosmos"></param>
- /// <param name="_dingDing"></param>
- /// <returns></returns>
- public static async Task<(EvaluationSyncInfo evaluation, bool change,string newGrouplistHash, List<RMember> members, List<RGroupList> groupLists)> CheckEvaluationGroupList(EvaluationSyncInfo evaluationSyncInfo, CoreAPIHttpService _coreAPIHttpService, AzureCosmosFactory _azureCosmos, DingDing _dingDing)
- {
- var listInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, _azureCosmos.GetCosmosClient(), _dingDing, evaluationSyncInfo.grouplist, evaluationSyncInfo.owner);
- //计算数据的hash值
- StringBuilder groupListData = new StringBuilder();
- //名单的hash值
- var orderList = listInfo.groups.OrderBy(x => x.id);
- foreach (var item in orderList)
- {
- groupListData.Append($"{item.id}-{item.name}");
- var orderMembers = item.members.OrderBy(x => x.id);
- foreach (var member in orderMembers)
- {
- groupListData.Append($"{member.id}-{member.name}");
- }
- }
- bool change = false;
- string grouplistHash = ShaHashHelper.GetSHA1(groupListData.ToString());
- if (!evaluationSyncInfo.grouplistHash .Equals(grouplistHash))
- {
- evaluationSyncInfo.grouplistHash = grouplistHash;
- change = true;
- }
- return (evaluationSyncInfo,change, grouplistHash,listInfo.rmembers, listInfo.groups);
- }
- /// <summary>
- /// 活动数据打包
- /// </summary>
- /// <param name="id"></param>
- /// <param name="scope"></param>
- /// <param name="owner"></param>
- /// <param name="type"></param>
- /// <param name="azureCosmos"></param>
- /// <param name="azureStorage"></param>
- public static async Task<EvaluationSyncInfo> PackageEvaluation( string id,string scope, string ownerId, string type, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage,
- CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing, IHttpClientFactory _httpClientFactory)
- {
- EvaluationSource evaluationSource = new EvaluationSource() { type=type,id=id};
- EvaluationSyncInfo evaluationSyncInfo= null;
- EvaluationClient evaluationClient = null;
- List<EvaluationExam> evaluationExams = new List<EvaluationExam>();
-
- long? dataTime = 0;
- long stime = 0;
- long etime = 0;
-
- string? ownerName=string.Empty;
- string? ownerPicture = string.Empty;
- string schoolCode = null;
- if (scope.Equals("school"))
- {
- try {
- School school = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(ownerId, new PartitionKey("Base"));
- schoolCode= ownerId;
- evaluationSource.school = school;
- ownerName = school.name;
- ownerPicture = school.picture;
- if (!string.IsNullOrWhiteSpace(ownerPicture))
- {
- //学校logo 下载到本地、
- HttpResponseMessage message = await _httpClientFactory.CreateClient().GetAsync(ownerPicture);
- if (message.IsSuccessStatusCode)
- {
- string base64Prefix = "data:image/jpeg;base64,";
- byte[] fileBytes = await message.Content.ReadAsByteArrayAsync();
- ownerPicture =$"{base64Prefix}{Convert.ToBase64String(fileBytes)}";
- }
- }
- }
- catch (Exception ex) {
- await _dingDing.SendBotMsg($"打包评测数据,获取学校信息报错,{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
- return null;
- }
- }
- else
- {
- try {
- Teacher teacher = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>(ownerId, new PartitionKey("Base"));
- evaluationSource.teacher = teacher;
- ownerName = teacher.name;
- ownerPicture = teacher.picture;
- if (!string.IsNullOrWhiteSpace(ownerPicture))
- {
- //学校logo 下载到本地、
- HttpResponseMessage message = await _httpClientFactory.CreateClient().GetAsync(ownerPicture);
- if (message.IsSuccessStatusCode)
- {
- string base64Prefix = "data:image/jpeg;base64,";
- byte[] fileBytes = await message.Content.ReadAsByteArrayAsync();
- ownerPicture =$"{base64Prefix}{Convert.ToBase64String(fileBytes)}";
- }
- }
- }
- catch (Exception ex) {
- await _dingDing.SendBotMsg($"打包评测数据,获取教师信息报错,{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
- return null;
- }
- }
- var responseEvaluationSyncInfo = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemStreamAsync(id, new PartitionKey("EvaluationSyncInfo"));
- if (responseEvaluationSyncInfo.IsSuccessStatusCode)
- {
- evaluationSyncInfo= JsonDocument.Parse(responseEvaluationSyncInfo.Content).RootElement.Deserialize<EvaluationSyncInfo>();
- }
- else {
- evaluationSyncInfo=new EvaluationSyncInfo {
- id = id,
- scope = scope,
- type = type,
- pk="EvaluationSyncInfo",
- code="ActivitySyncInfo",
- ownerId = ownerId,
- ownerPicture = ownerPicture,
- ownerName = ownerName,
- };
- }
-
- switch (true)
- {
- case bool when (type == "Exam"):
- {
- string code = $"Exam-{ownerId}";
- var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
- if (response.IsSuccessStatusCode)
- {
- ExamInfo exam= JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamInfo>();
- dataTime= exam._ts*1000;
- evaluationSyncInfo.name=exam.name;
- evaluationSyncInfo.subjects = exam.subjects?.Select(x=>new IES.ExamServer.Models.SubjectExam { subjectId=x.id,subjectName=x.name,examId=id}).ToList();
- evaluationSyncInfo.dataTime= DateTimeOffset.Now.ToUnixTimeMilliseconds();
- evaluationSyncInfo.scode=exam.code;
- stime=exam.startTime;
- etime=exam.endTime;
- HashSet<string> grouplist = new HashSet<string>();
- if (exam.classes.IsNotEmpty()) {
- exam.classes.ForEach(x => { grouplist.Add(x); });
- }
- if (exam.stuLists.IsNotEmpty())
- {
- exam.stuLists.ForEach(x => { grouplist.Add(x); });
- }
- evaluationSyncInfo.grouplist=grouplist.ToList() ;
- evaluationSyncInfo.paperCount=exam.papers.IsNotEmpty()? exam.papers.Count():0;
-
- foreach (var group in exam.papers.GroupBy(x=>x.subjectId).Select(x=>new { key = x.Key,list= x.ToList()}))
- {
- var subject= exam.subjects.Find(x => x.id.Equals(group.key));
- if (subject!=null)
- {
- evaluationSyncInfo.subjects.Add(new IES.ExamServer.Models.SubjectExam {
- subjectId=subject.id,
- subjectName=subject.name,
- examId=id,
- papers= group.list.Select(x=>new SubjectExamPaper {paperId= x.id,paperName=x.name,blob=x.blob }).ToList(),
- } );
- EvaluationExam evaluationExam = new EvaluationExam()
- {
- examId=exam.id,
- evaluationId=evaluationSyncInfo.id,
- examName=evaluationSyncInfo.name,
- subjectId=subject.id,
- subjectName=subject.name,
- classes= evaluationSyncInfo.grouplist,
- owner=exam.owner,
- scope=scope,
- stime=stime,
- etime=etime,
- papers= group.list.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, point=x.point,knowledge=x.knowledge,type=x.type,field=x.field }).ToList(),
- };
- evaluationExams.Add(evaluationExam);
- }
- }
- evaluationSource.exam=exam;
- }
- break;
- }
- case bool when (type == "Art"):
- {
- string code = $"Art-{ownerId}";
- var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
- if (response.IsSuccessStatusCode)
- {
- ArtEvaluation art = JsonDocument.Parse(response.Content).RootElement.Deserialize<ArtEvaluation>();
-
- // evaluationSyncInfo.subjects = art.subjects?.Select(x => new IES.ExamServer.Models.SubjectExam { id=x.id, name=x.name, examId=id }).ToList();
- evaluationSyncInfo.name = art.name;
- evaluationSyncInfo.pid= art.pId;
- evaluationSyncInfo.scode=art.code;
- evaluationSyncInfo.dataTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
- HashSet<string> grouplist = new HashSet<string>();
- if (art.classes.IsNotEmpty())
- {
- art.classes.ForEach(x => { grouplist.Add(x); });
- }
- if (art.stuLists.IsNotEmpty())
- {
- art.stuLists.ForEach(x => { grouplist.Add(x); });
- }
- if (art.tchLists.IsNotEmpty())
- {
- art.tchLists.ForEach(x => { grouplist.Add(x); });
- }
- evaluationSyncInfo.grouplist=grouplist.ToList();
- evaluationSource.art=art;
- dataTime= art._ts*1000;
- stime=art.startTime;
- etime=art.endTime;
- var quota_22 = art.settings.Find(x => x.id.Equals("quota_21"));
- foreach (var item in quota_22.task)
- {
- if (!string.IsNullOrWhiteSpace(item.acId))
- {
- var subject = art.subjects.Find(x => x.id.Equals(item.subject));
- var examResponse= await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(item.acId, new PartitionKey($"Exam-{ownerId}"));
- if (examResponse.IsSuccessStatusCode)
- {
- ExamInfo exam = JsonDocument.Parse(examResponse.Content).RootElement.Deserialize<ExamInfo>() ;
- var papers = exam.papers.FindAll(x => x.subjectId.Equals(item.subject));
- evaluationSyncInfo.subjects.Add(new IES.ExamServer.Models.SubjectExam
- {
- subjectId=item.subject,
- subjectName=subject.name,
- examId=item.acId,
- papers=papers?.Select(x => new SubjectExamPaper { paperId=x.id,paperName=x.name, blob=x.blob }).ToList(),
- });
- dataTime= dataTime<exam._ts*1000 ? exam._ts*1000 : dataTime;
- evaluationSource.artExams.Add(exam);
- EvaluationExam evaluationExam = new EvaluationExam()
- {
- examId=exam.id,
- evaluationId=evaluationSyncInfo.id,
- examName=evaluationSyncInfo.name,
- subjectId=subject.id,
- subjectName=subject.name,
- classes= evaluationSyncInfo.grouplist,
- owner=exam.owner,
- scope=scope,
- stime=stime,
- etime=etime,
- papers= papers.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, point=x.point, knowledge=x.knowledge, type=x.type, field=x.field }).ToList(),
- };
- evaluationExams.Add(evaluationExam);
- }
- }
- }
- }
- }
- break;
- default:
- break;
- }
- if (evaluationSyncInfo.subjects.IsNotEmpty() && evaluationSyncInfo.grouplist.IsNotEmpty())
- {
- long blobTime =-1;
- long blobSize = 0;
- long blobCount = 0;
-
- if (!string.IsNullOrWhiteSpace(evaluationSyncInfo.shortCode))
- {
- evaluationSyncInfo.shortCode = $"{MurmurHash3.Hash32(evaluationSyncInfo.id)}";
- }
- var listInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, azureCosmos.GetCosmosClient(), _dingDing, evaluationSyncInfo.grouplist, schoolCode);
- evaluationSyncInfo.studentCount = listInfo.rmembers.Count();
- evaluationSyncInfo.paperCount =evaluationSyncInfo.subjects.Select(x => x.papers).Count();
- var client = azureStorage.GetBlobContainerClient(ownerId);
- foreach (var subject in evaluationSyncInfo.subjects)
- {
- var evaluationExam = evaluationExams.FindAll(x => x.subjectId.Equals(subject.subjectId)).FirstOrDefault();
- foreach (var paper in subject.papers)
- {
- List<BlobHashInfo> blobs = new List<BlobHashInfo>();
- try
- {
- await foreach (BlobItem blobItem in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, paper.blob))
- {
- var lastModified = blobItem.Properties.LastModified;
- if (lastModified.HasValue)
- {
- lastModified.Value.ToUnixTimeMilliseconds();
- }
- var hash = blobItem.Properties.ContentHash;
- var path = blobItem.Name;
- var size = blobItem.Properties.ContentLength;
- blobs.Add(new BlobHashInfo
- {
- hash = Md5Hash.GetbyteToString(hash),
- last = lastModified.HasValue ? lastModified.Value.ToUnixTimeMilliseconds() : 0,
- path = path,
- size = size.HasValue ? size.Value : 0
- });
- };
- var evaluationPaper= evaluationExam.papers.Find(x => x.paperId.Equals(paper.paperId));
- evaluationPaper.blobs=blobs;
- }
- catch
- {
- }
- long lastTime = blobs.Max(x => x.last);
- blobTime= lastTime>blobTime?lastTime:blobTime;
- if (blobs.IsNotEmpty())
- {
- blobSize+=blobs.Sum(x => x.size);
- blobCount+=blobs.Count;
- var order = blobs.OrderBy(x => $"{x.path}-{x.hash}-{x.size}-{x.last}");
- string blobStr = string.Join(",", order.Select(x=> $"{x.path}-{x.hash}-{x.size}-{x.last}"));
- // 计算hash,校准路径,文件hash,文件大小,最后修改时间
- paper.paperHash= ShaHashHelper.GetSHA1(blobStr);
- }
-
- }
- }
- evaluationSyncInfo.blobTime = blobTime> evaluationSyncInfo.blobTime ? blobTime : evaluationSyncInfo.blobTime;
- evaluationSyncInfo.blobSize = blobSize;
- evaluationSyncInfo.blobCount = blobCount;
- evaluationSyncInfo.blobLastHash = evaluationSyncInfo.blobHash;
- evaluationSyncInfo.blobHash = ShaHashHelper.GetSHA1(string.Join("-", evaluationSyncInfo.subjects.SelectMany(x => x.papers).Select(x => x.paperHash)));
- evaluationSyncInfo.dataTime = dataTime.Value;
- evaluationSource.updateTime = dataTime.Value;
- var groupList = new { members = listInfo.rmembers, groupList = listInfo.groups };
- {
- //计算数据的hash值
-
- StringBuilder groupListData = new StringBuilder();
- //名单的hash值
- var orderList = listInfo.groups.OrderBy(x => x.id);
- foreach (var item in orderList)
- {
- groupListData.Append($"{item.id}-{item.name}");
- var orderMembers = item.members.OrderBy(x => x.id);
- foreach (var member in orderMembers)
- {
- groupListData.Append($"{member.id}-{member.name}");
- }
- }
- evaluationSyncInfo.grouplistHash= ShaHashHelper.GetSHA1(groupListData.ToString());
- var order= evaluationSyncInfo.subjects.OrderBy(x => x.subjectId);
- StringBuilder dataStr = new StringBuilder();
- dataStr.Append(evaluationSyncInfo.id);
- dataStr.Append(evaluationSyncInfo.name);
- dataStr.Append(evaluationSyncInfo.type);
- dataStr.Append(evaluationSyncInfo.owner);
- dataStr.Append(evaluationSyncInfo.ownerId);
- dataStr.Append(evaluationSyncInfo.scode);
- dataStr.Append(evaluationSyncInfo.scope);
- dataStr.Append(evaluationSyncInfo.grouplistHash);
- dataStr.Append(evaluationSyncInfo.blobHash);
- dataStr.Append(evaluationSyncInfo.shortCode);
- dataStr.Append($"{stime}{etime}");
- dataStr.Append(string.Join("", order.Select(x=>x.subjectId)));
- //计算dataHash
- evaluationSyncInfo.dataHash = ShaHashHelper.GetSHA1(dataStr.ToString());
- }
- evaluationClient= new EvaluationClient
- {
- id = evaluationSyncInfo.id,
- pid = evaluationSyncInfo.pid,
- name = evaluationSyncInfo.name,
- type = evaluationSyncInfo.type,
- owner = evaluationSyncInfo.owner,
- scode = evaluationSyncInfo.scode,
- scope = evaluationSyncInfo.scope,
- subjects = evaluationSyncInfo.subjects,
- dataTime = evaluationSyncInfo.dataTime,
- dataSize = evaluationSyncInfo.dataSize,
- blobTime = evaluationSyncInfo.blobTime,
- blobSize = evaluationSyncInfo.blobSize,
- blobCount = evaluationSyncInfo.blobCount,
- blobHash = evaluationSyncInfo.blobHash,
- blobLastHash = evaluationSyncInfo.blobLastHash,
- webviewCount = evaluationSyncInfo.webviewCount,
- webviewPath = evaluationSyncInfo.webviewPath,
- webviewSize = evaluationSyncInfo.webviewSize,
- webviewTime = evaluationSyncInfo.webviewTime,
- studentCount = evaluationSyncInfo.studentCount,
- paperCount = evaluationSyncInfo.paperCount,
- grouplist = evaluationSyncInfo.grouplist,
- shortCode = evaluationSyncInfo.shortCode,
- stime=stime,
- etime=etime,
- dataHash = evaluationSyncInfo.dataHash,
- grouplistHash = evaluationSyncInfo.grouplistHash,
- ownerId = evaluationSyncInfo.ownerId,
- ownerPicture =evaluationSyncInfo.ownerPicture,
- ownerName = evaluationSyncInfo.ownerName,
- //password = evaluationSyncInfo.password,
- //recordUrl = evaluationSyncInfo.recordUrl
- };
- long dataSize = 0;
- string sourceJson = evaluationSource.ToJsonString();
- dataSize+= Encoding.UTF8.GetByteCount(sourceJson);
- string groupListJson = groupList.ToJsonString();
- dataSize+= Encoding.UTF8.GetByteCount(groupListJson);
- string evaluationJson = new { evaluationClient, evaluationExams }.ToJsonString().ToJsonString();
- dataSize+= Encoding.UTF8.GetByteCount(evaluationJson);
- string evaluationSyncInfoSJson = evaluationSyncInfo.ToJsonString();
- dataSize+= Encoding.UTF8.GetByteCount(evaluationSyncInfoSJson);
- evaluationClient.dataSize = dataSize;
- await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(sourceJson, $"exam/{id}/package", "source.json");
- await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(groupListJson, $"exam/{id}/package", "grouplist.json");
- await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(new { evaluationClient, evaluationExams }.ToJsonString(), $"exam/{id}/package", "evaluation.json");
- evaluationSyncInfo.dataSize = dataSize;
-
- await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).UpsertItemAsync<EvaluationSyncInfo>(evaluationSyncInfo, new PartitionKey("EvaluationSyncInfo"));
- // await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(evaluationSyncInfo.ToJsonString(), $"package/{id}", "syncinfo.json");
- }
- return evaluationSyncInfo;
- }
- }
- }
|