//--------------------------------------------------------------------
// 此代码由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;
namespace IRaCIS.Core.Application.Service
{
///
/// 阅片计算
///
[NonDynamicWebApi]
[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;
}
///
/// 计算任务
///
///
///
public async Task CalculateTask(CalculateTaskInDto inDto)
{
var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.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,
QuestionType=x.QuestionType,
}).ToListAsync();
var questionAnswers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Select(x => new
{
x.ReadingQuestionTrialId,
x.Answer
}).ToListAsync() ;
var tableQuestion = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.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 = inDto.VisitTaskId,
SubjectVisitId = visitTask.SourceSubjectVisitId.Value,
QuestionInfo = questionInfos,
CriterionId= criterionId,
TrialId=visitTask.TrialId,
};
await ReadingCalculate(readingData);
}
///
/// 自动计算
///
///
///
public async Task ReadingCalculate(ReadingCalculateDto inDto)
{
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:
needAddList.Add(new ReadingTaskQuestionAnswer()
{
Answer = (await GetLowestIncrease(inDto)).ToString(),
ReadingQuestionTrialId = item.QuestionId,
});
break;
// 与整个访视期间最低点相比增加的百分比 其他任务需要改
case QuestionType.LowPercent:
needAddList.Add(new ReadingTaskQuestionAnswer()
{
Answer = (await GetLowPercent(inDto)).ToString(),
ReadingQuestionTrialId = item.QuestionId,
});
break;
// 整个访视期间最低点访视名称 其他任务需要改
case QuestionType.LowVisit:
needAddList.Add(new ReadingTaskQuestionAnswer()
{
Answer = (await GetLowVisit(inDto)).ToString(),
ReadingQuestionTrialId = item.QuestionId,
});
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();
}
#region 获取SOD
///
/// 获取SOD
///
///
/// 靶病灶径线之和(SOD)
/// 非淋巴结的长径 和淋巴结的短径
///
///
public async Task GetSODData(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()=="true".ToLower())))
{
// 淋巴结的短径
result += decimal.Parse(item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault() ?? "0");
}
if (item.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsLymph && (x.Answer == "是" || x.Answer.ToLower() == "true".ToLower())))
{
// 非淋巴结的长径
result += decimal.Parse(item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault() ?? "0");
}
}
return result;
}
#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 += decimal.Parse(item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).Select(x => x.Answer).FirstOrDefault() ?? "0");
}
}
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 * 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).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 = decimal.Parse(lastQuestionAsnwer.Where(x => x.RowIndex == item && x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault() ?? "0");
var thisRowData = thisQuestionAsnwer.Where(x => x.RowIndex == item).SelectMany(x => x.TableQuestionList).ToList();
var thisValue = decimal.Parse(thisRowData.Where(x => x.QuestionMark == QuestionMark.ShortAxis).Select(x => x.Answer).FirstOrDefault() ?? "0");
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 获取基线SOD
///
/// 获取基线SOD
///
///
///
private async Task GetBaseLineSOD(ReadingCalculateDto inDto)
{
if (await _visitTaskRepository.AnyAsync(x => x.Id == inDto.VisitTaskId && x.SourceSubjectVisit.IsBaseLine&&!x.IsAnalysisCreate))
{
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)
.Select(x => x.Id).FirstOrDefaultAsync();
var baseLineSOD = decimal.Parse(await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == baseLineTaskId && x.ReadingQuestionTrial.QuestionType == QuestionType.SOD).Select(x => x.Answer).FirstOrDefaultAsync() ?? "0");
return baseLineSOD;
}
#endregion
#region 获取访视任务信息
///
/// 获取访视任务信息
///
///
///
private async Task> GetVisitTaskAnswerList(ReadingCalculateDto inDto)
{
var answerList = 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
{
VisitName = x.VisitTask.SourceSubjectVisit.VisitName,
SOD = x.Answer
}).ToListAsync();
var decimalAnswerList = answerList.Select(x => new VisitTaskAnswerInfo
{
VisitName = x.VisitName,
SOD = decimal.Parse(x.SOD ?? "0"),
}).ToList();
return decimalAnswerList;
}
#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).Select(x => x.Id).FirstOrDefaultAsync();
return LastVisitTaskId;
}
#endregion
}
}