|
|
|
@ -59,6 +59,7 @@ import java.text.DecimalFormat; |
|
|
|
|
import java.time.LocalDate; |
|
|
|
|
import java.time.LocalDateTime; |
|
|
|
|
import java.util.*; |
|
|
|
|
import java.util.concurrent.CompletableFuture; |
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean; |
|
|
|
|
import java.util.concurrent.atomic.AtomicReference; |
|
|
|
|
import java.util.function.Function; |
|
|
|
@ -202,18 +203,18 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
&& testRecordSampleSolutionsNoList.contains(item.getSampleNo()) |
|
|
|
|
); |
|
|
|
|
}).collect(Collectors.toList()); |
|
|
|
|
ESTBusinessInfoVO estBusinessInfoVO = estBusinessInfoVOS.get(0); |
|
|
|
|
// 封装的结果集
|
|
|
|
|
List<Object> retList = new ArrayList<>(); |
|
|
|
|
if (estBusinessInfoVO.getBusinessType().equals(BusinessType.BOINT_CASE.getBusinessType())) { |
|
|
|
|
extractedSampleTestData(testRecordSampleDataList, retList, HairSewageDataDto.class); |
|
|
|
|
} else if (estBusinessInfoVO.getBusinessType().equals(BusinessType.NPS_CASE.getBusinessType()) || estBusinessInfoVO.getBusinessType().equals(BusinessType.SCREENING_EVENT.getBusinessType())) { |
|
|
|
|
extractedSampleTestData(testRecordSampleDataList, retList, NPSCaseTestDataDto.class); |
|
|
|
|
} else { |
|
|
|
|
extractedSampleTestData(testRecordSampleDataList, retList, HairSewageDataDto.class); |
|
|
|
|
} |
|
|
|
|
// List<?> collect = TypeCasting(retList);
|
|
|
|
|
return typeCasting(retList); |
|
|
|
|
// ESTBusinessInfoVO estBusinessInfoVO = estBusinessInfoVOS.get(0);
|
|
|
|
|
// // 封装的结果集
|
|
|
|
|
// List<Object> retList = new ArrayList<>();
|
|
|
|
|
// if (estBusinessInfoVO.getBusinessType().equals(BusinessType.BOINT_CASE.getBusinessType())) {
|
|
|
|
|
// extractedSampleTestData(testRecordSampleDataList, retList, HairSewageDataDto.class);
|
|
|
|
|
// } else if (estBusinessInfoVO.getBusinessType().equals(BusinessType.NPS_CASE.getBusinessType()) || estBusinessInfoVO.getBusinessType().equals(BusinessType.SCREENING_EVENT.getBusinessType())) {
|
|
|
|
|
// extractedSampleTestData(testRecordSampleDataList, retList, NPSCaseTestDataDto.class);
|
|
|
|
|
// } else {
|
|
|
|
|
// extractedSampleTestData(testRecordSampleDataList, retList, HairSewageDataDto.class);
|
|
|
|
|
// }
|
|
|
|
|
//// List<?> collect = TypeCasting(retList);
|
|
|
|
|
return testRecordSampleDataList; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -248,21 +249,21 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
List<TestRecordSampleData> list = this.list(Wrappers.<TestRecordSampleData>lambdaQuery() |
|
|
|
|
.eq(TestRecordSampleData::getTestId, testId) |
|
|
|
|
.last("ORDER BY SUBSTRING_INDEX(name, '-', -1) + 0")); |
|
|
|
|
List<Object> retList = new ArrayList<>(); |
|
|
|
|
switch (BusinessType.getBusinessTypeByType(type)) { |
|
|
|
|
case SCREENING_EVENT: |
|
|
|
|
case NPS_CASE: |
|
|
|
|
// NPS的数据分析
|
|
|
|
|
extractedSampleTestData(list, retList, NPSCaseTestDataDto.class); |
|
|
|
|
break; |
|
|
|
|
case BOINT_CASE: |
|
|
|
|
extractedSampleTestData(list, retList, HairSewageDataDto.class); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
// List<Object> retList = new ArrayList<>();
|
|
|
|
|
// switch (BusinessType.getBusinessTypeByType(type)) {
|
|
|
|
|
// case SCREENING_EVENT:
|
|
|
|
|
// case NPS_CASE:
|
|
|
|
|
// // NPS的数据分析
|
|
|
|
|
// extractedSampleTestData(list, retList, NPSCaseTestDataDto.class);
|
|
|
|
|
// break;
|
|
|
|
|
// case BOINT_CASE:
|
|
|
|
|
// extractedSampleTestData(list, retList, HairSewageDataDto.class);
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// z最后转换类型
|
|
|
|
|
// TypeCasting(retList);
|
|
|
|
|
return typeCasting(retList); |
|
|
|
|
return list; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -422,7 +423,7 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public JSONObject updateEntrustTestData(UpdateEntrustTestDataDTO dto) { |
|
|
|
|
public TestRecordSampleData updateEntrustTestData(UpdateEntrustTestDataDTO dto) { |
|
|
|
|
JSONObject dtoParam = dto.getParam(); |
|
|
|
|
TestRecordSampleData oldInfo = this.getById(dtoParam.getString("testSampleDataId")); // 取实验数据id
|
|
|
|
|
// 取出老数据,进行更改
|
|
|
|
@ -442,34 +443,40 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
/*dtoParam.put("testSampleDataList", null);*/ |
|
|
|
|
NPSCaseTestDataDto param = JSONObject.toJavaObject(dtoParam, NPSCaseTestDataDto.class); |
|
|
|
|
|
|
|
|
|
saved = saveOrUpdateTestData( |
|
|
|
|
return saveOrUpdateTestData( |
|
|
|
|
oldInfo, |
|
|
|
|
param.getCompoundName(), |
|
|
|
|
JSONUtil.toJsonStr(param), |
|
|
|
|
param.getSampleNo(), |
|
|
|
|
param.getTestId(), |
|
|
|
|
param.getSampleName(), |
|
|
|
|
param.getCompoundCnName()); |
|
|
|
|
param.getCompoundCnName(), |
|
|
|
|
param.getTargetRtTime(), |
|
|
|
|
param.getRtTimeError(), |
|
|
|
|
param.getTargetConcentration()); |
|
|
|
|
|
|
|
|
|
} else if (dto.getType().equals(BusinessType.BOINT_CASE.getBusinessType())) { |
|
|
|
|
} else { |
|
|
|
|
HairSewageDataDto param = JSONObject.toJavaObject(dtoParam, HairSewageDataDto.class); |
|
|
|
|
saved = saveOrUpdateTestData( |
|
|
|
|
return saveOrUpdateTestData( |
|
|
|
|
oldInfo, |
|
|
|
|
param.getCompoundName(), |
|
|
|
|
JSONUtil.toJsonStr(param), |
|
|
|
|
param.getSampleNo(), |
|
|
|
|
param.getTestId(), |
|
|
|
|
param.getSampleName(), |
|
|
|
|
param.getCompoundCnName()); |
|
|
|
|
} |
|
|
|
|
// 根据成功标识返回
|
|
|
|
|
if (saved) { |
|
|
|
|
// 保存成功, 返回成功的json对象
|
|
|
|
|
return dtoParam; |
|
|
|
|
} else { |
|
|
|
|
// 保存失败, 返回之前的json对象
|
|
|
|
|
return oldObject; |
|
|
|
|
} |
|
|
|
|
param.getCompoundCnName(), |
|
|
|
|
param.getTargetRtTime(), |
|
|
|
|
param.getRtTimeError(), |
|
|
|
|
param.getTargetConcentration()); |
|
|
|
|
} |
|
|
|
|
// // 根据成功标识返回
|
|
|
|
|
// if (saved) {
|
|
|
|
|
// // 保存成功, 返回成功的json对象
|
|
|
|
|
// return dtoParam;
|
|
|
|
|
// } else {
|
|
|
|
|
// // 保存失败, 返回之前的json对象
|
|
|
|
|
// return oldObject;
|
|
|
|
|
// }
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -844,49 +851,6 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
// }
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 更新或者保存实验数据 |
|
|
|
|
* |
|
|
|
|
* @param oldInfo 未更新前的数据 |
|
|
|
|
* @param compoundName |
|
|
|
|
* @param jsonStr DTO 转 json String |
|
|
|
|
* @param sampleNo |
|
|
|
|
* @param testId |
|
|
|
|
* @param sampleName |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
private boolean saveOrUpdateTestData(TestRecordSampleData oldInfo, |
|
|
|
|
String compoundName, |
|
|
|
|
String jsonStr, |
|
|
|
|
String sampleNo, |
|
|
|
|
String testId, String sampleName, String compoundCnName) { |
|
|
|
|
// TestRecordSampleData one = this.getById(testSampleDataId);
|
|
|
|
|
if (oldInfo != null) { |
|
|
|
|
return this.update(Wrappers.<TestRecordSampleData>lambdaUpdate() |
|
|
|
|
.eq(TestRecordSampleData::getId, oldInfo.getId()) |
|
|
|
|
.set(!oldInfo.getCompoundName().equals(compoundName), TestRecordSampleData::getCompoundName, compoundName) |
|
|
|
|
.set(sampleName != null && !sampleName.equals(oldInfo.getName()), TestRecordSampleData::getName, sampleName) |
|
|
|
|
.set(TestRecordSampleData::getDataResultJson, jsonStr) |
|
|
|
|
.set(StringUtils.isNotBlank(compoundCnName), TestRecordSampleData::getCompoundCnName, compoundCnName)); |
|
|
|
|
} else { |
|
|
|
|
TestRecordSampleData testRecordSampleData = new TestRecordSampleData(); |
|
|
|
|
testRecordSampleData.setId(IdWorker.get32UUID()); |
|
|
|
|
testRecordSampleData.setSampleNo(sampleNo); |
|
|
|
|
testRecordSampleData.setCompoundName(compoundName); |
|
|
|
|
testRecordSampleData.setTestId(testId); |
|
|
|
|
testRecordSampleData.setDataResultJson(jsonStr); |
|
|
|
|
if (sampleNo.startsWith(StdSolutionNum.QC_SOLUTION.getPrefix())) { |
|
|
|
|
testRecordSampleData.setSampleType(TestRecordSampleDataConstant.SAMPLE_TYPE_QC); |
|
|
|
|
} else if (sampleNo.startsWith(StdSolutionNum.MIXED_SOLUTION.getPrefix()) || sampleNo.startsWith(StdSolutionNum.SIMPLE_SOLUTION.getPrefix())) { |
|
|
|
|
testRecordSampleData.setSampleType(TestRecordSampleDataConstant.SAMPLE_TYPE_STD); |
|
|
|
|
} else { |
|
|
|
|
testRecordSampleData.setSampleType(TestRecordSampleDataConstant.SAMPLE_TYPE_ANALYTE); |
|
|
|
|
} |
|
|
|
|
return this.save(testRecordSampleData); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 毛发案件检验数据持久化到数据库 |
|
|
|
|
* |
|
|
|
@ -1651,15 +1615,15 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
|
|
|
|
|
List<TestRecordSampleData> sampleDataList = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
TestRecordSampleData stdSampleData = createSampleData(compoundName, TestRecordSampleDataConstant.SAMPLE_TYPE_STD, TestRecordSampleDataConstant.SAMPLE_TYPE_STD + "-" + compoundName); |
|
|
|
|
TestRecordSampleData stdSampleData = createSampleData(compoundName, TestRecordSampleDataConstant.SAMPLE_TYPE_STD, TestRecordSampleDataConstant.SAMPLE_TYPE_STD + "-" + compoundName, testId); |
|
|
|
|
sampleDataList.add(stdSampleData); |
|
|
|
|
|
|
|
|
|
sampleInfos.forEach(item -> { |
|
|
|
|
TestRecordSampleData sampleData = createSampleData(compoundName, TestRecordSampleDataConstant.SAMPLE_TYPE_ANALYTE, item.getAcceptNo()); |
|
|
|
|
TestRecordSampleData sampleData = createSampleData(compoundName, TestRecordSampleDataConstant.SAMPLE_TYPE_ANALYTE, item.getAcceptNo(), testId); |
|
|
|
|
sampleDataList.add(sampleData); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
if (drug != null && StrUtil.isAllNotBlank(drug.getMainProductIon(), drug.getMinorProductIon(), drug.getCharacteristicIons())) { |
|
|
|
|
if (drug != null && StrUtil.isNotBlank(drug.getCharacteristicIons())) { |
|
|
|
|
// 当对应的毒品信息不为空,添加扩展数据
|
|
|
|
|
List<TestRecordSampleDataExpand> testRecordSampleDataExpandList = sampleDataList.stream().flatMap(sampleData -> { |
|
|
|
|
List<TestRecordSampleDataExpand> testRecordSampleDataExpand = testRecordSampledataExpandService.saveExpDataByBusinessType(sampleData.getId(), drug, testRecord.getBusinessType()); |
|
|
|
@ -1676,15 +1640,17 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
* @param compoundName 化合物名称 |
|
|
|
|
* @param sampleType 样本类型 |
|
|
|
|
* @param sampleNo 样本编号 |
|
|
|
|
* @param testId 实验id |
|
|
|
|
* @return 返回创建的测试记录样本数据对象 |
|
|
|
|
*/ |
|
|
|
|
private TestRecordSampleData createSampleData(String compoundName, String sampleType, String sampleNo) { |
|
|
|
|
private TestRecordSampleData createSampleData(String compoundName, String sampleType, String sampleNo, String testId) { |
|
|
|
|
TestRecordSampleData data = new TestRecordSampleData(); |
|
|
|
|
data.setCompoundName(compoundName); |
|
|
|
|
data.setSampleNo(sampleNo); |
|
|
|
|
data.setSampleType(sampleType); |
|
|
|
|
data.setName(sampleNo); |
|
|
|
|
data.setStatus(TaskTestDataStatus.WAIT_REVIEW.getCode()); |
|
|
|
|
data.setTestId(testId); |
|
|
|
|
data.setId(IdWorker.getIdStr()); |
|
|
|
|
return data; |
|
|
|
|
} |
|
|
|
@ -1707,44 +1673,47 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
.eq(TestRecordSampleData::getTestId, testId) |
|
|
|
|
.eq(TestRecordSampleData::getCompoundName, compoundName)); |
|
|
|
|
List<String> removeIds = removeDataList.stream().map(TestRecordSampleData::getId).collect(Collectors.toList()); |
|
|
|
|
if (CollUtil.isNotEmpty(removeIds)) { |
|
|
|
|
// 根据测试记录ID和化合物名称删除对应的测试记录样本数据
|
|
|
|
|
testRecordSampledataExpandService.remove(Wrappers.<TestRecordSampleDataExpand>lambdaQuery().in(TestRecordSampleDataExpand::getTestDataId, removeIds)); |
|
|
|
|
} |
|
|
|
|
return this.removeBatchByIds(removeIds); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public TestRecordSampleData updateData(TestRecordSampleData data) { |
|
|
|
|
if (this.getById(data.getId()) == null) { |
|
|
|
|
throw new RuntimeException("数据不存在"); |
|
|
|
|
} |
|
|
|
|
String compoundName = data.getCompoundName(); |
|
|
|
|
/** |
|
|
|
|
* 更新计算数据,计算保留时间和保留时间误差 |
|
|
|
|
* @param dataId 检验数据id |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public Boolean calculateInspectData(String dataId) { |
|
|
|
|
TestRecordSampleData testRecordSampleData = super.getById(dataId); |
|
|
|
|
String compoundName = testRecordSampleData.getCompoundName(); |
|
|
|
|
|
|
|
|
|
TestRecordSampleData std = this.getOne(Wrappers.<TestRecordSampleData>lambdaQuery() |
|
|
|
|
.eq(TestRecordSampleData::getCompoundName, compoundName) |
|
|
|
|
.eq(TestRecordSampleData::getTestId, data.getTestId()) |
|
|
|
|
.eq(TestRecordSampleData::getTestId, testRecordSampleData.getTestId()) |
|
|
|
|
.eq(TestRecordSampleData::getSampleType, "STD")); |
|
|
|
|
|
|
|
|
|
if ( data.getTargetRtTime() != null && std.getTargetRtTime() != null ) { |
|
|
|
|
TestRecord testRecord = testRecordService.getById(data.getTestId()); |
|
|
|
|
if ( testRecordSampleData.getTargetRtTime() != null && std.getTargetRtTime() != null ) { |
|
|
|
|
TestRecord testRecord = testRecordService.getById(testRecordSampleData.getTestId()); |
|
|
|
|
if (testRecord.getBusinessType().equals(BusinessType.BOINT_CASE.getBusinessType())) { |
|
|
|
|
data.setRtTimeError(processInspectDataService.getHairCaseRtTimeError(data.getTargetRtTime(), std.getStdRtTime())); |
|
|
|
|
data.setRtTimeWithinError( |
|
|
|
|
testRecordSampleData.setRtTimeError(processInspectDataService.getHairCaseRtTimeError(testRecordSampleData.getTargetRtTime(), std.getStdRtTime())); |
|
|
|
|
testRecordSampleData.setRtTimeWithinError( |
|
|
|
|
processInspectDataService.setHairCaseRtTimeWithinError( |
|
|
|
|
data.getRtTimeError() |
|
|
|
|
testRecordSampleData.getRtTimeError() |
|
|
|
|
) |
|
|
|
|
); |
|
|
|
|
} else { |
|
|
|
|
data.setRtTimeError(processInspectDataService.getHairCaseRtTimeError(data.getTargetRtTime(), std.getStdRtTime())); |
|
|
|
|
data.setRtTimeWithinError( |
|
|
|
|
testRecordSampleData.setRtTimeError(processInspectDataService.getHairCaseRtTimeError(testRecordSampleData.getTargetRtTime(), std.getStdRtTime())); |
|
|
|
|
testRecordSampleData.setRtTimeWithinError( |
|
|
|
|
processInspectDataService.getRtWithinErrorText( |
|
|
|
|
Math.abs(data.getRtTimeError()), |
|
|
|
|
Math.abs(testRecordSampleData.getRtTimeError()), |
|
|
|
|
1 |
|
|
|
|
) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
System.out.println("所有属性都不为 null"); |
|
|
|
|
} |
|
|
|
|
return this.updateById(data) ? data : null; |
|
|
|
|
return this.updateById(testRecordSampleData); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@ -1762,4 +1731,62 @@ public class TestRecordSampleDataServiceImpl extends ServiceImpl<TestRecordSampl |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 更新或者保存实验数据 |
|
|
|
|
* |
|
|
|
|
* @param oldInfo 未更新前的数据 |
|
|
|
|
* @param compoundName |
|
|
|
|
* @param jsonStr DTO 转 json String |
|
|
|
|
* @param sampleNo |
|
|
|
|
* @param testId |
|
|
|
|
* @param sampleName |
|
|
|
|
* @param targetRtTime |
|
|
|
|
* @param rtTimeError |
|
|
|
|
* @param targetConcentration |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
private TestRecordSampleData saveOrUpdateTestData(TestRecordSampleData oldInfo, |
|
|
|
|
String compoundName, |
|
|
|
|
String jsonStr, |
|
|
|
|
String sampleNo, |
|
|
|
|
String testId, String sampleName, String compoundCnName, double targetRtTime, double rtTimeError, String targetConcentration) { |
|
|
|
|
boolean success = false; |
|
|
|
|
if (oldInfo != null) { |
|
|
|
|
success = this.update(Wrappers.<TestRecordSampleData>lambdaUpdate() |
|
|
|
|
.eq(TestRecordSampleData::getId, oldInfo.getId()) |
|
|
|
|
.set(!oldInfo.getCompoundName().equals(compoundName), TestRecordSampleData::getCompoundName, compoundName) |
|
|
|
|
.set(sampleName != null && !sampleName.equals(oldInfo.getName()), TestRecordSampleData::getName, sampleName) |
|
|
|
|
.set(TestRecordSampleData::getTargetRtTime, targetRtTime) |
|
|
|
|
.set(TestRecordSampleData::getRtTimeError, rtTimeError) |
|
|
|
|
.set(TestRecordSampleData::getSampleConcentration, targetConcentration) |
|
|
|
|
// .set(TestRecordSampleData::getDataResultJson, jsonStr) // 现在数据提取到了表字段,不在处理json数据
|
|
|
|
|
.set(StringUtils.isNotBlank(compoundCnName), TestRecordSampleData::getCompoundCnName, compoundCnName)); |
|
|
|
|
} else { |
|
|
|
|
oldInfo = new TestRecordSampleData(); |
|
|
|
|
oldInfo.setId(IdWorker.get32UUID()); |
|
|
|
|
oldInfo.setSampleNo(sampleNo); |
|
|
|
|
oldInfo.setCompoundName(compoundName); |
|
|
|
|
oldInfo.setSampleConcentration(targetConcentration); |
|
|
|
|
oldInfo.setRtTimeError(rtTimeError); |
|
|
|
|
oldInfo.setTargetRtTime(targetRtTime); |
|
|
|
|
oldInfo.setTestId(testId); |
|
|
|
|
// oldInfo.setDataResultJson(jsonStr); // 现在数据提取到了表字段,不在处理json数据
|
|
|
|
|
if (sampleNo.startsWith(StdSolutionNum.QC_SOLUTION.getPrefix())) { |
|
|
|
|
oldInfo.setSampleType(TestRecordSampleDataConstant.SAMPLE_TYPE_QC); |
|
|
|
|
} else if (sampleNo.startsWith(StdSolutionNum.MIXED_SOLUTION.getPrefix()) || sampleNo.startsWith(StdSolutionNum.SIMPLE_SOLUTION.getPrefix())) { |
|
|
|
|
oldInfo.setSampleType(TestRecordSampleDataConstant.SAMPLE_TYPE_STD); |
|
|
|
|
} else { |
|
|
|
|
oldInfo.setSampleType(TestRecordSampleDataConstant.SAMPLE_TYPE_ANALYTE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
success = this.save(oldInfo); |
|
|
|
|
} |
|
|
|
|
if (success) { |
|
|
|
|
String dataId = oldInfo.getId(); |
|
|
|
|
CompletableFuture.runAsync(() -> calculateInspectData(dataId)); |
|
|
|
|
return super.getById(dataId); |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|