修改PCWG计算

Test_HIR_Net8
he 2025-09-18 10:00:41 +08:00
parent e6f91b9c4b
commit d1ae500735
4 changed files with 187 additions and 50 deletions

View File

@ -4847,11 +4847,26 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.PCWG3CalculateService.ChangeLastTaskSiteVisitForTumorEvaluation(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.PCWG3CalculateService.GetSiteVisitForTumorEvaluationByDay(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto,System.Nullable{System.Int32})">
<summary>
获取肿瘤评估 逻辑抽离
</summary>
<param name="inDto"></param>
<param name="daysBetween"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.PCWG3CalculateService.FrontGetSiteVisitForTumorEvaluation(IRaCIS.Core.Application.Service.Reading.Dto.FrontGetSiteVisitForTumorEvaluationInDto)">
<summary>
前端获取访视点肿瘤评估
</summary>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.PCWG3CalculateService.ChangeLastTaskSiteVisitForTumorEvaluation(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto,System.Nullable{System.Int32})">
<summary>
修改上一次访视结果 并且计算是不是PD
</summary>
<param name="inDto"></param>
<param name="numOfDaysBetween"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingCalculate.PCWG3CalculateService.GetSiteVisitForTumorList(IRaCIS.Core.Application.Service.Reading.Dto.ReadingCalculateDto)">

View File

@ -319,7 +319,11 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
}
public class FrontGetSiteVisitForTumorEvaluationInDto
{
public Guid VisitTaskId { get; set; }
public int NumberOfDaysBetween { get; set; }
}
/// <summary>
@ -399,6 +403,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
/// </summary>
public string Answer { get; set; }
public string PCWGInterimAnswer { get; set; }
/// <summary>
/// 问题名称
/// </summary>

View File

@ -207,7 +207,8 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
var questionAnswers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Select(x => new
{
x.ReadingQuestionTrialId,
x.Answer
x.Answer,
x.PCWGInterimAnswer,
}).ToListAsync();
var tableQuestion = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Include(x => x.ReadingTableQuestionTrial).Select(x => new TableQuestionInfo()
@ -226,7 +227,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
item.Answer = questionAnswers.Where(y => y.ReadingQuestionTrialId == item.QuestionId).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
item.PCWGInterimAnswer = questionAnswers.Where(y => y.ReadingQuestionTrialId == item.QuestionId).Select(x => x.PCWGInterimAnswer).FirstOrDefault() ?? string.Empty;
var thisItemRowInfo = rowInfoList.Where(x => x.QuestionId == item.QuestionId).ToList();
var thisItemTableQuestions = tableQuestion.Where(x => x.QuestionId == item.QuestionId).ToList();

View File

@ -1,8 +1,10 @@
using IRaCIS.Application.Contracts;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
@ -12,6 +14,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MiniSoftware;
using NPOI.SS.Formula.Functions;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
@ -753,6 +756,14 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
public async Task TestCalculate(Guid visitTaskId, QuestionType type)
{
ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(visitTaskId);
// 只获取当前的 不会获取上一次临时修改的结果
foreach (var item in readingData.QuestionInfo)
{
if (item.PCWGInterimAnswer != string.Empty)
{
item.Answer = item.PCWGInterimAnswer;
}
}
await ReadingCalculate(readingData, new List<QuestionType>() { type });
}
@ -765,6 +776,14 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
public async Task CalculateTask(CalculateTaskInDto inDto)
{
ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId);
// 只获取当前的 不会获取上一次临时修改的结果
foreach (var item in readingData.QuestionInfo)
{
if (item.PCWGInterimAnswer != string.Empty)
{
item.Answer = item.PCWGInterimAnswer;
}
}
readingData.IsChangeOtherTask = inDto.IsChangeOtherTask;
await ReadingCalculate(readingData);
}
@ -1049,6 +1068,14 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
return -1;
}
// 这里的answer可能是临时结果了 有的话就不计算了
var daysBetween = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.DaysBetween).Select(x => x.Answer).FirstIsNullReturnEmpty();
if (daysBetween!=string.Empty)
{
return int.Parse(daysBetween);
}
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var taskList = await GetSiteVisitForTumorList(inDto);
var lastTask = taskList.Where(x => x.VisitTaskNum < taskinfo.VisitTaskNum && x.VisitTaskId != inDto.VisitTaskId).OrderByDescending(x => x.VisitTaskNum).FirstOrDefault();
@ -1083,6 +1110,17 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<string> GetSiteVisitForTumorEvaluation(ReadingCalculateDto inDto)
{
return await GetSiteVisitForTumorEvaluationByDay(inDto);
}
/// <summary>
/// 获取肿瘤评估 逻辑抽离
/// </summary>
/// <param name="inDto"></param>
/// <param name="daysBetween"></param>
/// <returns></returns>
public async Task<string> GetSiteVisitForTumorEvaluationByDay(ReadingCalculateDto inDto, int? daysBetween = null)
{
if (inDto.IsBaseLine)
{
@ -1099,7 +1137,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
//影像质量不正常
return VisitTumorEvaluation.NE.GetEnumInt();
}
var isPD = await ChangeLastTaskSiteVisitForTumorEvaluation(inDto);
var isPD = await ChangeLastTaskSiteVisitForTumorEvaluation(inDto, daysBetween);
var newLesionsCount = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesionsCount).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();
var baseLineLesionsCount = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.BaseLineLesionsCount).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();
var alwaysNewLesionsCount = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.AlwaysNewLesionsCount).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();
@ -1120,19 +1158,40 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
}
}
/// <summary>
/// 前端获取访视点肿瘤评估
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<string> FrontGetSiteVisitForTumorEvaluation(FrontGetSiteVisitForTumorEvaluationInDto inDto)
{
ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId);
// 只获取当前的 不会获取上一次临时修改的结果
foreach (var item in readingData.QuestionInfo)
{
if (item.PCWGInterimAnswer != string.Empty)
{
item.Answer = item.PCWGInterimAnswer;
}
}
return await GetSiteVisitForTumorEvaluationByDay(readingData, inDto.NumberOfDaysBetween);
}
/// <summary>
/// 修改上一次访视结果 并且计算是不是PD
/// </summary>
/// <param name="inDto"></param>
/// <param name="numOfDaysBetween"></param>
/// <returns></returns>
public async Task<bool> ChangeLastTaskSiteVisitForTumorEvaluation(ReadingCalculateDto inDto)
public async Task<bool> ChangeLastTaskSiteVisitForTumorEvaluation(ReadingCalculateDto inDto, int? numOfDaysBetween)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
var taskList = await GetSiteVisitForTumorList(inDto);
var lastTask = taskList.Where(x => x.VisitTaskNum < taskinfo.VisitTaskNum && x.VisitTaskId != inDto.VisitTaskId).OrderByDescending(x => x.VisitTaskNum).FirstOrDefault();
var baseLineTask = taskList.OrderBy(x => x.VisitTaskNum).FirstOrDefault();
var newLesionsCountQuestionId = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesionsCount).Select(x => x.QuestionId).FirstOrDefault();
var isPDResult = false;
@ -1142,62 +1201,118 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
// 查看历史有没有PD
var taskIdList = taskList.Select(x => x.VisitTaskId).ToList();
var pdTaskList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId!=inDto.VisitTaskId&& taskIdList.Contains(x.VisitTaskId) && x.ReadingQuestionTrial.QuestionType == QuestionType.SiteVisitForTumorEvaluation && x.Answer == VisitTumorEvaluation.PD.GetEnumInt()).OrderByDescending(x=>x.VisitTask.VisitTaskNum).ToListAsync();
// pd的任务列表
var pdTaskList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId != inDto.VisitTaskId && taskIdList.Contains(x.VisitTaskId) && x.ReadingQuestionTrial.QuestionType == QuestionType.SiteVisitForTumorEvaluation && x.Answer == VisitTumorEvaluation.PD.GetEnumInt()).OrderByDescending(x => x.VisitTask.VisitTaskNum).ToListAsync();
// 自治疗后第二个访视点以来持续的新骨变数量
var thisNewBoneLesionsCount = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewBoneLesionsCount).Select(x => x.Answer).FirstIsNullReturnEmpty().IsNullOrEmptyReturn0();
// 当前任务的BL-BTN
var thisBTN = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.BaseLineLesionsCount).Select(x => x.Answer).FirstIsNullReturnEmpty().IsNullOrEmptyReturn0();
// 当前访视新病灶数量
var thisNewLesionsCount = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesionsCount).Select(x => x.Answer).FirstOrDefault().IsNullOrEmptyReturn0();
var thisNewLesionsCount = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.NewLesionsCount).Select(x => x.Answer).FirstIsNullReturnEmpty().IsNullOrEmptyReturn0();
// 其他访视的BTN
var otherBTNStrList =await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId != inDto.VisitTaskId && taskIdList.Contains(x.VisitTaskId) && x.ReadingQuestionTrial.QuestionType == QuestionType.BaseLineLesionsCount).Select(x=>new {
x.VisitTask.VisitTaskNum,
x.Answer,
}).ToListAsync();
// 最小的BTN 这个时候再转为int 避免查询报错
var othenMinBTNCount= otherBTNStrList.Select(x => x.Answer.IsNullOrEmptyReturn0()).Min();
// 历史有PD
if (pdTaskList.Count() > 0&& thisNewLesionsCount >= 2)
if (pdTaskList.Count() > 0)
{
// 满足以下所有条件:1、前序访视已经确定为PD;2、当前访视新病灶≥2个;
isPDResult = true;
}
else
{
// 满足以下所有条件:1、前序访视没有评估为PD2、前一个访视:新病灶计数≥2个;3、当前访视:新病灶2个:4.前后2个访视间隔6周以上。
var lastStudyDate = taskList.Where(x=>x.VisitTaskId==lastTask.VisitTaskId).Select(x=>x.StudyTime).FirstOrDefault();
var thisStudyDate= taskList.Where(x => x.VisitTaskId == inDto.VisitTaskId).Select(x => x.StudyTime).FirstOrDefault();
var lastNewLesionsStr=await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTask.VisitTaskId && x.ReadingQuestionTrialId == newLesionsCountQuestionId).Select(x => x.Answer).FirstOrDefaultAsync();
var lastNewLesionsCount = lastNewLesionsStr.IsNullOrEmptyReturn0();
if (lastStudyDate != null && thisStudyDate != null)
// 当前访视:自治疗后第二个访视点以来持续的新骨变数量 + [(V3 - BTN - MinV2 - BTN、V1 - BTN、BL - BTN] + 新病灶 >= 2
if (thisNewBoneLesionsCount + thisBTN - othenMinBTNCount + thisNewLesionsCount >= 2)
{
if (lastNewLesionsCount >= 2 && thisNewLesionsCount >= 2 && thisStudyDate.Value > lastStudyDate.Value.AddDays(42))
isPDResult = true;
}
}
else
{
// 间隔天数
var daysBetween = numOfDaysBetween != null ? numOfDaysBetween.Value : await GetNumberOfDaysBetween(inDto);
// 上一次访视的新病灶数量
var lastNewLesionsCount = (await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTask.VisitTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.NewLesionsCount).Select(x => x.Answer).FirstOrDefaultAsync()).IsNullOrEmptyReturn0();
// 之前不存在pd 又分为两种情况 在访视2 和 访视2以后
if (inDto.VisitTaskNum == 2)
{
// V1新病灶计数>=2; V2新病灶计数 >= 2; V2与V1的间隔 >= 6周
if (lastNewLesionsCount >= 2 && thisNewLesionsCount >= 2 && daysBetween >= 42)
{
var visitForTumorEvaluationQuestionId = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SiteVisitForTumorEvaluation).Select(x => x.QuestionId).FirstOrDefault();
await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == lastTask.VisitTaskId && x.ReadingQuestionTrialId == visitForTumorEvaluationQuestionId, x => new ReadingTaskQuestionAnswer
{
PCWGInterimAnswer = VisitTumorEvaluation.PD.GetEnumInt(),
});
isPDResult = true;
}
}
}
}
if (!isPDResult)
{
if (lastTask != null)
{
// 如果不是PD 需要把上一次的PD改为NoPD
var visitForTumorEvaluationQuestionId = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SiteVisitForTumorEvaluation).Select(x => x.QuestionId).FirstOrDefault();
var lastAnswer = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTask.VisitTaskId && x.ReadingQuestionTrialId == visitForTumorEvaluationQuestionId).FirstOrDefaultAsync();
if (lastAnswer != null)
else if (inDto.VisitTaskNum > 2)
{
await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.Id == lastAnswer.Id, x => new ReadingTaskQuestionAnswer
// 上一个访视的BTN
var lastBTN = (await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTask.VisitTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.BaseLineLesionsCount).Select(x => x.Answer).FirstOrDefaultAsync()).IsNullOrEmptyReturn0();
// 上上个访视的 最小BTN
var lastTwoBTN = otherBTNStrList.Where(x => x.VisitTaskNum < lastTask.VisitTaskNum).Select(x => x.Answer.IsNullOrEmptyReturn0()).Min();
// V2新病灶计数+[(V2-BTN- MinV1-BTN、BL-BTN]>=2
// V3自治疗后第二个访视点以来持续的新骨变数量 + [(V3 - BTN - MinV2 - BTN、V1 - BTN、BL - BTN] + 新病灶 >= 2
// V3与V2的间隔 >= 6周
// 按上面条件写三个if看着清晰点
if (lastNewLesionsCount + lastBTN - lastTwoBTN >= 2)
{
PCWGInterimAnswer = string.Empty,
if (thisNewBoneLesionsCount + thisBTN - othenMinBTNCount + thisNewLesionsCount >= 2)
{
if (daysBetween >= 42)
{
isPDResult = true;
}
}
}
}
if (isPDResult)
{
var visitForTumorEvaluationQuestionId = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SiteVisitForTumorEvaluation).Select(x => x.QuestionId).FirstOrDefault();
await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.VisitTaskId == lastTask.VisitTaskId && x.ReadingQuestionTrialId == visitForTumorEvaluationQuestionId, x => new ReadingTaskQuestionAnswer
{
PCWGInterimAnswer = VisitTumorEvaluation.PD.GetEnumInt(),
});
}
else
{
if (lastTask != null)
{
// 如果不是PD 需要把上一次的PD改为NoPD
var visitForTumorEvaluationQuestionId = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.SiteVisitForTumorEvaluation).Select(x => x.QuestionId).FirstOrDefault();
var lastAnswer = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTask.VisitTaskId && x.ReadingQuestionTrialId == visitForTumorEvaluationQuestionId).FirstOrDefaultAsync();
if (lastAnswer != null)
{
await _readingTaskQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.Id == lastAnswer.Id, x => new ReadingTaskQuestionAnswer
{
PCWGInterimAnswer = string.Empty,
});
}
}
}
}
}
return isPDResult;
}