using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using TEAMModelOS.Models; using TEAMModelOS.SDK; using TEAMModelOS.SDK.Helper.Common.CollectionHelper; using TEAMModelOS.SDK.DI; using System.Text.Json; using TEAMModelOS.SDK.Helper.Common.StringHelper; using TEAMModelOS.Models.CommonInfo; using Microsoft.AspNetCore.Http; using TEAMModelOS.SDK.Extension; using Azure.Cosmos; using Microsoft.AspNetCore.Authentication; using System.Text; using TEAMModelOS.SDK.DI.AzureCosmos.Inner; namespace TEAMModelOS.Controllers { [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] //[Authorize(Roles = "IES5")] [Route("common/item")] //[Route("api/[controller]")] [ApiController] public class ItemInfoController : ControllerBase { private readonly SnowflakeId _snowflakeId; private readonly AzureCosmosFactory _azureCosmos; public ItemInfoController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId) { _azureCosmos = azureCosmos; _snowflakeId = snowflakeId; } /// /// 批量保存题目 /// /// /// [ProducesDefaultResponseType] [HttpPost("upsert-all")] public async Task UpsertAll(List request) { // ResponseBuilder builder = ResponseBuilder.custom(); request.ForEach(x => { if (string.IsNullOrEmpty(x.id)) { x.id = _snowflakeId.NextId()+""; x.code = typeof(ItemInfo).Name + "-" + x.code; }; x.createTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); }); return Ok(await _azureCosmos.SaveOrUpdateAll(request)); } [ProducesDefaultResponseType] [HttpPost("upsert")] public async Task Upsert(JsonElement request) { ResponseBuilder builder = ResponseBuilder.custom(); /* if (string.IsNullOrEmpty(request.id)) { request.id = _snowflakeId.NextId() + ""; request.code = typeof(ItemInfo).Name + "-" + request.code; }; request.createTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); return Ok(await _azureCosmos.SaveOrUpdate(request));*/ var client = _azureCosmos.GetCosmosClient(); if (!request.TryGetProperty("itemInfo", out JsonElement item)) return BadRequest(); if (!request.TryGetProperty("option", out JsonElement option)) return BadRequest(); ItemInfo itemInfo; itemInfo = item.ToObject(); itemInfo.ttl = -1; itemInfo.pk = "Item"; if (option.ToString().Equals("insert")) { itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); //new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds(); itemInfo.code = "Item-" + itemInfo.code; var response = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(itemInfo.id, new PartitionKey($"{itemInfo.code}")); if (response.Status == 200) { return Ok(); } else { if (itemInfo.scope.Equals("private")) { itemInfo = await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}")); } else { itemInfo = await client.GetContainer("TEAMModelOS", "School").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}")); } } } else { itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); if (itemInfo.scope.Equals("private")) { if (!itemInfo.code.Contains("Item")) { itemInfo.code = "Item-" + itemInfo.code; // itemInfo = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}")); } itemInfo = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}")); } else { if (!itemInfo.code.Contains("Item")) { itemInfo.code = "Item-" + itemInfo.code; //itemInfo = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}")); } itemInfo = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}")); } } return Ok(new { itemInfo }); } /// //获取题目摘要信息 /// /// /// [ProducesDefaultResponseType] //[AuthToken(Roles = "teacher")] [HttpPost("find-summary")] public async Task FindSummary(JsonElement requert) { var client = _azureCosmos.GetCosmosClient(); StringBuilder sql = new StringBuilder(); sql.Append("select c.id, c.question,c.useCount,c.level,c.field,c.points,c.type,c.option,c.createTime from c "); if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest(); /* if (!requert.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest(); if (!requert.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/ if (!requert.TryGetProperty("@DESC", out JsonElement desc)) return BadRequest(); if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest(); List summary = new List(); Dictionary dict = new Dictionary(); /* dict.Add("@CURRPAGE", page.GetInt32()); dict.Add("@PAGESIZE", size.GetInt32());*/ dict.Add("@DESC", desc.ToString()); if (requert.TryGetProperty("periodId", out JsonElement periodId)) { dict.Add("periodId", periodId); } if (requert.TryGetProperty("subjectId", out JsonElement subjectId)) { dict.Add("subjectId", subjectId); } if (requert.TryGetProperty("level", out JsonElement level)) { dict.Add("level", level); } if (requert.TryGetProperty("type", out JsonElement type)) { dict.Add("type", type); } if (requert.TryGetProperty("field", out JsonElement field)) { dict.Add("field", field); } AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql); //List items = new List(); if (scope.ToString().Equals("private")) { await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") })) { 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()) { summary.Add(obj.ToObject()); } } } } if (scope.ToString().Equals("school")) { await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") })) { 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()) { summary.Add(obj.ToObject()); } } } } return Ok(new { summary }); } /// /// 手动挑题 /// /// /// [ProducesDefaultResponseType] //[AuthToken(Roles = "teacher")] [HttpPost("find-by-ids")] public async Task FindByIds(List request) { ResponseBuilder builder = ResponseBuilder.custom(); List items = await _azureCosmos.FindByIds(request); return Ok(items); } /// /// 删除 /// /// /// [ProducesDefaultResponseType] //[AuthToken(Roles = "teacher")] [HttpPost("delete")] public async Task Delete(JsonElement request) { try { if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest(); if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest(); if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest(); var client = _azureCosmos.GetCosmosClient(); if (scope.ToString().Equals("school")) { var response = await client.GetContainer("TEAMModelOS", "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}")); return Ok(new { code = response.Status }); } else { var response = await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}")); return Ok(new { code = response.Status }); } } catch (Exception e) { return BadRequest(); } /* ResponseBuilder builder = ResponseBuilder.custom(); IdPk idPk = await _azureCosmos.DeleteAsync( request ); return Ok(idPk);*/ } /// /// 删除 /// /// /// [ProducesDefaultResponseType] //[AuthToken(Roles = "teacher")] [HttpPost("delete-all")] public async Task DeleteAll(JsonElement request) { ResponseBuilder builder = ResponseBuilder.custom(); List idPk = await _azureCosmos.DeleteAll(request); return Ok(idPk); } /// /// 手动挑题 /// /// /// [ProducesDefaultResponseType] //[AuthToken(Roles = "teacher")] [HttpPost("find")] public async Task Find(JsonElement requert) { var client = _azureCosmos.GetCosmosClient(); StringBuilder sql = new StringBuilder(); sql.Append("select c.id,c.code,c.repairResource, c.periodId,c.question,c.useCount,c.level,c.field,c.points,c.type,c.option,c.createTime,c.answer,c.explain,c.children,c.score,c.gradeIds,c.subjectId,c.blob,c.scope from c "); if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest(); /* if (!requert.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest(); if (!requert.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/ if (!requert.TryGetProperty("@DESC", out JsonElement desc)) return BadRequest(); if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest(); Dictionary dict = new Dictionary(); /*var emobj = requert.EnumerateObject(); while (emobj.MoveNext()) { dict[emobj.Current.Name] = emobj.Current.Value; } //处理code if (dict.TryGetValue("code", out object _)) { dict.Remove("code"); }*/ /* dict.Add("@CURRPAGE", page.GetInt32()); dict.Add("@PAGESIZE", size.GetInt32());*/ dict.Add("@DESC", desc.ToString()); if (requert.TryGetProperty("periodId", out JsonElement periodId)) { dict.Add("periodId", periodId); } if (requert.TryGetProperty("subjectId", out JsonElement subjectId)) { dict.Add("subjectId", subjectId); } if (requert.TryGetProperty("level", out JsonElement level)) { dict.Add("level", level); } if (requert.TryGetProperty("type", out JsonElement type)) { dict.Add("type", type); } if (requert.TryGetProperty("field", out JsonElement field)) { dict.Add("field", field); } if (requert.TryGetProperty("gradeIds[*]", out JsonElement gradeIds)) { dict.Add("gradeIds[*]", gradeIds); } AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql); List items = new List(); if (scope.ToString().Equals("private")) { await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") })) { 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()) { items.Add(obj.ToObject()); } } } } if(scope.ToString().Equals("school")) { await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") })) { 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()) { items.Add(obj.ToObject()); } } } } //ResponseBuilder builder = ResponseBuilder.custom(); /* List items = new List(); if (StringHelper.getKeyCount(requert) > 0) { items = await _azureCosmos.FindByDict(requert); }*/ return Ok(new { items }); //return builder.Data(items).build(); } /// /// 手动挑题 /// /// /// [ProducesDefaultResponseType] //[AuthToken(Roles = "teacher")] [HttpPost("Find-cache-shell")] public async Task FindCacheShell(JsonElement requert) { var client = _azureCosmos.GetCosmosClient(); if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest(); if (!requert.TryGetProperty("ids", out JsonElement id)) return BadRequest(); //List ids = new List(); string info = ""; for (int i = 0; i < id.GetArrayLength(); i++) { //ids.Add(id[i].ToJsonString()); info += id[i].ToJsonString() + ","; } List items = new List(); var query = $"select c.id, c.question,c.useCount,c.level,c.field,c.points,c.type,c.option,c.createTime from c where c.id in ({info[0..^1]})"; await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ItemInfo-{school_code}") })) { 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()) { items.Add(obj.ToObject()); } } } return Ok(new { items }); /* ResponseBuilder builder = ResponseBuilder.custom(); List items = await _azureCosmos.FindByIds(request); //List ps = new List() { "6f705b1b-8221-5307-18da-13da05adf91e", "c3e1e95a-561e-fabf-cce3-3a564782e443" }; // // //Random random = new Random(); //items.ForEach(x => { x.usageCount = random.Next(0, 300);x.createTime = random.Next(1426668584, 1584521384);x.order = random.Next(1, items.Count); }); //await cosmosDBV3Repository.SaveOrUpdateAll(items); return builder.Data(items).build();*/ } /// /// 自动组题 /// /// /// [HttpPost("Automatic")] public async Task Automatic(List request) { //ResponseBuilder builder = ResponseBuilder.custom(); List> list = new List>(); var client = _azureCosmos.GetCosmosClient(); for (int i = 0; i < request.Count; i++) { ///处理知识点均分问题 int avg = 0; Dictionary point = new Dictionary(); if (request[i].points.IsNotEmpty()) { avg = (int)Math.Ceiling(request[i].count * 1.0 / request[i].points.Count); foreach (string p in request[i].points) { point.TryAdd(p, avg); } } List retnInfos = new List(); List itemInfos = new List(); List tempItems = new List(); if (request[i].quInfos.IsNotEmpty()) { List types = new List(); List levels = new List(); foreach (QuInfo quInfo in request[i].quInfos) { StringBuilder sql = new StringBuilder(); sql.Append("select c.id,c.code,c.repairResource, c.periodId,c.question,c.useCount,c.level,c.field,c.points,c.type,c.option,c.createTime,c.answer,c.explain,c.children,c.score,c.gradeIds,c.subjectId,c.blob,c.scope from c "); // 自定义 if (quInfo.custom.IsNotEmpty() && quInfo.policy.Equals("custom")) { foreach (Custom custom in quInfo.custom) { for (int j = 0; j < custom.count; j++) { tempItems.Add(new TempItem { level = custom.level, type = quInfo.type }); } Dictionary dict = new Dictionary(); if (!string.IsNullOrEmpty(request[i].code)) { dict.Add("code", request[i].code); } if (!string.IsNullOrEmpty(request[i].period)) { dict.Add("periodId", request[i].period); } if (request[i].points.IsNotEmpty()) { dict.Add("points[*]", request[i].points.ToArray()); } dict.Add("lite", false); /// dict.Add("type", quInfo.type); dict.Add("level", custom.level); List items = new List(); AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql); if (request[i].scope.Equals("school")) { await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") })) { 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()) { items.Add(obj.ToObject()); } } } } else { await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") })) { 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()) { items.Add(obj.ToObject()); } } } } //List items = await _azureCosmos.FindByDict(dict); //id去重 items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList(); ////均分知识点题目 itemInfos.AddRange(items); } } else { Dictionary dict = new Dictionary(); if (!string.IsNullOrEmpty(request[i].code)) { dict.Add("code", request[i].code); } if (!string.IsNullOrEmpty(request[i].period)) { dict.Add("periodId", request[i].period); } if (request[i].points.IsNotEmpty()) { dict.Add("points[*]", request[i].points.ToArray()); } if (!string.IsNullOrEmpty(request[i].subject)) { dict.Add("subjectId", request[i].subject); } dict.Add("lite", false); dict.Add("type", quInfo.type); List items = new List(); AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql); if (request[i].scope.Equals("school")) { await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") })) { 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()) { items.Add(obj.ToObject()); } } } } else { await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") })) { 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()) { items.Add(obj.ToObject()); } } } } //List items = await _azureCosmos.FindByDict(dict); //id去重 items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList(); itemInfos.AddRange(items); //均分 if (quInfo.policy.Equals("average")) { //按等级去重 获取所有等级 List lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList(); foreach (int k in lvls) { int count = quInfo.count / lvls.Count; for (int j = 0; j < count; j++) { tempItems.Add(new TempItem { level = k, type = quInfo.type }); } } // 余数 取模 随机处理 if (lvls.Count != 0) { int mod = quInfo.count % lvls.Count; for (int m = 0; m < mod; m++) { int lv = lvls.OrderBy(x => Guid.NewGuid()).Take(1).FirstOrDefault(); tempItems.Add(new TempItem { level = lv, type = quInfo.type }); lvls.Remove(lv); } } } //随机 if (quInfo.policy.Equals("random")) { List lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList(); for (int n = 0; n < quInfo.count; n++) { int lv = lvls.OrderBy(x => Guid.NewGuid()).FirstOrDefault(); tempItems.Add(new TempItem { level = lv, type = quInfo.type,policy = "random" }); } } } } } itemInfos = itemInfos.OrderBy(x => Guid.NewGuid()).ToList(); tempItems = tempItems.OrderBy(x => Guid.NewGuid()).ToList(); foreach (TempItem temp in tempItems) { ItemInfo itemInfo = new ItemInfo(); if (temp.policy != null && temp.policy.Equals("random")) { itemInfo = itemInfos.Where(x => x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault(); } else { itemInfo = itemInfos.Where(x => x.level == temp.level && x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault(); } if (itemInfo != null) { retnInfos.Add(itemInfo); itemInfos.Remove(itemInfo); } } List> listInfo = new List>(); foreach (IGrouping group in retnInfos.GroupBy(c => c.type)) { Dictionary dictInfo = new Dictionary(); listInfo.Add(group.ToList()); } foreach (List infos in listInfo) { List> dict = new List>(); foreach (IGrouping group in infos.GroupBy(c => c.level)) { Dictionary dictInfo = new Dictionary(); dictInfo.Add("level", group.Key); dictInfo.Add("count", group.Count()); dict.Add(dictInfo); } Dictionary typeDict = new Dictionary(); typeDict.Add("info", dict); typeDict.Add("item", infos); typeDict.Add("count", infos.Count); typeDict.Add("type", infos.FirstOrDefault().type); list.Add(typeDict); } } //return builder.Data(list).build(); return Ok(list); } } public class TempItem { public string type { get; set; } public int level { get; set; } public ItemInfo itemInfo { get; set; } public string policy { get; set; } } public class Compose { /// /// 科目 /// public string subject { get; set; } /// /// 来源,个人题库,校本题库 /// public string code { get; set; } /// /// 适用学段,小学,初中,高中 /// public string period { get; set; } /// /// 关联知识点 /// public List points { get; set; } /// /// 题目组合 /// public List quInfos { get; set; } /// /// 题目总数 /// public int count { get; set; } public string scope { get; set; } } public class QuInfo { /// /// 题目类型,单选,多选,判断,填空,问答,综合 Single单选,Multiple多选,Judge判断,Complete填空,Subjective问答,Compose综合 /// public string type { get; set; } /// /// 随机 random 平均的 average ,自定义 custom /// public string policy { get; set; } /// /// 自定义题目类型 /// public List custom { get; set; } /// /// 总题 /// public int count { get; set; } } public class Custom { /// /// 难易程度 /// public int level { get; set; } /// /// 数量 /// public int count { get; set; } } }