123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915 |
- using Azure.Cosmos;
- using DocumentFormat.OpenXml.Bibliography;
- using DocumentFormat.OpenXml.Drawing.Charts;
- using DocumentFormat.OpenXml.Spreadsheet;
- using MathNet.Numerics.LinearAlgebra.Double;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.Options;
- using OpenXmlPowerTools;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Text.Json;
- using System.Threading.Tasks;
- using TEAMModelOS.Filter;
- using TEAMModelOS.Models;
- using TEAMModelOS.SDK;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.Extension;
- using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
- using TEAMModelOS.SDK.Models;
- using TEAMModelOS.SDK.Models.Cosmos.Common;
- namespace TEAMModelOS.Controllers.Analysis
- {
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- [Route("class/analysis")]
- [ApiController]
- public class ClassAnalysisController : ControllerBase
- {
- private readonly AzureCosmosFactory _azureCosmos;
- private readonly SnowflakeId _snowflakeId;
- private readonly AzureServiceBusFactory _serviceBus;
- private readonly DingDing _dingDing;
- private readonly Option _option;
- private readonly AzureStorageFactory _azureStorage;
- private readonly CoreAPIHttpService _coreAPIHttpService;
- public ClassAnalysisController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
- IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage)
- {
- _azureCosmos = azureCosmos;
- _serviceBus = serviceBus;
- _snowflakeId = snowflakeId;
- _dingDing = dingDing;
- _option = option?.Value;
- _azureStorage = azureStorage;
- _coreAPIHttpService = coreAPIHttpService;
- }
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [Authorize(Roles = "IES")]
- [AuthToken(Roles = "teacher,admin")]
- [HttpPost("analysis-recod")]
- public async Task<IActionResult> analysisRecod(JsonElement request)
- {
- try
- {
- //区级Id
- //if (!request.TryGetProperty("time", out JsonElement time)) return BadRequest();
- if (!request.TryGetProperty("stime", out JsonElement stime)) return BadRequest();
- if (!request.TryGetProperty("etime", out JsonElement etime)) return BadRequest();
- if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
- if (!request.TryGetProperty("periodId", out JsonElement pId)) return BadRequest();
- long st = stime.GetInt64();
- long et = etime.GetInt64();
- //获取当前学期所有的课程记录
- List<LessonRecord> records = new List<LessonRecord>();
- var client = _azureCosmos.GetCosmosClient();
- var queryClass = $"select value(c) from c where c.periodId = '{pId}'";
- string tId = string.Empty;
- if (request.TryGetProperty("tmdId", out JsonElement tmdId))
- {
- queryClass = $"select value(c) from c where c.tmdid = '{tmdId}'";
- tId = tmdId.GetString();
- }
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonRecord>(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord-{code}") }))
- {
- records.Add(item);
- }
- if (records.Count > 0)
- {
- var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(code.GetString(), new PartitionKey($"Base"));
- School sc = new School();
- if (response.Status == 200)
- {
- using var json = await JsonDocument.ParseAsync(response.ContentStream);
- sc = json.ToObject<School>();
- }
- List<(string name, double count)> rc = await getRecordCount(client, records, st, et, code.GetString(), tId, pId.GetString());
- List<(int week, List<double> count)> tpc = await getTPCount(client, records, st, et, code.GetString(), tId, pId.GetString());
- List<(string name, int count)> groups = getGroupCount(records, st, et);
- List<(string name, int count)> grades = getGradeCount(records, st, et);
- List<(string name, int count)> types = getTypeCount(records, st, et);
- List<double> exams = await getExamTypeCount(client, st, et, code.GetString());
- var subs = records.GroupBy(x => x.subjectId).Select(y => new { key = y.Key, count = y.ToList().Count }).ToList();
- List<string> groupIds = new List<string>();
- List<(string name, int count)> groc = new List<(string name, int count)>();
- foreach (var item in groups)
- {
- List<GroupListGrp> grps = await GroupListService.GetMemberInGroupList(_coreAPIHttpService, client, _dingDing, item.name, 1, code.GetString(), new List<string> { "research" });
- //groupIds.Add(item.name);
- //List<(string name, int count)> groc = new List<(string name, int count)>();
- foreach (var grp in grps)
- {
- groc.Add((grp.name, item.count));
- }
- }
- //var gyc = groc.GroupBy(x => x.name).Select(y => new {name = y.Key, count = y.Sum(c => c.count) });
- //var gs = sc.period.Where(s => s.id == pId.GetString()).Select(x => x.grades);
- //(List<RMember> tchList, List<RGroupList> classLists) = await GroupListService.GetStutmdidListids(_coreAPIHttpService, client, _dingDing, groupIds, code.GetString(), null);
- var total = rc.Select(x => new { x.name, value = x.count });
- var trend = tpc.Select(x => new { name = x.week, value = x.count });
- var classify_group = groc.GroupBy(x => x.name).Select(y => new { name = y.Key, value = y.Sum(c => c.count) });
- var classify = grades.Select(x => new { x.name, value = x.count });
- var classify_type = types.Select(x => new { x.name, value = x.count });
- var classify_sub = subs.Select(x => new { name = x.key, value = x.count });
- double teachCount = records.Where(r => r.tmdid != null).Where((x, i) => records.FindIndex(z => z.tmdid == x.tmdid) == i).ToList().Count;
- double taskCount = records.Select(c => c.collateTaskCount).Sum();
- double workCount = records.Select(c => c.collateCount).Sum();
- double examQuizCount = records.Select(c => c.examQuizCount).Sum();
- double interactCount = records.Select(c => c.clientInteractionCount).Sum();
- //学校基本信息
- School scInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{code}", partitionKey: new PartitionKey("Base"));
- var perMore = scInfo.period.Where(c => c.id.Equals(pId.GetString())).FirstOrDefault().grades;
- var interaction = records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64() && c.grade.Any()).GroupBy(k => int.Parse(k.grade?[0])).Select(x => new
- {
- x.Key,
- name = perMore[x.Key],
- count = x.Sum(t => t.learningCategory.interaction)
- });
- var cooperation = records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64() && c.grade.Any()).GroupBy(k => int.Parse(k.grade?[0])).Select(x => new
- {
- x.Key,
- name = perMore[x.Key],
- count = x.Sum(t => t.learningCategory.cooperation)
- });
- var task = records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64() && c.grade.Any()).GroupBy(k => int.Parse(k.grade?[0])).Select(x => new
- {
- x.Key,
- name = perMore[x.Key],
- count = x.Sum(t => t.learningCategory.task)
- });
- var exam = records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64() && c.grade.Any()).GroupBy(k => int.Parse(k.grade?[0])).Select(x => new
- {
- x.Key,
- name = perMore[x.Key],
- count = x.Sum(t => t.learningCategory.exam)
- });
- var diffential = records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64() && c.grade.Any()).GroupBy(k => int.Parse(k.grade?[0])).Select(x => new
- {
- x.Key,
- name = perMore[x.Key],
- count = x.Sum(t => t.learningCategory.diffential)
- });
- List<(string name, int? cICount, int? pCount, int? cTCount, int? eCount,int? diffCount)> tcount = new();
- List<(string name, int? count)> gdCount = new();
- perMore.ForEach(x =>
- {
- var cICount = interaction.Where(c => c.name.Equals(x, StringComparison.OrdinalIgnoreCase)).FirstOrDefault()?.count;
- var pCount = cooperation.Where(c => c.name.Equals(x, StringComparison.OrdinalIgnoreCase)).FirstOrDefault()?.count;
- var cTCount = task.Where(c => c.name.Equals(x, StringComparison.OrdinalIgnoreCase)).FirstOrDefault()?.count;
- var eCount = exam.Where(c => c.name.Equals(x, StringComparison.OrdinalIgnoreCase)).FirstOrDefault()?.count;
- var diffCount = diffential.Where(c => c.name.Equals(x, StringComparison.OrdinalIgnoreCase)).FirstOrDefault()?.count;
- var gradeCount = grades.Where(c => perMore[int.Parse(c.name)].Equals(x, StringComparison.OrdinalIgnoreCase)).FirstOrDefault().count;
- tcount.Add((x, cICount, pCount, cTCount, eCount, diffCount));
- gdCount.Add((x, gradeCount));
- });
- var teachingCount = tcount.Select(x => new
- {
- x.name,
- interaction = x.cICount == null ? 0 : x.cICount,
- cooperation = x.pCount == null ? 0 : x.pCount,
- task = x.cTCount == null ? 0 : x.cTCount,
- exam = x.eCount == null ? 0 : x.eCount,
- diffential = x.diffCount == null ? 0 : x.eCount
- });
- var classify_grade = gdCount.Select(x => new
- {
- x.name,
- value = x.count
- });
- return Ok(new { total, trend, classify_group, classify_grade, classify_type, classify_sub, teachCount, taskCount, workCount, examQuizCount, interactCount, exams, teachingCount });
- }
- else
- {
- return Ok(new { code = 404, msg = "暂无课程记录" });
- }
- }
- catch (Exception e)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/analysis-recod()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
- return BadRequest();
- }
- }
- /// <param name="request"></param>
- /// <returns></returns>
- [ProducesDefaultResponseType]
- [Authorize(Roles = "IES")]
- [AuthToken(Roles = "teacher,admin")]
- [HttpPost("analysis-recod-teacher")]
- public async Task<IActionResult> analysisRecordTeacher(JsonElement request)
- {
- try
- {
- //区级Id
- //if (!request.TryGetProperty("time", out JsonElement time)) return BadRequest();
- if (!request.TryGetProperty("stime", out JsonElement stime)) return BadRequest();
- if (!request.TryGetProperty("etime", out JsonElement etime)) return BadRequest();
- if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
- //if (!request.TryGetProperty("periodId", out JsonElement pId)) return BadRequest();
- long st = 0;
- long et = 0;
- try
- {
- stime.TryGetInt64(out st);
- etime.TryGetInt64(out et);
- }
- catch (Exception e)
- {
- //await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/analysisRecordTeacher()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
- }
- /*if (null != stime.GetString() && null != etime.GetString()) {
- st = stime.GetInt64();
- et = etime.GetInt64();
- }*/
- //获取当前学期所有的课程记录
- List<LessonRecord> records = new List<LessonRecord>();
- var client = _azureCosmos.GetCosmosClient();
- var queryClass = $"select value(c) from c ";
- string tId = string.Empty;
- if (request.TryGetProperty("tmdId", out JsonElement tmdId))
- {
- queryClass = $"select value(c) from c where c.tmdid = '{tmdId}'";
- tId = tmdId.GetString();
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<LessonRecord>(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord") }))
- {
- records.Add(item);
- }
- }
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonRecord>(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord-{code}") }))
- {
- records.Add(item);
- }
- if (records.Count > 0)
- {
- List<(string name, double count)> rc = await getRecordCount(client, records, st, et, code.GetString(), tId, "");
- List<(int week, List<double> count)> tpc = await getTPCount(client, records, st, et, code.GetString(), tId, "");
- var total = rc.Select(x => new { x.name, value = x.count });
- var trend = tpc.Select(x => new { name = x.week, value = x.count });
- var max = records.Select(x => x.tScore).Max();
- return Ok(new { total, trend, max });
- }
- else
- {
- return Ok(new { code = 404, msg = "暂无课程记录" });
- }
- }
- catch (Exception e)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/analysisRecordTeacher()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
- return BadRequest();
- }
- }
- [ProducesDefaultResponseType]
- [Authorize(Roles = "IES")]
- [AuthToken(Roles = "teacher,admin")]
- [HttpPost("analysis-record-count")]
- public async Task<IActionResult> analysisRecordCount(JsonElement request)
- {
- try
- {
- if (!request.TryGetProperty("stime", out JsonElement stime)) return BadRequest();
- if (!request.TryGetProperty("etime", out JsonElement etime)) return BadRequest();
- if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
- if (!request.TryGetProperty("periodId", out JsonElement pId)) return BadRequest();
- //获取当前学期所有的课程记录
- List<LessonRecord> records = new();
- var client = _azureCosmos.GetCosmosClient();
- var queryClass = $"select value(c) from c where c.periodId = '{pId}' and (c.status<>404 or IS_DEFINED(c.status) = false) and c.expire <= 0 and array_length(c.groupIds)>0 ";
- string tId = string.Empty;
- if (request.TryGetProperty("tmdId", out JsonElement tmdId))
- {
- queryClass = $"select value(c) from c where c.tmdid = '{tmdId}' and c.periodId = '{pId}' and (c.status<>404 or IS_DEFINED(c.status) = false) and c.expire <= 0 and array_length(c.groupIds)>0 ";
- tId = tmdId.GetString();
- }
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonRecord>(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord-{code}") }))
- {
- records.Add(item);
- }
- //班级信息
- List<string> classes = await getStudentsAsync(pId.GetString(), client, "Class", "School");
- if (records.Count > 0)
- {
- var sTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- var time = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd");
- var today = DateTimeHelper.FromUnixTimestamp(sTime);
- DateTime startWeek = today.AddDays(1 - Convert.ToInt32(today.DayOfWeek.ToString("d")));
- DateTime startMonth = today.AddDays(1 - today.Day); //本月月初
- var wt = DateTimeHelper.ToUnixTimestamp(startWeek);
- var mt = DateTimeHelper.ToUnixTimestamp(startMonth);
- var wwt = DateTimeOffset.FromUnixTimeMilliseconds(wt).ToString("yyyy-MM-dd");
- var mmt = DateTimeOffset.FromUnixTimeMilliseconds(mt).ToString("yyyy-MM-dd");
- string sst = string.Format("{0}{1}{2}", time, " ", "00:00:00");
- string wst = string.Format("{0}{1}{2}", wwt, " ", "00:00:00");
- string mst = string.Format("{0}{1}{2}", mmt, " ", "00:00:00");
- string est = string.Format("{0}{1}{2}", time, " ", "23:59:59");
- var tt = DateTimeOffset.Parse(sst).ToUnixTimeMilliseconds();
- var weekstime = DateTimeOffset.Parse(wst).ToUnixTimeMilliseconds();
- var monthstime = DateTimeOffset.Parse(mst).ToUnixTimeMilliseconds();
- var endtime = DateTimeOffset.Parse(est).ToUnixTimeMilliseconds();
- var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(code.GetString(), new PartitionKey($"Base"));
- School sc = new School();
- if (response.Status == 200)
- {
- using var json = await JsonDocument.ParseAsync(response.ContentStream);
- sc = json.ToObject<School>();
- }
- List<(string time, double count)> counts = new()
- {
- ("total", records.Count),
- ("today", records.Where(c => c.startTime >= tt && c.startTime <= endtime).ToList().Count),
- ("week", records.Where(c => c.startTime >= weekstime && c.startTime <= endtime).ToList().Count),
- ("month", records.Where(c => c.startTime >= monthstime && c.startTime <= endtime).ToList().Count),
- ("semester", records.Where(c => c.startTime >= stime.GetInt64() && c.startTime <= etime.GetInt64()).ToList().Count)
- };
- var total = counts.Select(x => new
- {
- name = x.time,
- value = x.count
- });
- var tp = records.Where(c => c.tLevel == 2 && c.pLevel == 2).ToList().Count;
- return Ok(new { total, tp, classCount = classes?.Count });
- }
- else
- {
- return Ok(new { total = new List<string>(), tp = 0, classCount = classes?.Count });
- }
- }
- catch (Exception e)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/analysis-record-count()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
- return BadRequest();
- }
- }
- private List<(string name, int count)> getGroupCount(List<LessonRecord> records, long stime, long etime)
- {
- List<string> groupIds = new();
- List<(string name, int count)> grCount = new();
- var subs = records.Where(r => r.startTime >= stime && r.startTime <= etime).GroupBy(x => x.tmdid).Select(y => new { key = y.Key, count = y.ToList().Count }).ToList();
- /*foreach (var groupId in groupIds)
- {
- var c = records.Where(r => r.groupIds.Contains(groupId)).Count();
- grCount.Add((groupId, c));
- }*/
- foreach (var gr in subs)
- {
- grCount.Add((gr.key, gr.count));
- }
- return grCount;
- }
- private List<(string name, int count)> getGradeCount(List<LessonRecord> records, long stime, long etime)
- {
- List<string> grades = new();
- List<(string name, int count)> gCount = new();
- foreach (var record in records)
- {
- foreach (string gId in record.grade)
- {
- if (!grades.Contains(gId) && int.Parse(gId) >= 0)
- {
- grades.Add(gId);
- }
- }
- }
- foreach (var gId in grades)
- {
- var c = records.Where(r => r.grade.Contains(gId) && r.startTime >= stime && r.startTime <= etime).Count();
- gCount.Add((gId, c));
- }
- return gCount;
- }
- private List<(string name, int count)> getTypeCount(List<LessonRecord> records, long stime, long etime)
- {
- List<string> tags = new();
- List<(string name, int count)> tyCount = new();
- foreach (var record in records)
- {
- foreach (string tag in record.category)
- {
- if (!tags.Contains(tag))
- {
- tags.Add(tag);
- }
- }
- }
- foreach (var tag in tags)
- {
- var c = records.Where(r => r.category.Contains(tag) && r.startTime >= stime && r.startTime <= etime).Count();
- tyCount.Add((tag, c));
- }
- return tyCount;
- }
- //课列趋势图
- private async Task<List<(int week, List<double> count)>> getTPCount(CosmosClient client, List<LessonRecord> records, long stime, long etime, string code, string tId, string periodId)
- {
- try
- {
- List<(int week, List<double>)> wks = new();
- var syear = DateTimeOffset.FromUnixTimeMilliseconds(stime).Year;
- //var eyear = DateTimeOffset.FromUnixTimeMilliseconds(etime).Year;
- var sday = DateTimeOffset.FromUnixTimeMilliseconds(stime).DayOfYear;
- //var eday = DateTimeOffset.FromUnixTimeMilliseconds(etime).DayOfYear;
- int dayOfweek = (int)DateTimeOffset.FromUnixTimeMilliseconds(stime).DayOfWeek;
- var tyear = DateTimeOffset.UtcNow.Year;
- //求开学年多少天
- int tdays = DateTimeHelper.getDays(syear);
- //如果跨年 求今年多少天
- //int pydays = DateTimeHelper.getDays(eyear);
- (List<LessonCount> scount, List<LessonCount> tcount) = await getCount(client, records, syear, tyear, code, tId, periodId);
- List<List<double>> begin = new();
- List<List<double>> t = new();
- List<List<double>> p = new();
- List<List<double>> pt = new();
- if (scount.Count > 0)
- {
- foreach (LessonCount lesson in scount)
- {
- begin.Add(lesson.beginCount);
- t.Add(lesson.tCount);
- p.Add(lesson.pCount);
- pt.Add(lesson.ptCount);
- }
- var bmatrix = DenseMatrix.OfColumns(begin);
- var tmatrix = DenseMatrix.OfColumns(t);
- var pmatrix = DenseMatrix.OfColumns(p);
- var ptmatrix = DenseMatrix.OfColumns(pt);
- //开学第一周周内开课
- if (dayOfweek == 0)
- {
- dayOfweek = 7;
- }
- //补齐第一周
- //var fd = dayOfweek - 1;
- //本周有多少天
- var dd = 7 - dayOfweek + 1;
- int startdays = tdays - sday + dayOfweek;
- //有几周
- int sweeks = startdays / 7;
- //余几天
- int rweeks = startdays % 7;
- if (sweeks > 0)
- {
- for (int i = 1; i <= sweeks; i++)
- {
- if (i == 1)
- {
- var bsum = bmatrix.SubMatrix(sday - 1, dd, 0, bmatrix.ColumnCount).ColumnSums().Sum();
- var tsum = tmatrix.SubMatrix(sday - 1, dd, 0, tmatrix.ColumnCount).ColumnSums().Sum();
- var psum = pmatrix.SubMatrix(sday - 1, dd, 0, pmatrix.ColumnCount).ColumnSums().Sum();
- var ptsum = ptmatrix.SubMatrix(sday - 1, dd, 0, ptmatrix.ColumnCount).ColumnSums().Sum();
- sday += dd;
- wks.Add((i, new List<double>() { bsum, tsum, psum, ptsum }));
- }
- else
- {
- var bsum = bmatrix.SubMatrix(sday - 1, 7, 0, bmatrix.ColumnCount).ColumnSums().Sum();
- var tsum = tmatrix.SubMatrix(sday - 1, 7, 0, tmatrix.ColumnCount).ColumnSums().Sum();
- var psum = pmatrix.SubMatrix(sday - 1, 7, 0, pmatrix.ColumnCount).ColumnSums().Sum();
- var ptsum = ptmatrix.SubMatrix(sday - 1, 7, 0, ptmatrix.ColumnCount).ColumnSums().Sum();
- sday += 7;
- wks.Add((i, new List<double>() { bsum, tsum, psum, ptsum }));
- }
- }
- }
- if (rweeks > 0)
- {
- var bsum = bmatrix.SubMatrix(tdays - rweeks - 1, rweeks + 1, 0, bmatrix.ColumnCount).ColumnSums().Sum();
- var tsum = tmatrix.SubMatrix(tdays - rweeks - 1, rweeks + 1, 0, tmatrix.ColumnCount).ColumnSums().Sum();
- var psum = pmatrix.SubMatrix(tdays - rweeks - 1, rweeks + 1, 0, pmatrix.ColumnCount).ColumnSums().Sum();
- var ptsum = ptmatrix.SubMatrix(tdays - rweeks - 1, rweeks + 1, 0, ptmatrix.ColumnCount).ColumnSums().Sum();
- if (tyear > syear)
- {
- var eday = DateTimeOffset.UtcNow.DayOfYear;
- int pydays = DateTimeHelper.getDays(tyear);
- List<List<double>> e_begin = new();
- List<List<double>> e_t = new();
- List<List<double>> e_p = new();
- List<List<double>> e_pt = new();
- if (tcount.Count > 0)
- {
- foreach (LessonCount lesson in tcount)
- {
- e_begin.Add(lesson.beginCount);
- e_t.Add(lesson.tCount);
- e_p.Add(lesson.pCount);
- e_pt.Add(lesson.ptCount);
- }
- var tbmatrix = DenseMatrix.OfColumns(e_begin);
- var ttmatrix = DenseMatrix.OfColumns(e_t);
- var tpmatrix = DenseMatrix.OfColumns(e_p);
- var tptmatrix = DenseMatrix.OfColumns(e_pt);
- int day = 7 - rweeks;
- //补齐新年第一周
- int start = eday - day;
- int eweeks = start / 7;
- int erweeks = start % 7;
- var tbsum = tbmatrix.SubMatrix(0, day, 0, tbmatrix.ColumnCount).ColumnSums().Sum();
- var ttsum = ttmatrix.SubMatrix(0, day, 0, ttmatrix.ColumnCount).ColumnSums().Sum();
- var tpsum = tpmatrix.SubMatrix(0, day, 0, tpmatrix.ColumnCount).ColumnSums().Sum();
- var tptsum = tptmatrix.SubMatrix(0, day, 0, tptmatrix.ColumnCount).ColumnSums().Sum();
- wks.Add((sweeks + 1, new List<double>() { bsum + tbsum, tsum + ttsum, psum + tpsum, ptsum + tptsum }));
- if (eweeks > 0)
- {
- for (int i = 1; i <= eweeks; i++)
- {
- var newbsum = tbmatrix.SubMatrix(day, 7, 0, tbmatrix.ColumnCount).ColumnSums().Sum();
- var newtsum = ttmatrix.SubMatrix(day, 7, 0, ttmatrix.ColumnCount).ColumnSums().Sum();
- var newpsum = tpmatrix.SubMatrix(day, 7, 0, tpmatrix.ColumnCount).ColumnSums().Sum();
- var newptsum = tptmatrix.SubMatrix(day, 7, 0, tptmatrix.ColumnCount).ColumnSums().Sum();
- day += 7;
- wks.Add((sweeks += 1, new List<double>() { newbsum, newtsum, newpsum, newptsum }));
- }
- }
- if (erweeks > 0)
- {
- var newbsum = tbmatrix.SubMatrix(eday - day - 1, erweeks, 0, tbmatrix.ColumnCount).ColumnSums().Sum();
- var newtsum = ttmatrix.SubMatrix(eday - day - 1, erweeks, 0, ttmatrix.ColumnCount).ColumnSums().Sum();
- var newpsum = tpmatrix.SubMatrix(eday - day - 1, erweeks, 0, tpmatrix.ColumnCount).ColumnSums().Sum();
- var newptsum = tptmatrix.SubMatrix(eday - day - 1, erweeks, 0, tptmatrix.ColumnCount).ColumnSums().Sum();
- wks.Add((sweeks + 1, new List<double>() { newbsum, newtsum, newpsum, newptsum }));
- }
- }
- }
- else
- {
- wks.Add((sweeks + 1, new List<double>() { bsum, tsum, psum, ptsum }));
- }
- }
- }
- return wks;
- }
- catch (Exception e)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/getTPCount()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
- return null;
- }
- }
- private async Task<(List<LessonCount> sc, List<LessonCount> tc)> getCount(CosmosClient client, List<LessonRecord> records, int syear, int tyear, string code, string tId, string periodId)
- {
- List<LessonCount> scount = new();
- List<LessonCount> tcount = new();
- var queryClass = $"select value(c) from c ";
- List<string> perId = records.Select(r => r.periodId).Distinct().ToList();
- if (!string.IsNullOrEmpty(tId))
- {
- queryClass = $"select value(c) from c where c.id = '{tId}'";
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<LessonCount>(
- queryText: queryClass,
- requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonCount-{syear}") }))
- {
- scount.Add(item);
- }
- foreach (string pId in perId)
- {
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonCount>(
- queryText: queryClass,
- requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonCount-{code}-{syear}-{pId}") }))
- {
- scount.Add(item);
- }
- }
- }
- else
- {
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonCount>(
- queryText: queryClass,
- requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonCount-{code}-{syear}-{periodId}") }))
- {
- scount.Add(item);
- }
- }
- if (scount.Count == 0)
- {
- int days = DateTimeHelper.getDays(syear);
- foreach (LessonRecord record in records)
- {
- string tbname = string.Empty;
- string rcode = string.Empty;
- if (record.scope != null && record.scope.Equals("school"))
- {
- rcode = $"LessonCount-{record.school}-{syear}-{record.periodId}";
- tbname = "School";
- }
- else
- {
- rcode = $"LessonCount-{syear}";
- tbname = "Teacher";
- }
- LessonCount count = new LessonCount
- {
- id = record.tmdid,
- code = rcode,
- ttl = -1
- };
- double[] da = new double[days];
- List<double> list = new(da);
- List<double> listT = new(da);
- List<double> listP = new(da);
- List<double> listPT = new(da);
- count.beginCount.AddRange(list);
- count.tCount.AddRange(listT);
- count.pCount.AddRange(listP);
- count.ptCount.AddRange(listPT);
- await client.GetContainer("TEAMModelOS", tbname).UpsertItemAsync(count, new PartitionKey(rcode));
- scount.Add(count);
- }
- }
- if (tyear > syear)
- {
- if (!string.IsNullOrEmpty(tId))
- {
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<LessonCount>(
- queryText: queryClass,
- requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonCount-{tyear}") }))
- {
- tcount.Add(item);
- }
- foreach (string pId in perId)
- {
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonCount>(
- queryText: queryClass,
- requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonCount-{code}-{tyear}-{pId}") }))
- {
- scount.Add(item);
- }
- }
- }
- else
- {
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonCount>(
- queryText: queryClass,
- requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonCount-{code}-{tyear}-{periodId}") }))
- {
- tcount.Add(item);
- }
- }
- }
- return (scount, tcount);
- }
- private async Task<List<(string time, double count)>> getRecordCount(CosmosClient client, List<LessonRecord> records, long stime, long etime, string code, string tId, string periodId)
- {
- List<(string time, double count)> counts = new();
- counts.Add(("total", records.Where(c => c.startTime >= stime && c.startTime <= etime).ToList().Count));
- var syear = DateTimeOffset.FromUnixTimeMilliseconds(stime).Year;
- //var eyear = DateTimeOffset.FromUnixTimeMilliseconds(etime).Year;
- var tyear = DateTimeOffset.UtcNow.Year;
- var tday = DateTimeOffset.UtcNow.DayOfYear;
- //求今年多少天
- int tdays = DateTimeHelper.getDays(tyear);
- //如果跨年 求前年多少天
- int pydays = DateTimeHelper.getDays(syear);
- (List<LessonCount> scount, List<LessonCount> tcount) = await getCount(client, records, syear, tyear, code, tId, periodId);
- DenseMatrix dense = null;
- //var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(syear.ToString(), new PartitionKey($"ClassCount-" + code));
- if (tyear > syear)
- {
- if (tcount.Count > 0)
- {
- List<List<double>> be = new();
- foreach (var item in tcount)
- {
- be.Add(item.beginCount);
- }
- dense = DenseMatrix.OfColumns(be);
- }
- }
- if (scount.Count > 0)
- {
- List<List<double>> begin = new List<List<double>>();
- foreach (LessonCount lesson in scount)
- {
- begin.Add(lesson.beginCount);
- }
- var matrix = DenseMatrix.OfColumns(begin);
- //求本周
- int sday = (int)DateTimeOffset.UtcNow.DayOfWeek;
- //本月
- var tmonth = DateTimeOffset.UtcNow.Day;
- //求本学期
- var sdays = DateTimeOffset.FromUnixTimeMilliseconds(stime).DayOfYear;
- if (tyear > syear)
- {
- //今日
- double tcounts = dense.Row(tday - 1).Sum();
- counts.Add(("today", tcounts));
- if (sday == 0)
- {
- sday = 7;
- }
- if (tday - sday < 0)
- {
- //var tmatrix = DenseMatrix.OfColumns(scount.beginCount);
- //新的一年不超过7天的值
- double tsum = 0;
- if (null != dense)
- {
- tsum = dense.SubMatrix(tday, tday, 0, dense.ColumnCount).ColumnSums().Sum();
- }
- //前一年余下的值
- var pysum = matrix.SubMatrix(pydays - (sday - tday) - 1, sday - tday + 1, 0, matrix.ColumnCount).ColumnSums().Sum();
- counts.Add(("week", tsum + pysum));
- }
- else
- {
- var subDay = dense.SubMatrix(tday - sday - 1, sday + 1, 0, dense.ColumnCount).ColumnSums().Sum();
- counts.Add(("week", subDay));
- }
- var subMonth = dense.SubMatrix(tday - tmonth - 1, tmonth + 1, 0, dense.ColumnCount).ColumnSums().Sum();
- counts.Add(("month", subMonth));
- //var tmatrix = DenseMatrix.OfColumns(scount.beginCount);
- //跨年后开始到本学期结束
- double endMonth = 0;
- if (null != dense)
- {
- endMonth = dense.SubMatrix(0, tday, 0, dense.ColumnCount).ColumnSums().Sum();
- }
- var startMonth = matrix.SubMatrix(sdays - 1, pydays - sdays, 0, matrix.ColumnCount).ColumnSums().Sum();
- counts.Add(("semester", endMonth + startMonth));
- }
- else
- {
- //今日
- double tcounts = matrix.Row(tday - 1).Sum();
- counts.Add(("today", tcounts));
- var subDay = matrix.SubMatrix(tday - sday - 1, sday + 1, 0, matrix.ColumnCount).ColumnSums().Sum();
- counts.Add(("week", subDay));
- var subMonth = matrix.SubMatrix(tday - tmonth - 1, tmonth + 1, 0, matrix.ColumnCount).ColumnSums().Sum();
- counts.Add(("month", subMonth));
- var allMonth = matrix.SubMatrix(sdays - 1, tday - sdays + 1, 0, matrix.ColumnCount).ColumnSums().Sum();
- counts.Add(("semester", allMonth));
- }
- //求本学期
- //var sdays = DateTimeOffset.FromUnixTimeMilliseconds(stime).DayOfYear;
- //var edays = DateTimeOffset.FromUnixTimeMilliseconds(etime).DayOfYear;
- /* //本月
- var tmonth = DateTimeOffset.UtcNow.Day;
- var subMonth = matrix.SubMatrix(tmonth - 1, tmonth + 1, 0, matrix.ColumnCount).ColumnSums().Sum();
- counts.Add(("month", subMonth));*/
- //求今年
- var subYear = matrix.SubMatrix(0, tdays, 0, matrix.ColumnCount).ColumnSums().Sum();
- }
- return counts;
- }
- //取得该学校当前学期所有评测活动进行分类计算
- private async Task<List<double>> getExamTypeCount(CosmosClient client, long stime, long etime, string code)
- {
- List<double> counts = new List<double>();
- try
- {
- List<(string id, string source, string scope)> ps = new List<(string id, string source, string scope)>();
- var queryClass = $"select c.id,c.source,c.scope from c where c.school = '{code}' and c.pk = 'Exam' and c.startTime >= {stime} and c.endTime <= {etime}";
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: queryClass))
- {
- using var json = await JsonDocument.ParseAsync(item.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
- while (accounts.MoveNext())
- {
- JsonElement account = accounts.Current;
- ps.Add((account.GetProperty("id").GetString(), account.GetProperty("source").GetString(), account.GetProperty("scope").GetString()));
- }
- break;
- }
- }
- var sc_online = ps.Where(x => !string.IsNullOrEmpty(x.source) && x.source.Equals("0") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("school")).ToList().Count;
- var p_online = ps.Where(x => !string.IsNullOrEmpty(x.source) && x.source.Equals("0") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("private")).ToList().Count;
- var sc_class = ps.Where(x => !string.IsNullOrEmpty(x.source) && x.source.Equals("1") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("school")).ToList().Count;
- var p_class = ps.Where(x => !string.IsNullOrEmpty(x.source) && x.source.Equals("1") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("private")).ToList().Count;
- var sc_mark = ps.Where(x => !string.IsNullOrEmpty(x.source) && x.source.Equals("2") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("school")).ToList().Count;
- var p_mark = ps.Where(x => !string.IsNullOrEmpty(x.source) && x.source.Equals("2") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("private")).ToList().Count;
- counts.Add(sc_online);
- counts.Add(sc_class);
- counts.Add(sc_mark);
- counts.Add(p_online);
- counts.Add(p_class);
- counts.Add(p_mark);
- return counts;
- }
- catch (Exception e)
- {
- return counts;
- }
- }
- [ProducesDefaultResponseType]
- [Authorize(Roles = "IES")]
- [AuthToken(Roles = "teacher,admin")]
- [HttpPost("settle-recod")]
- public async Task<IActionResult> settleRecod(JsonElement request)
- {
- //if (!request.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
- if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
- if (!request.TryGetProperty("periodId", out JsonElement periodId)) return BadRequest();
- if (!request.TryGetProperty("stime", out JsonElement stime)) return BadRequest();
- if (!request.TryGetProperty("etime", out JsonElement etime)) return BadRequest();
- try
- {
- var client = _azureCosmos.GetCosmosClient();
- List<LessonRecord> records = new();
- StringBuilder sql = new($"select c.periodId,c.tmdid,c.collateTaskCount,c.collateCount,c.clientInteractionCount,c.examQuizCount,c.scpoe from c where c.periodId = '{periodId}'");
- await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(
- queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord-{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())
- {
- records.Add(obj.ToObject<LessonRecord>());
- }
- }
- }
- if (records.Count > 0)
- {
- double total = records.Count;
- double teachCount = records.Where(r => r.tmdid != null).Where((x, i) => records.FindIndex(z => z.tmdid == x.tmdid) == i).ToList().Count;
- double taskCount = records.Select(c => c.collateTaskCount).Sum();
- double workCount = records.Select(c => c.collateCount).Sum();
- double examQuizCount = records.Select(c => c.examQuizCount).Sum();
- double interactCount = records.Select(c => c.clientInteractionCount).Sum();
- List<(string name, double count)> rc = await getRecordCount(client, records, stime.GetInt64(), etime.GetInt64(), code.GetString(), "", periodId.GetString());
- double semester = rc.Where(r => r.name.Equals("semester")).FirstOrDefault().count;
- return Ok(new { total, teachCount, taskCount, workCount, examQuizCount, interactCount, semester });
- }
- else
- {
- return Ok(new { total = 0, teachCount = 0, taskCount = 0, workCount = 0, examQuizCount = 0, interactCount = 0, semester = 0 });
- }
- }
- catch (Exception ex)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},class/analysis/settle-recod()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
- return Ok(new { code = 404, msg = ex.Message });
- }
- }
- private async Task<List<string>> getStudentsAsync(string pId, CosmosClient client, string pk, string source)
- {
- try
- {
- List<string> sIds = new();
- await foreach (var item in client.GetContainer("TEAMModelOS", source).GetItemQueryStreamIterator(queryText: $"select c.id from c where c.pk = '{pk}' and c.periodId = '{pId}'"))
- {
- using var json = await JsonDocument.ParseAsync(item.ContentStream);
- if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
- {
- var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
- while (accounts.MoveNext())
- {
- JsonElement account = accounts.Current;
- sIds.Add(account.GetProperty("id").GetString());
- }
- }
- }
- return sIds;
- }
- catch (Exception e)
- {
- await _dingDing.SendBotMsg($"OS,{_option.Location},area/get-students()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
- return new List<string>();
- }
- }
- }
- }
|