irc-netcore-api/IRaCIS.Core.Application/Service/ReadingCalculate/OCTCalculateService.cs

1192 lines
53 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
[ApiExplorerSettings(GroupName = "Reading")]
public class OCTCalculateService(
IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository,
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
IRepository<OrganInfo> _organInfoRepository,
IHttpContextAccessor httpContext,
IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<TumorAssessment_IRECIST1Point1> _tumorAssessmentRepository,
IGeneralCalculateService _generalCalculateService,
IVisitTaskHelpeService _visitTaskHelpeService,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
ILogger<IRECIST1Point1CalculateService> _logger) : BaseService, ICriterionCalculateService
{
/// <summary>
/// 获取阅片的计算数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<object> GetReadingCalculationData(GetReadingCalculationDataInDto inDto)
{
return new
{
};
}
#region 临时对象 单个请求的生命周期 避免重复查询数据库
private List<VisitTaskAnswerInfo> visitTaskAnswerList;
/// <summary>
/// 获取Sod的值
/// </summary>
private decimal? sODData;
/// <summary>
/// 获取iSod的值
/// </summary>
private decimal? iSODData;
private string nAString = "NA";
/// <summary>
/// 上一次访视Id
/// </summary>
public Guid? lastVisitTaskId;
/// <summary>
/// 首次转变的任务ID
/// </summary>
public Guid? firstChangeTaskId;
/// <summary>
/// 触发任务list
/// </summary>
public List<TirggerTaskInfo>? compareTaskList = null;
#endregion
#region 删除病灶获取起始病灶序号
/// <summary>
/// 删除病灶获取起始病灶序号RECIST1Point1 固定是1
/// </summary>
/// <returns></returns>
public async Task<int> GetDeleteLesionStatrIndex(DeleteReadingRowAnswerInDto inDto)
{
return 1;
}
#endregion
#region 获取阅片报告
/// <summary>
/// 获取阅片报告
/// </summary>
/// <param name="indto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetReadingReportEvaluationOutDto> GetReadingReportEvaluation(GetReadingReportEvaluationInDto indto)
{
GetReadingReportEvaluationOutDto result = new GetReadingReportEvaluationOutDto();
var isConvertTask = await _visitTaskRepository.Where(x => x.Id == indto.VisitTaskId).Select(x => x.IsConvertedTask).FirstNotNullAsync();
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == indto.VisitTaskId).FirstNotNullAsync();
result.CalculateResult = await this.GetReportVerify(new GetReportVerifyInDto()
{
VisitTaskId = indto.VisitTaskId,
IsConvertTask = isConvertTask,
BeforeConvertedTaskId = visitTaskInfo.BeforeConvertedTaskId,
});
result.ReadingTaskState = visitTaskInfo.ReadingTaskState;
var taskInfoList = await _generalCalculateService.GetReadingReportTaskList(indto.VisitTaskId);
result.VisitTaskList = taskInfoList;
var visitTaskIds = taskInfoList.Select(x => x.VisitTaskId).ToList();
var criterionId = visitTaskInfo.TrialReadingCriterionId;
var questionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == criterionId && x.ShowQuestion != ShowQuestion.Hide)
.WhereIf(isConvertTask, x => x.ConvertShowType == ConvertShowType.All || x.ConvertShowType == ConvertShowType.AfterShow)
.WhereIf(!isConvertTask, x => x.ConvertShowType == ConvertShowType.All || x.ConvertShowType == ConvertShowType.BeforeShow)
.ToListAsync();
var tableQuestionList = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == criterionId).OrderBy(x => x.ShowOrder).ToListAsync();
var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == indto.VisitTaskId).ProjectTo<TableAnsweRowInfo>(_mapper.ConfigurationProvider).ToListAsync();
result.LesionCountList = tableAnsweRowInfos.GroupBy(x => x.LesionType).Select(x => new LesionDto
{
LesionType = x.Key!.Value,
Count = x.ToList().Count()
}).ToList();
var lesionsIndexs = await _readingTableAnswerRowInfoRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).GroupBy(x => new { x.QuestionId }).Select(x => new lesionsIndexDto()
{
QuestionId = x.Key.QuestionId,
Rowindexs = x.Select(x => x.RowIndex).Distinct().OrderBy(x => x).ToList()
}).ToListAsync();
var answers = await _readingTaskQuestionAnswerRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).ToListAsync();
var tableAnswers = await _readingTableQuestionAnswerRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).ToListAsync();
var globalanswerList = await _readingGlobalTaskInfoRepository.Where(x => visitTaskIds.Contains(x.TaskId) && x.GlobalVisitTask.TaskState == TaskState.Effect && x.Answer != string.Empty).Select(x => new
{
x.TaskId,
x.GlobalVisitTask.VisitTaskNum,
x.QuestionId,
x.Answer
}).ToListAsync();
var alltableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).ToListAsync();
var organIds = alltableAnsweRowInfos.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList();
var organInfos = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
var needChangeType = new List<QuestionMark?>() {
QuestionMark.Organ,
QuestionMark.Location,
QuestionMark.Part,
};
// 第一级
#region 构造问题
List<ReadingReportDto> questions = questionList.Where(x => x.Type == ReadingQestionType.Group).OrderBy(x => x.ShowOrder).Select(x => new ReadingReportDto()
{
QuestionId = x.Id,
GroupName = x.GroupName,
GroupEnName = x.GroupEnName,
IsShowInDicom = x.IsShowInDicom,
Type = x.Type,
GroupId = x.GroupId,
QuestionType = x.QuestionType,
LesionType = x.LesionType,
QuestionGenre = x.QuestionGenre,
DataSource = x.DataSource,
DictionaryCode = x.DictionaryCode,
TypeValue = x.TypeValue,
QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us),
ShowOrder = x.ShowOrder,
ValueType = x.ValueType,
Unit = x.Unit,
CustomUnit = x.CustomUnit,
ReportLayType = ReportLayType.Group,
HighlightAnswer = x.HighlightAnswer,
HighlightAnswerList = x.HighlightAnswerList,
}).ToList();
// 分组
foreach (var item in questions)
{
item.Childrens = questionList.Where(x => x.GroupId == item.QuestionId).OrderBy(x => x.ShowOrder).Select(x => new ReadingReportDto()
{
GroupName = x.GroupName,
QuestionId = x.Id,
IsShowInDicom = x.IsShowInDicom,
GroupEnName = x.GroupEnName,
QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us),
LesionType = x.LesionType,
QuestionGenre = x.QuestionGenre,
DataSource = x.DataSource,
DictionaryCode = x.DictionaryCode,
Type = x.Type,
QuestionType = x.QuestionType,
TypeValue = x.TypeValue,
ShowOrder = x.ShowOrder,
OrderMark = x.OrderMark,
ValueType = x.ValueType,
Unit = x.Unit,
CustomUnit = x.CustomUnit,
ReportLayType = ReportLayType.Question,
HighlightAnswer = x.HighlightAnswer,
HighlightAnswerList = x.HighlightAnswerList,
}).ToList();
// 问题
foreach (var question in item.Childrens)
{
foreach (var task in taskInfoList)
{
var globalAnswer = globalanswerList.Where(x => x.TaskId == task.VisitTaskId && x.QuestionId == question.QuestionId).OrderByDescending(x => x.VisitTaskNum).FirstOrDefault();
var answer = answers.Where(x => x.VisitTaskId == task.VisitTaskId && x.ReadingQuestionTrialId == question.QuestionId).FirstOrDefault();
question.Answer.Add(new TaskQuestionAnswer()
{
Answer = answer == null ? string.Empty : answer.Answer,
IsGlobalChange = globalAnswer == null ? false : true,
GlobalChangeAnswer = globalAnswer == null ? string.Empty : globalAnswer.Answer,
TaskName = task.TaskName,
VisitTaskId = task.VisitTaskId,
});
}
// 构造表格行数据
var rowlist = tableAnsweRowInfos.Where(x => x.QuestionId == question.QuestionId).OrderBy(x => x.RowIndex).ToList();
question.Childrens = new List<ReadingReportDto>();
var rowoindexs = lesionsIndexs.Where(x => x.QuestionId == question.QuestionId).Select(x => x.Rowindexs.OrderBy(y => y).ToList()).FirstOrDefault();
rowoindexs = rowoindexs == null ? new List<decimal>() : rowoindexs;
foreach (var rowoindex in rowoindexs)
{
var rowinfo = rowlist.Where(x => x.RowIndex == rowoindex).FirstOrDefault();
question.Childrens.Add(new ReadingReportDto()
{
QuestionName = question.OrderMark + rowoindex.GetLesionMark(),
RowId = rowinfo?.Id,
IsShowInDicom = question.IsShowInDicom,
SplitOrMergeLesionName = rowinfo != null ? (rowinfo.MergeName.IsNullOrEmpty() ? rowinfo.SplitName : rowinfo.MergeName) : string.Empty,
SplitOrMergeType = rowinfo != null ? (rowinfo.SplitOrMergeType) : null,
LesionType = question.LesionType,
IsCanEditPosition = rowinfo != null ? (rowinfo.IsCanEditPosition) : false,
RowIndex = rowoindex,
BlindName = rowinfo != null ? rowinfo.BlindName : string.Empty,
ReportLayType = ReportLayType.Lesions,
ReportMark = rowinfo != null ? rowinfo.ReportMark : string.Empty,
});
}
foreach (var row in question.Childrens)
{
// tableQuestion
row.Childrens = tableQuestionList.Where(x => x.ReadingQuestionId == question.QuestionId).Select(x => new ReadingReportDto()
{
QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us),
QuestionId = x.ReadingQuestionId,
TableQuestionId = x.Id,
Type = x.Type,
LesionType = question.LesionType,
TableQuestionType = x.TableQuestionType,
RowId = row.RowId,
IsShowInDicom = question.IsShowInDicom,
DataSource = x.DataSource,
DictionaryCode = x.DictionaryCode,
QuestionMark = x.QuestionMark,
TypeValue = x.TypeValue,
RowIndex = row.RowIndex,
ShowOrder = x.ShowOrder,
ValueType = x.ValueType,
Unit = x.Unit,
ReportLayType = ReportLayType.TableQuestion,
}).ToList();
foreach (var tableQuestion in row.Childrens)
{
foreach (var task in taskInfoList)
{
var rowinfo = alltableAnsweRowInfos.Where(x => x.VisitTaskId == task.VisitTaskId && x.QuestionId == tableQuestion.QuestionId && x.RowIndex == tableQuestion.RowIndex).FirstOrDefault();
var taskQuestionAnswer = new TaskQuestionAnswer()
{
Answer = tableAnswers.Where(x => x.VisitTaskId == task.VisitTaskId && x.QuestionId == tableQuestion.QuestionId && x.RowIndex == tableQuestion.RowIndex && x.TableQuestionId == tableQuestion.TableQuestionId).Select(x => x.Answer).FirstIsNullReturnEmpty(),
TaskName = task.TaskName,
VisitTaskId = task.VisitTaskId,
};
if (rowinfo != null && rowinfo.OrganInfoId != null)
{
var organInfo = organInfos.Where(x => x.Id == rowinfo.OrganInfoId).FirstOrDefault();
if (organInfo != null && needChangeType.Contains(tableQuestion.QuestionMark))
{
if (_userInfo.IsEn_Us)
{
switch (tableQuestion.QuestionMark)
{
case QuestionMark.Organ:
taskQuestionAnswer.Answer = organInfo.TULOCEN;
break;
case QuestionMark.Location:
if (organInfo.IsCanEditPosition)
{
}
else
{
taskQuestionAnswer.Answer = organInfo.TULATEN;
}
break;
case QuestionMark.Part:
taskQuestionAnswer.Answer = organInfo.PartEN;
break;
}
}
else
{
switch (tableQuestion.QuestionMark)
{
case QuestionMark.Organ:
taskQuestionAnswer.Answer = organInfo.TULOC;
break;
case QuestionMark.Location:
if (organInfo.IsCanEditPosition)
{
}
else
{
taskQuestionAnswer.Answer = organInfo.TULAT;
}
break;
case QuestionMark.Part:
taskQuestionAnswer.Answer = organInfo.Part;
break;
}
}
}
}
tableQuestion.Answer.Add(taskQuestionAnswer);
}
}
}
};
}
#endregion
result.TaskQuestions = questions;
return result;
}
#endregion
/// <summary>
/// 测试计算
/// </summary>
/// <param name="visitTaskId"></param>
/// <param name="type"></param>
/// <returns></returns>
[HttpGet]
public async Task TestCalculate(Guid visitTaskId, QuestionType? type)
{
//_logger.LogError("测试计算");
ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(visitTaskId);
// await _generalCalculateService.LogRecord(readingData, "其他既往新病灶", LesionType.OtherPreviousNewLesion);
if (type == null)
{
await ReadingCalculate(readingData);
}
else
{
await ReadingCalculate(readingData, new List<QuestionType>() { type.Value });
}
}
/// <summary>
/// 计算任务
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task CalculateTask(CalculateTaskInDto inDto)
{
ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId);
readingData.IsChangeOtherTask = inDto.IsChangeOtherTask;
await ReadingCalculate(readingData);
}
/// <summary>
/// 获取报告验证的信息(这里每个标准可能不一样 返回用object)
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<GetReportVerifyOutDto> GetReportVerify(GetReportVerifyInDto inDto)
{
return new GetReportVerifyOutDto()
{
TumorEvaluate = string.Empty,
IsExistDisease = string.Empty,
};
}
/// <summary>
/// 获取OCT-FCT模板
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<FileResult> GetOCTFCTTemplate(GetExportTemplateInDto inDto)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.Subject).FirstNotNullAsync();
var values = new
{
SubjectID = taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode,
TaskBlindName = taskinfo.TaskBlindName,
};
return await _visitTaskHelpeService.ExportTemplateAsync(new IRaCIS.Application.Contracts.ExportTemplateAsyncDto()
{
ExportFileName = "OCT_FCT_Template",
TemplateCode = StaticData.Export.OCT_FCT_Template,
Data = values
});
}
/// <summary>
/// 导入OCT-FCT数据
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task UploadOCTFCTTemplate()
{
var request = httpContext.HttpContext!.Request;
var file = request.Form.Files[0];
Guid visitTaskId = Guid.Parse(request.Form["VisitTaskId"]);
var dataTable = await _generalCalculateService.GetDataTableFromUpload(file);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.Subject).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var values = new
{
SubjectID = taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode,
TaskBlindName = taskinfo.TaskBlindName,
};
if (values.SubjectID != dataTable.Rows[0]["B"].ToString() || values.TaskBlindName != dataTable.Rows[1]["B"].ToString())
{
throw new BusinessValidationFailedException(_localizer["IVUS_UploadVisitTaskError"]);
}
List<OCTFCTUploadData> measuredValueList = new List<OCTFCTUploadData>();
try
{
for (int i = 3; i < dataTable.Rows.Count; i++)
{
measuredValueList.Add(new OCTFCTUploadData()
{
PlaqueNum = int.Parse(dataTable.Rows[i]["A"].ToString()),
FirstData = int.Parse(dataTable.Rows[i]["B"].ToString()),
SecondData = int.Parse(dataTable.Rows[i]["C"].ToString()),
ThirdData = int.Parse(dataTable.Rows[i]["D"].ToString()),
});
}
}
catch (Exception)
{
throw new BusinessValidationFailedException(_localizer["IVUS_UplpadDataError"]);
}
var questionInfo = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId && x.LesionType == LesionType.FCT).FirstNotNullAsync();
var tableQuestionList = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionId == questionInfo.Id).ToListAsync();
List<ReadingTableAnswerRowInfo> tableAnsweRowInfos = new List<ReadingTableAnswerRowInfo>();
List<ReadingTableQuestionAnswer> tableAnswers = new List<ReadingTableQuestionAnswer>();
var maxnum = 0;
foreach (var item in measuredValueList)
{
maxnum = maxnum + 1;
var newRowId = NewId.NextGuid();
// 斑块数据统计
tableAnsweRowInfos.Add(new ReadingTableAnswerRowInfo()
{
Id = newRowId,
QuestionId = questionInfo.Id,
VisitTaskId = taskinfo.Id,
TrialId = taskinfo.TrialId,
RowIndex = maxnum,
IsCurrentTaskAdd = true,
BlindName = taskinfo.TaskBlindName,
OrderMark = questionInfo.OrderMark,
FristAddTaskNum = taskinfo.VisitTaskNum,
FristAddTaskId = taskinfo.Id,
RowMark = questionInfo.OrderMark + decimal.Parse(maxnum.ToString()).GetLesionMark()
});
// 编号
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = item.PlaqueNum.ToString(),
QuestionId = questionInfo.Id,
TrialId = taskinfo.TrialId,
VisitTaskId = taskinfo.Id,
RowId = newRowId,
RowIndex = maxnum,
TableQuestionId = tableQuestionList.Where(x => x.ReadingQuestionId == questionInfo.Id && x.QuestionMark == QuestionMark.PlaqueNumber).Select(x => x.Id).FirstOrDefault(),
});
var avg = item.Avg.ToString();
if (taskinfo.TrialReadingCriterion.DigitPlaces != -1)
{
var digitPlaces = taskinfo.TrialReadingCriterion.DigitPlaces ?? 0;
avg = decimal.Round(decimal.Parse(avg ?? "0"), digitPlaces).ToString("F" + digitPlaces.ToString());
}
// 第一次
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = item.FirstData.ToString(),
QuestionId = questionInfo.Id,
TrialId = taskinfo.TrialId,
VisitTaskId = taskinfo.Id,
RowId = newRowId,
RowIndex = maxnum,
TableQuestionId = tableQuestionList.Where(x => x.ReadingQuestionId == questionInfo.Id && x.QuestionMark == QuestionMark.FirstFCT).Select(x => x.Id).FirstOrDefault(),
});
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = item.SecondData.ToString(),
QuestionId = questionInfo.Id,
TrialId = taskinfo.TrialId,
VisitTaskId = taskinfo.Id,
RowId = newRowId,
RowIndex = maxnum,
TableQuestionId = tableQuestionList.Where(x => x.ReadingQuestionId == questionInfo.Id && x.QuestionMark == QuestionMark.SecondFCT).Select(x => x.Id).FirstOrDefault(),
});
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = item.ThirdData.ToString(),
QuestionId = questionInfo.Id,
TrialId = taskinfo.TrialId,
VisitTaskId = taskinfo.Id,
RowId = newRowId,
RowIndex = maxnum,
TableQuestionId = tableQuestionList.Where(x => x.ReadingQuestionId == questionInfo.Id && x.QuestionMark == QuestionMark.ThirdFCT).Select(x => x.Id).FirstOrDefault(),
});
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = avg,
QuestionId = questionInfo.Id,
TrialId = taskinfo.TrialId,
VisitTaskId = taskinfo.Id,
RowId = newRowId,
RowIndex = maxnum,
TableQuestionId = tableQuestionList.Where(x => x.ReadingQuestionId == questionInfo.Id && x.QuestionMark == QuestionMark.AvgFCT).Select(x => x.Id).FirstOrDefault(),
});
}
await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableAnswerRowInfoRepository.AddRangeAsync(tableAnsweRowInfos);
await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswers);
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
await this.CalculateTask(new CalculateTaskInDto()
{
VisitTaskId = taskinfo.Id,
});
}
/// <summary>
/// 获取OCT-脂质角度模板
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<FileResult> GetOCTLipidAngleTemplate(GetExportTemplateInDto inDto)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.Subject).FirstNotNullAsync();
var values = new
{
SubjectID = taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode,
TaskBlindName = taskinfo.TaskBlindName,
};
return await _visitTaskHelpeService.ExportTemplateAsync(new IRaCIS.Application.Contracts.ExportTemplateAsyncDto()
{
ExportFileName = "OCT_LipidAngle_Template",
TemplateCode = StaticData.Export.OCT_LipidAngle_Template,
Data = values
});
}
/// <summary>
/// 导入OCT-脂质角度数据
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task UploadOCTLipidAngleTemplate()
{
var request = httpContext.HttpContext!.Request;
var file = request.Form.Files[0];
Guid visitTaskId = Guid.Parse(request.Form["VisitTaskId"]);
var dataTable = await _generalCalculateService.GetDataTableFromUpload(file);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.Subject).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var values = new
{
SubjectID = taskinfo.BlindSubjectCode.IsNullOrEmpty() ? taskinfo.Subject.Code : taskinfo.BlindSubjectCode,
TaskBlindName = taskinfo.TaskBlindName,
};
if (values.SubjectID != dataTable.Rows[0]["B"].ToString() || values.TaskBlindName != dataTable.Rows[1]["B"].ToString())
{
throw new BusinessValidationFailedException(_localizer["IVUS_UploadVisitTaskError"]);
}
List<OCTFCTUploadData> measuredValueList = new List<OCTFCTUploadData>();
try
{
for (int i = 3; i < dataTable.Rows.Count; i++)
{
measuredValueList.Add(new OCTFCTUploadData()
{
PlaqueNum = int.Parse(dataTable.Rows[i]["A"].ToString()),
FirstData = int.Parse(dataTable.Rows[i]["B"].ToString()),
});
}
}
catch (Exception)
{
throw new BusinessValidationFailedException(_localizer["IVUS_UplpadDataError"]);
}
var questionInfo = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId && x.LesionType == LesionType.LipidAngle).FirstNotNullAsync();
var tableQuestionList = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionId == questionInfo.Id).ToListAsync();
List<ReadingTableAnswerRowInfo> tableAnsweRowInfos = new List<ReadingTableAnswerRowInfo>();
List<ReadingTableQuestionAnswer> tableAnswers = new List<ReadingTableQuestionAnswer>();
var maxnum = 0;
foreach (var item in measuredValueList)
{
maxnum = maxnum + 1;
var newRowId = NewId.NextGuid();
// 斑块数据统计
tableAnsweRowInfos.Add(new ReadingTableAnswerRowInfo()
{
Id = newRowId,
QuestionId = questionInfo.Id,
VisitTaskId = taskinfo.Id,
TrialId = taskinfo.TrialId,
RowIndex = maxnum,
IsCurrentTaskAdd = true,
BlindName = taskinfo.TaskBlindName,
OrderMark = questionInfo.OrderMark,
FristAddTaskNum = taskinfo.VisitTaskNum,
FristAddTaskId = taskinfo.Id,
RowMark = questionInfo.OrderMark + decimal.Parse(maxnum.ToString()).GetLesionMark()
});
// 编号
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = item.PlaqueNum.ToString(),
QuestionId = questionInfo.Id,
TrialId = taskinfo.TrialId,
VisitTaskId = taskinfo.Id,
RowId = newRowId,
RowIndex = maxnum,
TableQuestionId = tableQuestionList.Where(x => x.ReadingQuestionId == questionInfo.Id && x.QuestionMark == QuestionMark.PlaqueNumber).Select(x => x.Id).FirstOrDefault(),
});
var avg = item.Avg.ToString();
if (taskinfo.TrialReadingCriterion.DigitPlaces != -1)
{
var digitPlaces = taskinfo.TrialReadingCriterion.DigitPlaces ?? 0;
avg = decimal.Round(decimal.Parse(avg ?? "0"), digitPlaces).ToString("F" + digitPlaces.ToString());
}
// 脂质角度
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = item.FirstData.ToString(),
QuestionId = questionInfo.Id,
TrialId = taskinfo.TrialId,
VisitTaskId = taskinfo.Id,
RowId = newRowId,
RowIndex = maxnum,
TableQuestionId = tableQuestionList.Where(x => x.ReadingQuestionId == questionInfo.Id && x.QuestionMark == QuestionMark.LipidAngle).Select(x => x.Id).FirstOrDefault(),
});
}
await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.QuestionId == questionInfo.Id && x.VisitTaskId == taskinfo.Id);
await _readingTableAnswerRowInfoRepository.AddRangeAsync(tableAnsweRowInfos);
await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswers);
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
await this.CalculateTask(new CalculateTaskInDto()
{
VisitTaskId = taskinfo.Id,
});
}
/// <summary>
/// 自动计算
/// </summary>
/// <param name="inDto"></param>
/// <param name="calculateType"></param>
/// <returns></returns>
public async Task ReadingCalculate(ReadingCalculateDto inDto, List<QuestionType>? calculateType = null)
{
#region 计算 这里顺序非常重要 后面计算的值要依赖前面计算的结果
var needAddList = new List<ReadingTaskQuestionAnswer>();
// 计算斑块统计数据
await this.CalculatePatchDataStatistics(inDto);
inDto = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId);
List<ReadingCalculateData> calculateList = new List<ReadingCalculateData>()
{
// 斑块1-匹配动脉段最小FCT
new ReadingCalculateData (){QuestionType=QuestionType.Plaque1MinFCT,GetDecimalNullFun=GetPlaque1MinFCT},
// 斑块2-匹配动脉段最小FCT
new ReadingCalculateData (){QuestionType=QuestionType.Plaque2MinFCT,GetDecimalNullFun=GetPlaque2MinFCT},
// 斑块3-匹配动脉段最小FCT
new ReadingCalculateData (){QuestionType=QuestionType.Plaque3MinFCT,GetDecimalNullFun=GetPlaque3MinFCT},
};
if (calculateType != null)
{
calculateList = calculateList.Where(x => calculateType.Contains(x.QuestionType)).ToList();
}
foreach (var calculate in calculateList)
{
var item = inDto.QuestionInfo.FirstOrDefault(x => x.QuestionType == calculate.QuestionType);
if (item != null)
{
//计算答案
#region 计算答案
if (calculate.GetDecimalFun != null)
{
item.Answer = (await calculate.GetDecimalFun(inDto)).ToString();
}
else if (calculate.GetDecimalNullFun != null)
{
var value = await calculate.GetDecimalNullFun(inDto);
item.Answer = value == null ? string.Empty : value.Value.ToString();
}
else if (calculate.GetStringFun != null)
{
item.Answer = await calculate.GetStringFun(inDto);
}
#endregion
// 修改修约小数位数
List<ValueOfType?> valueOfTypes = new List<ValueOfType?>() {
ValueOfType.Decimals,
ValueOfType.Percentage
};
if (inDto.DigitPlaces != -1)
{
try
{
if (valueOfTypes.Contains(item.ValueType))
{
item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces).ToString("F" + inDto.DigitPlaces.ToString());
}
}
catch (Exception)
{
}
}
needAddList.Add(new ReadingTaskQuestionAnswer()
{
Answer = item.Answer,
ReadingQuestionTrialId = item.QuestionId,
});
}
}
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
}
/// <summary>
/// 计算斑块的统计数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task CalculatePatchDataStatistics(ReadingCalculateDto inDto)
{
// FCT 问题信息
var fCTQuestionInfo = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.FCT).FirstOrDefault();
List<OCTInfo> oCTFCTInfos=new List<OCTInfo> ();
foreach (var item in fCTQuestionInfo!.TableRowInfoList)
{
oCTFCTInfos.Add(new OCTInfo()
{
PlaqueNum = item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.PlaqueNumber).Select(x => int.Parse(x.Answer)).FirstOrDefault(),
Data = item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.AvgFCT).Select(x => decimal.Parse(x.Answer)).FirstOrDefault(),
});
}
// 脂质角度 问题信息
var lipidAngleQuestionInfo = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.LipidAngle).FirstOrDefault();
List<OCTInfo> lipidAngleInfos = new List<OCTInfo>();
foreach (var item in lipidAngleQuestionInfo!.TableRowInfoList)
{
lipidAngleInfos.Add(new OCTInfo()
{
PlaqueNum = item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.PlaqueNumber).Select(x => int.Parse(x.Answer)).FirstOrDefault(),
Data = item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.LipidAngle).Select(x => decimal.Parse(x.Answer)).FirstOrDefault(),
});
}
// 所有的斑块编号
var plaqueNumbers = oCTFCTInfos.Select(x => x.PlaqueNum).ToList().Union(lipidAngleInfos.Select(x => x.PlaqueNum).ToList()).Distinct().OrderBy(x => x).ToList();
List<ReadingTableAnswerRowInfo> tableAnsweRowInfos = new List<ReadingTableAnswerRowInfo>();
List<ReadingTableQuestionAnswer> tableAnswers = new List<ReadingTableQuestionAnswer>();
// 斑块统计问题的Id
var patchDataStatisticsInfo = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId && x.LesionType == LesionType.PatchDataStatistics).FirstNotNullAsync();
// 斑块统计表格问题
var patchDataTableQuestion = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionId == patchDataStatisticsInfo.Id).ToListAsync();
#region 取小数
string GetDigitPlacesData(string value)
{
if (inDto.DigitPlaces != -1)
{
value = decimal.Round(decimal.Parse(value ?? "0"), inDto.DigitPlaces).ToString("F" + inDto.DigitPlaces.ToString());
}
return value;
}
#endregion
foreach (var item in plaqueNumbers)
{
var newRowId = NewId.NextGuid();
var thisnumTableRows = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.PatchDataStatistics).SelectMany(x => x.TableRowInfoList).Where(x => x.TableQuestionList.Any(y => y.QuestionMark == QuestionMark.PlaqueNumber && y.Answer == item.ToString())).ToList();
// 斑块数据统计
tableAnsweRowInfos.Add(new ReadingTableAnswerRowInfo()
{
Id = newRowId,
QuestionId = patchDataStatisticsInfo.Id,
VisitTaskId = inDto.VisitTaskId,
TrialId = inDto.TrialId,
RowIndex = item,
IsCurrentTaskAdd = true,
BlindName = inDto.BlindName,
OrderMark = patchDataStatisticsInfo.OrderMark,
FristAddTaskNum = inDto.VisitTaskNum,
FristAddTaskId = inDto.VisitTaskId,
RowMark = patchDataStatisticsInfo.OrderMark + decimal.Parse(item.ToString()).GetLesionMark()
});
// 斑块编号
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = item.ToString(),
Id = NewId.NextGuid(),
QuestionId = patchDataStatisticsInfo.Id,
TrialId = inDto.TrialId,
VisitTaskId = inDto.VisitTaskId,
RowId = newRowId,
RowIndex = item,
TableQuestionId = patchDataTableQuestion.Where(x => x.QuestionMark == QuestionMark.PlaqueNumber).Select(x => x.Id).FirstOrDefault(),
});
// 匹配动脉段最小FCT
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = oCTFCTInfos.Count()==0? "0.00" : GetDigitPlacesData(oCTFCTInfos.Where(x => x.PlaqueNum == item).MinOrDefault(x => x.Data).ToString()),
Id = NewId.NextGuid(),
QuestionId = patchDataStatisticsInfo.Id,
TrialId = inDto.TrialId,
VisitTaskId = inDto.VisitTaskId,
RowId = newRowId,
RowIndex = item,
TableQuestionId = patchDataTableQuestion.Where(x => x.QuestionMark == QuestionMark.MiniMumFCT).Select(x => x.Id).FirstOrDefault(),
});
// 平均最小FCT
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = oCTFCTInfos.Count() == 0 ? "0.00" : GetDigitPlacesData(oCTFCTInfos.Where(x => x.PlaqueNum == item).Average(x => x.Data).ToString()),
Id = NewId.NextGuid(),
QuestionId = patchDataStatisticsInfo.Id,
TrialId = inDto.TrialId,
VisitTaskId = inDto.VisitTaskId,
RowId = newRowId,
RowIndex = item,
TableQuestionId = patchDataTableQuestion.Where(x => x.QuestionMark == QuestionMark.AvgMinFCT).Select(x => x.Id).FirstOrDefault(),
});
// 脂质角度平均值
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = lipidAngleInfos.Count() == 0 ? "0.00" : GetDigitPlacesData(lipidAngleInfos.Where(x => x.PlaqueNum == item).Average(x => x.Data).ToString()),
Id = NewId.NextGuid(),
QuestionId = patchDataStatisticsInfo.Id,
TrialId = inDto.TrialId,
VisitTaskId = inDto.VisitTaskId,
RowId = newRowId,
RowIndex = item,
TableQuestionId = patchDataTableQuestion.Where(x => x.QuestionMark == QuestionMark.AvgLipidAngle).Select(x => x.Id).FirstOrDefault(),
});
// 脂质角度最大值
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = lipidAngleInfos.Count() == 0 ? "0.00" : GetDigitPlacesData(lipidAngleInfos.Where(x => x.PlaqueNum == item).MaxOrDefault(x => x.Data).ToString()),
Id = NewId.NextGuid(),
QuestionId = patchDataStatisticsInfo.Id,
TrialId = inDto.TrialId,
VisitTaskId = inDto.VisitTaskId,
RowId = newRowId,
RowIndex = item,
TableQuestionId = patchDataTableQuestion.Where(x => x.QuestionMark == QuestionMark.MaxAvgLipidAngle).Select(x => x.Id).FirstOrDefault(),
});
// 待定指标
tableAnswers.Add(new ReadingTableQuestionAnswer()
{
Answer = string.Empty,
Id = NewId.NextGuid(),
QuestionId = patchDataStatisticsInfo.Id,
TrialId = inDto.TrialId,
VisitTaskId = inDto.VisitTaskId,
RowId = newRowId,
RowIndex = item,
TableQuestionId = patchDataTableQuestion.Where(x => x.QuestionMark == QuestionMark.Undetermined).Select(x => x.Id).FirstOrDefault(),
});
}
await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x =>x.QuestionId== patchDataStatisticsInfo.Id && x.VisitTaskId == inDto.VisitTaskId);
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.QuestionId == patchDataStatisticsInfo.Id && x.VisitTaskId == inDto.VisitTaskId);
await _readingTableAnswerRowInfoRepository.AddRangeAsync(tableAnsweRowInfos);
await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswers);
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
}
/// <summary>
/// 斑块1-匹配动脉段最小FCT
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<decimal?> GetPlaque1MinFCT(ReadingCalculateDto inDto)
{
return inDto.QuestionInfo.Where(x => x.LesionType == LesionType.PatchDataStatistics).SelectMany(x => x.TableRowInfoList).Where(x => x.TableQuestionList.Any(y => y.QuestionMark == QuestionMark.PlaqueNumber && y.Answer.IsNullOrEmptyReturn0() == 1)).SelectMany(x => x.TableQuestionList)
.Where(x => x.QuestionMark == QuestionMark.MiniMumFCT).Select(x => x.Answer).FirstIsNullReturnEmpty().IsNullOrEmptyReturn0();
}
/// <summary>
/// 斑块2-匹配动脉段最小FCT
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<decimal?> GetPlaque2MinFCT(ReadingCalculateDto inDto)
{
return inDto.QuestionInfo.Where(x => x.LesionType == LesionType.PatchDataStatistics).SelectMany(x => x.TableRowInfoList).Where(x => x.TableQuestionList.Any(y => y.QuestionMark == QuestionMark.PlaqueNumber && y.Answer.IsNullOrEmptyReturn0() == 2)).SelectMany(x => x.TableQuestionList)
.Where(x => x.QuestionMark == QuestionMark.MiniMumFCT).Select(x => x.Answer).FirstIsNullReturnEmpty().IsNullOrEmptyReturn0();
}
/// <summary>
/// 斑块3-匹配动脉段最小FCT
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<decimal?> GetPlaque3MinFCT(ReadingCalculateDto inDto)
{
return inDto.QuestionInfo.Where(x => x.LesionType == LesionType.PatchDataStatistics).SelectMany(x => x.TableRowInfoList).Where(x => x.TableQuestionList.Any(y => y.QuestionMark == QuestionMark.PlaqueNumber && y.Answer.IsNullOrEmptyReturn0() == 3)).SelectMany(x => x.TableQuestionList)
.Where(x => x.QuestionMark == QuestionMark.MiniMumFCT).Select(x => x.Answer).FirstIsNullReturnEmpty().IsNullOrEmptyReturn0();
}
/// <summary>
/// 验证访视提交
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto)
{
}
/// <summary>
/// 匹配动脉段最小FCT
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<decimal?> GetAllMinFCT(ReadingCalculateDto inDto)
{
var allMinFCT = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.FCT).SelectMany(x => x.TableRowInfoList).SelectMany(x => x.TableQuestionList)
.Where(x => x.QuestionMark == QuestionMark.MinFCT).Select(x => x.Answer.IsNullOrEmptyReturn0()).MinOrDefault();
if (allMinFCT == 0)
{
return null;
}
return allMinFCT;
}
/// <summary>
/// 所有FCT最小值中的平均值
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<decimal?> GetAvgMinFCT(ReadingCalculateDto inDto)
{
var allMinFCT = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.FCT).SelectMany(x => x.TableRowInfoList).SelectMany(x => x.TableQuestionList)
.Where(x => x.QuestionMark == QuestionMark.MinFCT).Select(x => x.Answer.IsNullOrEmptyReturn0()).ToList();
if (allMinFCT.Count() == 0)
{
return null;
}
return allMinFCT.Average(); ;
}
/// <summary>
/// 脂质角度最大值
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<decimal?> GetAllMaxLipidAngle(ReadingCalculateDto inDto)
{
var maxLipidAngle = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.LipidAngle).SelectMany(x => x.TableRowInfoList).SelectMany(x => x.TableQuestionList)
.Where(x => x.QuestionMark == QuestionMark.LipidAngle).Select(x => x.Answer.IsNullOrEmptyReturn0()).MaxOrDefault();
if (maxLipidAngle == 0)
{
return null;
}
return maxLipidAngle;
}
/// <summary>
/// 脂质角度平均值
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<decimal?> GetAvgMinLipidAngle(ReadingCalculateDto inDto)
{
var avgMinLipidAngle = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.LipidAngle).SelectMany(x => x.TableRowInfoList).SelectMany(x => x.TableQuestionList)
.Where(x => x.QuestionMark == QuestionMark.LipidAngle).Select(x => x.Answer.IsNullOrEmptyReturn0()).ToList();
if (avgMinLipidAngle.Count() == 0)
{
return null;
}
return avgMinLipidAngle.Average();
}
#region 将上一次的访视病灶添加到这一次
/// <summary>
/// 将上一次的访视病灶添加到这一次
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<AddTaskLesionAnswerFromLastTaskOutDto> AddTaskLesionAnswerFromLastTask(AddTaskLesionAnswerFromLastTaskInDto inDto)
{
var visitTaskId = inDto.VisitTaskId;
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskinfo.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstOrDefaultAsync();
return new AddTaskLesionAnswerFromLastTaskOutDto()
{
IsBaseLine = taskinfo.SourceSubjectVisitId == baseLineVisitId,
};
}
#endregion
}
}