//-------------------------------------------------------------------- // 此代码由T4模板自动生成 byzhouhang 20210918 // 生成时间 2022-08-22 09:33:24 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 //-------------------------------------------------------------------- using IRaCIS.Core.Domain.Models; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using Panda.DynamicWebApi.Attributes; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infra.EFCore.Common; using Microsoft.Extensions.Caching.Memory; using IRaCIS.Core.Application.Service.Reading.Dto; namespace IRaCIS.Core.Application.Service { /// /// 阅片计算 /// [ApiExplorerSettings(GroupName = "Reading")] public class ReadingCalculateService : BaseService, IReadingCalculateService { private readonly IRepository _readingTableQuestionAnswerRepository; private readonly IRepository _visitTaskRepository; private readonly IRepository _readingQuestionCriterionTrialRepository; private readonly IRepository _readingTableQuestionTrialRepository; private readonly IRepository _readingQuestionTrialRepository; private readonly IRepository _subjectVisitRepository; private readonly IRepository _tumorAssessmentRepository; private readonly IRepository _readingTaskQuestionAnswerRepository; public ReadingCalculateService( IRepository readingTableQuestionAnswerRepository, IRepository visitTaskRepository, IRepository readingQuestionCriterionTrialRepository, IRepository readingTableQuestionTrialRepository, IRepository readingQuestionTrialRepository, IRepository subjectVisitRepository, IRepository tumorAssessmentRepository, IRepository readingTaskQuestionAnswerRepository ) { this._readingTableQuestionAnswerRepository = readingTableQuestionAnswerRepository; this._visitTaskRepository = visitTaskRepository; this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository; this._readingTableQuestionTrialRepository = readingTableQuestionTrialRepository; this._readingQuestionTrialRepository = readingQuestionTrialRepository; this._subjectVisitRepository = subjectVisitRepository; this._tumorAssessmentRepository = tumorAssessmentRepository; this._readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository; } #region 临时对象 单个请求的生命周期 避免重复查询数据库 private List visitTaskAnswerList; private decimal? sODData; #endregion /// /// 计算任务 /// /// /// [HttpPost] public async Task CalculateTask(CalculateTaskInDto inDto) { ReadingCalculateDto readingData = await GetReadingCalculateDto(inDto.VisitTaskId); readingData.IsChangeOtherTask = inDto.IsChangeOtherTask; await ReadingCalculate(readingData); } /// /// 自动计算 /// /// /// public async Task ReadingCalculate(ReadingCalculateDto inDto) { // 找到所有访视任务的Id var visitTaskIds = await _visitTaskRepository.Where(x => !x.IsAnalysisCreate && x.ReadingCategory == ReadingCategory.Visit && x.TaskState == TaskState.Effect && x.ReadingTaskState == ReadingTaskState.HaveSigned && x.DoctorUserId == inDto.DoctorUserId).Select(x => x.Id).ToListAsync(); #region 计算 这里顺序非常重要 后面计算的值要依赖前面计算的结果 var needAddList = new List(); // 循环找要计算的值进行计算 foreach (var item in inDto.QuestionInfo.Where(x => x.QuestionType != null)) { switch (item.QuestionType) { // 靶病灶径线之和(SOD) case QuestionType.SOD: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = (await GetSODData(inDto)).ToString(), ReadingQuestionTrialId = item.QuestionId, }); break; // 非淋巴结靶病灶长径之和 case QuestionType.SumOfDiameter: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = (await GetSumOfDiameter(inDto)).ToString(), ReadingQuestionTrialId = item.QuestionId, }); break; // 与基线SOD相比变化量(mm) case QuestionType.SODChange: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = (await GetSODChange(inDto)).ToString(), ReadingQuestionTrialId = item.QuestionId, }); break; // 与基线访视相比SOD变化百分比 case QuestionType.SODPercent: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = (await GetSODPercent(inDto)).ToString(), ReadingQuestionTrialId = item.QuestionId, }); break; // 与整个访视期间最低点相比增加的值(mm) 其他任务需要改 case QuestionType.LowestIncrease: if (!inDto.IsChangeOtherTask) { needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = (await GetLowestIncrease(inDto)).ToString(), ReadingQuestionTrialId = item.QuestionId, }); } else { await ChangeAllLowestIncrease(new ChangeAllTaskDto() { calculateDto = inDto, QuestionId = item.QuestionId, }); } break; // 与整个访视期间最低点相比增加的百分比 其他任务需要改 case QuestionType.LowPercent: if (!inDto.IsChangeOtherTask) { needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = (await GetLowPercent(inDto)).ToString(), ReadingQuestionTrialId = item.QuestionId, }); } else { await ChangeAllLowPercent(inDto, item.QuestionId); } break; // 整个访视期间最低点访视名称 其他任务需要改 case QuestionType.LowVisit: var answer = (await GetLowVisit(inDto)).ToString(); if (!inDto.IsChangeOtherTask) { needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = answer, ReadingQuestionTrialId = item.QuestionId, }); } else { if (inDto.IsChangeOtherTask) { await this.ChangeAllVisitTaskAnswer(visitTaskIds, item.QuestionId, answer); } } break; // 是否存在非淋巴结靶病灶 case QuestionType.IsLymphTarget: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = await GetIsLymphTarget(inDto), ReadingQuestionTrialId = item.QuestionId, }); break; // 是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上 case QuestionType.IsAddFive: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = await GetIsAddFive(inDto), ReadingQuestionTrialId = item.QuestionId, }); break; // 被评估为NE的单个靶病灶 case QuestionType.NETarget: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = await GetNETarget(inDto), ReadingQuestionTrialId = item.QuestionId, }); break; // 整体肿瘤评估 case QuestionType.Tumor: needAddList.Add(new ReadingTaskQuestionAnswer() { Answer = await GetTumor(inDto), ReadingQuestionTrialId = item.QuestionId, }); break; } } var questionIds = needAddList.Select(x => x.ReadingQuestionTrialId).ToList(); await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => questionIds.Contains(x.ReadingQuestionTrialId) && x.VisitTaskId == inDto.VisitTaskId); needAddList.ForEach(x => { x.SubjectId = inDto.SubjectId; x.ReadingQuestionCriterionTrialId = inDto.CriterionId; x.VisitTaskId = inDto.VisitTaskId; x.TrialId = inDto.TrialId; x.SubjectId = inDto.SubjectId; }); await _readingTaskQuestionAnswerRepository.AddRangeAsync(needAddList); await _readingTaskQuestionAnswerRepository.SaveChangesAsync(); #endregion } /// /// 验证访视提交 /// /// /// public async Task VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto) { await this.CalculateTask(new CalculateTaskInDto() { VisitTaskId = inDto.VisitTaskId, IsChangeOtherTask = true }); visitTaskAnswerList = null; ReadingCalculateDto data = await GetReadingCalculateDto(inDto.VisitTaskId); VerifyVisitTaskQuestionsOutDto result = new VerifyVisitTaskQuestionsOutDto() { IsVerified=true, ErrorMessage=string.Empty, }; List types = new List() { new VerifyVisitTaskDto (){ QuestionType=QuestionType.TargetLesion,Fun=this.GetTargetLesionEvaluate }, new VerifyVisitTaskDto (){ QuestionType=QuestionType.NoTargetLesion,Fun=this.GetNoTargetLesionEvaluate }, new VerifyVisitTaskDto (){ QuestionType=QuestionType.NewLesions,Fun=this.GetNewLesionEvaluate } }; foreach (var type in types) { var question=data.QuestionInfo.Where(x => x.QuestionType == type.QuestionType).FirstOrDefault(); if (question != null) { var calculateAnswer = await type.Fun(data); if (question.Answer != calculateAnswer) { result.IsVerified = false; var msg = $"问题【{question.QuesionName}】的答案为【{question.Answer}】但是计算答案为【{calculateAnswer}】"; result.ErrorMessage += result.ErrorMessage == string.Empty ? msg : "," + msg; } } } return result; } /// /// 获取ReadingCalculateDto /// /// /// public async Task GetReadingCalculateDto(Guid visitTaskId) { var visitTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync(); var criterionId = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == visitTask.TrialId && x.IsConfirm).Select(x => x.Id).FirstOrDefaultAsync(); List questionInfos = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == criterionId).Select(x => new QuestionInfo() { LesionType = x.LesionType, QuestionId = x.Id, QuesionName=x.QuestionName, QuestionType = x.QuestionType, }).ToListAsync(); var questionAnswers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Select(x => new { x.ReadingQuestionTrialId, x.Answer }).ToListAsync(); var tableQuestion = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Include(x => x.ReadingTableQuestionTrial).Select(x => new TableQuestionInfo() { Answer = x.Answer, QuestionMark = x.ReadingTableQuestionTrial.QuestionMark, TableQuestionId = x.TableQuestionId, QuestionId = x.QuestionId, RowIndex = x.RowIndex, }).ToListAsync(); foreach (var item in questionInfos) { item.Answer = questionAnswers.Where(y => y.ReadingQuestionTrialId == item.QuestionId).Select(x => x.Answer).FirstOrDefault() ?? string.Empty; var thisItemTableQuestions = tableQuestion.Where(x => x.QuestionId == item.QuestionId).ToList(); item.TableRowInfoList = thisItemTableQuestions.GroupBy(x => new { x.RowIndex }) .Select(g => new TableRowInfo() { RowIndex = g.Key.RowIndex, TableQuestionList = g.ToList() }).ToList(); } ReadingCalculateDto readingData = new ReadingCalculateDto() { SubjectId = visitTask.SubjectId, VisitTaskId = visitTaskId, SubjectVisitId = visitTask.SourceSubjectVisitId.Value, QuestionInfo = questionInfos, CriterionId = criterionId, TrialId = visitTask.TrialId, DoctorUserId = visitTask.DoctorUserId, }; return readingData; } #region 获取SOD /// /// 获取SOD /// /// /// 靶病灶径线之和(SOD) /// 非淋巴结的长径 和淋巴结的短径 /// /// public async Task GetSODData(ReadingCalculateDto inDto) { if (sODData != null) { return sODData.Value; } var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); decimal result = 0; foreach (var item in tableQuestion) { if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && (x.Answer == "是"||x.Answer.ToLower()=="true".ToLower()))) { // 淋巴结的短径 result += (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0(); } if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && (x.Answer == "是" || x.Answer.ToLower() == "true".ToLower()))) { // 非淋巴结的长径 result += item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); } } sODData = result; return sODData.Value; } #endregion #region 非淋巴结靶病灶长径之和 /// /// 非淋巴结靶病灶长径之和 /// /// /// public async Task GetSumOfDiameter(ReadingCalculateDto inDto) { var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); decimal result = 0; foreach (var item in tableQuestion) { if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && (x.Answer == "是" || x.Answer.ToLower() == "false".ToLower()))) { // 非淋巴结的长径 result += item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); } } return result; } #endregion #region 与基线SOD相比变化量(mm) /// /// 与基线SOD相比变化量(mm) /// /// /// public async Task GetSODChange(ReadingCalculateDto inDto) { return await GetSODData(inDto) - await GetBaseLineSOD(inDto); } #endregion #region 与整个访视期间最低点相比增加的百分比 /// /// 与整个访视期间最低点相比增加的百分比 /// /// /// public async Task GetSODPercent(ReadingCalculateDto inDto) { var thisSOD = await GetSODData(inDto); var baseLineSOD = await GetBaseLineSOD(inDto); if (baseLineSOD == 0) { return 100; } else { return decimal.Round(thisSOD * 100 / baseLineSOD, 2); } } #endregion #region 与整个访视期间最低点相比增加的值(mm) /// /// 与整个访视期间最低点相比增加的值(mm) /// /// /// /// 要更新之前的 /// /// public async Task GetLowestIncrease(ReadingCalculateDto inDto) { var decimalAnswerList = await GetVisitTaskAnswerList(inDto); var minSOD = decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.SOD).FirstOrDefault(); return await GetSODData(inDto) - minSOD; } #endregion #region 与整个访视期间最低点相比增加的百分比 /// /// 与整个访视期间最低点相比增加的百分比 /// /// /// /// 要更新之前的 /// /// public async Task GetLowPercent(ReadingCalculateDto inDto) { var thisSOD = await GetSODData(inDto); var decimalAnswerList = await GetVisitTaskAnswerList(inDto); var minSOD = decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.SOD).FirstOrDefault(); if (minSOD == 0) { return 100; } else { return decimal.Round((thisSOD- minSOD) * 100 / minSOD, 2); } } #endregion #region 整个访视期间最低点访视名称 /// /// 整个访视期间最低点访视名称 /// /// /// /// 要更新之前的 /// /// public async Task GetLowVisit(ReadingCalculateDto inDto) { var decimalAnswerList = await GetVisitTaskAnswerList(inDto); return decimalAnswerList.OrderBy(x => x.SOD).Select(x => x.VisitName).FirstOrDefault() ?? string.Empty; } #endregion #region 是否存在非淋巴结靶病灶 /// /// 是否存在非淋巴结靶病灶 /// /// /// public async Task GetIsLymphTarget(ReadingCalculateDto inDto) { var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); foreach (var item in tableQuestion) { if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && (x.Answer == "是" || x.Answer.ToLower() == "true".ToLower()))) { return "是"; } } return "否"; } #endregion #region 是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上 /// /// 是否存在淋巴结靶病灶且该病灶比上一访视短径增加5MM以上 /// /// /// public async Task GetIsAddFive(ReadingCalculateDto inDto) { var LastVisitTaskId = await this.GetLastVisitTaskId(inDto); var questionIds = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).Select(x => x.QuestionId).ToList(); var lastQuestionAsnwer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == LastVisitTaskId && questionIds.Contains(x.QuestionId)).Include(x=>x.ReadingQuestionTrial).Include(x => x.ReadingTableQuestionTrial).ToListAsync(); var rowIndexs = lastQuestionAsnwer.Where(x=>x.ReadingTableQuestionTrial.QuestionMark==QuestionMark.IsLymph&& (x.Answer == "是" || x.Answer.ToLower() == "true".ToLower())).Select(x => x.RowIndex).Distinct().OrderBy(x => x).ToList(); var thisQuestionAsnwer = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); var isExists = false; foreach (var item in rowIndexs) { var lastValue = lastQuestionAsnwer.Where(x => x.RowIndex == item && x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); var thisRowData = thisQuestionAsnwer.Where(x => x.RowIndex == item).SelectMany(x => x.TableQuestionList).ToList(); var thisValue = thisRowData.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0(); if (thisValue - lastValue > 5) { isExists = true; } } return isExists?"是":"否"; } #endregion #region 被评估为NE的单个靶病灶 /// /// 被评估为NE的单个靶病灶 /// /// /// public async Task GetNETarget(ReadingCalculateDto inDto) { var result = inDto.QuestionInfo.Any(x => x.QuestionType == QuestionType.TargetLesion && x.Answer == "NE"); return result ? "有" : "无"; } #endregion #region 整体肿瘤评估 /// /// 整体肿瘤评估 /// /// /// public async Task GetTumor(ReadingCalculateDto inDto) { var targetLesion = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.TargetLesion).Select(x => x.Answer).FirstOrDefault(); var noTargetLesion = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NoTargetLesion).Select(x => x.Answer).FirstOrDefault(); var newLesions = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesions).Select(x => x.Answer).FirstOrDefault(); var result = await _tumorAssessmentRepository.Where(x => x.TargetLesion == targetLesion && x.NonTargetLesions == noTargetLesion && x.NewLesion == newLesions).Select(x => x.OverallEfficacy).FirstOrDefaultAsync(); return result ?? string.Empty; } #endregion #region 修改其他标准 #region 修改与整个访视期间最低点相比增加的值(mm) /// /// 修改与整个访视期间最低点相比增加的值(mm) /// /// /// /// public async Task ChangeAllLowestIncrease(ChangeAllTaskDto inDto) { var visitTaskList = await GetVisitTaskAnswerList(inDto.calculateDto); var lowSod = visitTaskList.Select(x => x.SOD).OrderBy(x => x).FirstOrDefault(); foreach (var item in visitTaskList) { await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == inDto.QuestionId, x => new ReadingTaskQuestionAnswer() { Answer = (item.SOD - lowSod).ToString() }) ; } } #endregion #region 修改整个访视期间最低点相比增加的百分比 /// /// 修改整个访视期间最低点相比增加的百分比 /// /// /// /// public async Task ChangeAllLowPercent(ReadingCalculateDto inDto, Guid questionId) { var visitTaskList = await GetVisitTaskAnswerList(inDto); var lowSod = visitTaskList.Select(x => x.SOD).OrderBy(x => x).FirstOrDefault(); foreach (var item in visitTaskList) { decimal percent = 0; if (lowSod == 0) { percent= 100; } else { percent= decimal.Round((item.SOD - lowSod) * 100 / lowSod, 2); } await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == item.VisitTaskId && x.ReadingQuestionTrialId == questionId, x => new ReadingTaskQuestionAnswer() { Answer = percent.ToString() }); } } #endregion #endregion #region 通用方法 #region 修改所有访视任务的答案 /// /// 修改所有访视任务的答案 /// /// /// /// /// private async Task ChangeAllVisitTaskAnswer(List visitTaskGuids, Guid questionId, string answer) { await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => visitTaskGuids.Contains(x.VisitTaskId) && x.ReadingQuestionTrialId == questionId, x => new ReadingTaskQuestionAnswer() { Answer = answer }); } #endregion #region 获取基线SOD /// /// 获取基线SOD /// /// /// private async Task GetBaseLineSOD(ReadingCalculateDto inDto) { if (await _visitTaskRepository.AnyAsync(x => x.Id == inDto.VisitTaskId && x.SourceSubjectVisit.IsBaseLine&&!x.IsAnalysisCreate&&x.DoctorUserId==inDto.DoctorUserId)) { return 0; } // 先找到基线的任务 var baseLineTaskId = await _visitTaskRepository.Where(x => x.SubjectId == inDto.SubjectId && x.ReadingCategory == ReadingCategory.Visit && x.SourceSubjectVisit.IsBaseLine && x.TaskState == TaskState.Effect&&!x.IsAnalysisCreate&&x.DoctorUserId==inDto.DoctorUserId) .Select(x => x.Id).FirstOrDefaultAsync(); var baseLineSOD =(await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == baseLineTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD).Select(x => x.Answer).FirstOrDefaultAsync()).IsNullOrEmptyReturn0(); return baseLineSOD; } #endregion #region 获取访视任务信息 /// /// 获取访视任务信息 /// /// /// public async Task> GetVisitTaskAnswerList(ReadingCalculateDto inDto) { if (visitTaskAnswerList == null) { visitTaskAnswerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTask.ReadingCategory == ReadingCategory.Visit && x.SubjectId == inDto.SubjectId && x.VisitTask.ReadingTaskState == ReadingTaskState.HaveSigned && x.VisitTask.TaskState == TaskState.Effect && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD) .Select(x => new VisitTaskAnswerInfo { VisitTaskId = x.VisitTaskId, QuestionId = x.ReadingQuestionTrialId, VisitName = x.VisitTask.SourceSubjectVisit.VisitName, SOD = x.Answer.IsNullOrEmptyReturn0(), }).ToListAsync(); } return visitTaskAnswerList; } #endregion /// /// 获取上一个访视任务Id /// /// private async Task GetLastVisitTaskId(ReadingCalculateDto inDto) { // 拿到这一个访视 var thisNum = await _subjectVisitRepository.Where(x => x.Id == inDto.SubjectVisitId).Select(x => x.VisitNum).FirstOrDefaultAsync(); // 先找到上一个访视 var lastVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == inDto.SubjectId && x.VisitNum < thisNum).OrderByDescending(x => x.VisitNum).Select(x => x.Id).FirstOrDefaultAsync(); // 找到访视任务Id var LastVisitTaskId = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Visit && x.TaskState == TaskState.Effect && !x.IsAnalysisCreate && x.SourceSubjectVisitId == lastVisitId&&x.DoctorUserId==inDto.DoctorUserId).Select(x => x.Id).FirstOrDefaultAsync(); return LastVisitTaskId; } #endregion #region 计算阅片问题 外层问题 #region 获取靶病灶评估 /// /// 获取靶病灶评估 /// /// /// public async Task GetTargetLesionEvaluate(ReadingCalculateDto inDto) { var tableQuestion = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.TargetLesion).SelectMany(x => x.TableRowInfoList).ToList(); TargetLesionCalculateDto resultData = new TargetLesionCalculateDto() { //非淋巴结靶病灶长径之和 decimal SumOfDiameter = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SumOfDiameter).Sum(x => x.Answer.IsNullOrEmptyReturn0()), //所有淋巴结靶病灶的短径小于10mm bool DiameterLessThan10 = true, // SOD 百分比与基线期SOD相比减小≥30% bool SODPercentBigger30 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SODPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) >= (decimal)0.3, // SOD 百分比 与基线期SOD相比减小<30% bool SODPercentLess30 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SODPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) < (decimal)0.3, // SOD 百分比 整体访视期间最低点SOD相比增加<20% LowPercentLess20 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) < (decimal)0.2, // SOD 百分比 比整体访视期间最低点SOD增加≥20% LowPercentBigger20 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowPercent).Sum(x => x.Answer.IsNullOrEmptyReturn0()) >= (decimal)0.2, // SOD 变化值 比整体访视期间最低点SOD绝对增加值<5 mm LowChangeLess5 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowestIncrease).Sum(x => x.Answer.IsNullOrEmptyReturn0()) < 5, // 比整体访视期间最低点SOD绝对增加值≥5 mm LowChangeBigger5 = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.LowestIncrease).Sum(x => x.Answer.IsNullOrEmptyReturn0()) >= 5, // 被评估为NE的单个靶病灶 是否存在状态为不可评估的靶病灶 ExixtsNETargetLesion = tableQuestion.SelectMany(x => x.TableQuestionList).Any(x => x.QuestionMark == QuestionMark.State && x.Answer == "不可评估"), //// 上次访视点整体肿瘤评估 LastTargetLesionEvaluate = string.Empty, // 当前访视点非淋巴结病灶长径>0 CurrentMajoreBigger0 = true, // 至少一个淋巴结靶病灶短径≥10 mm CurrenShortBigger10 = true, // 该淋巴结靶病灶短径绝对增加值≥5 mm IsAddFive = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.IsAddFive && x.Answer == "是").Count() > 0, }; foreach (var item in tableQuestion) { if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && (x.Answer == "是" || x.Answer.ToLower() == "true".ToLower()))) { // 淋巴结的短径 resultData.DiameterLessThan10 = (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0() < 10; // 至少一个淋巴结靶病灶短径≥10 mm resultData.CurrenShortBigger10 = (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0() >= 10; } if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && (x.Answer == "否" || x.Answer.ToLower() == "false".ToLower()))) { // 当前访视点非淋巴结病灶 resultData.CurrentMajoreBigger0 = (item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault()).IsNullOrEmptyReturn0() > 0; } } var lastVisitTaskId = await GetLastVisitTaskId(inDto); var questionId = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.Tumor).Select(x => x.QuestionId).FirstOrDefault(); resultData.LastTargetLesionEvaluate=(await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastVisitTaskId && x.ReadingQuestionTrialId == questionId) .Select(x => x.Answer).FirstOrDefaultAsync()) ?? string.Empty; string result = string.Empty; if (resultData.SumOfDiameter == 0 && resultData.DiameterLessThan10 && !resultData.ExixtsNETargetLesion) { result = "CR"; } else if ( (resultData.SODPercentBigger30 && resultData.LowPercentLess20 && !resultData.ExixtsNETargetLesion) || (resultData.SODPercentBigger30 && resultData.LowChangeLess5 && !resultData.ExixtsNETargetLesion) ) { result = "PR"; } else if ( (resultData.SODPercentLess30 && resultData.LowPercentLess20 && !resultData.ExixtsNETargetLesion) || (resultData.SODPercentLess30 && resultData.LowChangeLess5 && !resultData.ExixtsNETargetLesion) ) { result = "SD"; } else if (resultData.LowPercentBigger20 && resultData.LowChangeBigger5) { result = "PD"; } else if ( (resultData.LowPercentLess20 && resultData.ExixtsNETargetLesion) || (resultData.LowPercentBigger20 && resultData.LowChangeLess5 && resultData.ExixtsNETargetLesion) ) { result = "NE"; } else if (!resultData.ExixtsNETargetLesion) { result = "ND"; } else if ( (resultData.LastTargetLesionEvaluate == "CR" && resultData.CurrenShortBigger10 && resultData.IsAddFive) || (resultData.LastTargetLesionEvaluate == "CR" && resultData.CurrentMajoreBigger0) ) { result = "PD"; } return result; } #endregion #region 获取非靶病灶评估 /// /// 获取非靶病灶评估 /// /// /// public async Task GetNoTargetLesionEvaluate(ReadingCalculateDto inDto) { var tableRows = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.NonTargetLesions).SelectMany(x => x.TableRowInfoList).ToList(); var tableQuestions = tableRows.SelectMany(x => x.TableQuestionList).ToList(); //任意单个病灶 / 病灶组评估为“显著增大” if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer == "显著增大")) { return "PD"; } //所有单个病灶/病灶组状态评估状态为“消失” else if (!tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer != "消失")) { return "PD"; } // 任意单个病灶/病灶组评估为“无法评估”并且没有“显著增大” else if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer == "无法评估") && !tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer != "显著增大") ) { return "NE"; } // 基线时没有非靶病灶 else if (tableQuestions.Count() == 0) { return "ND"; } // 所有单个病灶/病灶组评估为”存在”或者有些评估为“消失”有些评估为“存在”,且没有“显著增大”和“无法评估”的病灶 else if (!tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer != "存在") || (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer == "存在" || x.Answer == "消失") && !tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && (x.Answer != "显著增大" || x.Answer != "无法评估"))) ) { return "NN"; } else { return string.Empty; } } #endregion #region 获取新病灶评估 /// /// 获取新病灶评估 /// /// /// public async Task GetNewLesionEvaluate(ReadingCalculateDto inDto) { var tableRows = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.NewLesions).SelectMany(x => x.TableRowInfoList).ToList(); var tableQuestions = tableRows.SelectMany(x => x.TableQuestionList).ToList(); // 当前访视存在至少一个明确新病灶 if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer == "明确")) { return "是"; } //当前访视不存在明确新病灶且存在至少一个疑似新病灶 else if (!tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer != "明确") || tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer == "疑似") ) { return "疑似"; } //只要有任何一个新病灶状态为“无法评估” else if (tableQuestions.Any(x => x.QuestionMark == QuestionMark.State && x.Answer == "无法评估")) { return "NE"; } else { return "否"; } } #endregion #endregion } }