@ -2,7 +2,7 @@ package a8k.app.engineer.service.qatest;
import a8k.OS ;
import a8k.app.constant.AppConstant ;
import a8k.app.dao.type.combination.ProjBuildi nInfo ;
import a8k.app.dao.type.combination.ProjBuildI nInfo ;
import a8k.app.dao.type.db.ProjExtInfoCard ;
import a8k.app.dao.type.db.ReactionReport ;
import a8k.app.engineer.service.executor.EngineerModeActionExecutor ;
@ -37,6 +37,8 @@ import a8k.app.type.a8k.state.Tube;
import a8k.app.type.error.AppError ;
import a8k.app.type.exception.AppException ;
import a8k.app.type.exception.EngineerTaskBreakException ;
import a8k.app.type.misc.TubeHolderScanResult ;
import a8k.app.type.misc.TubeScanResult ;
import a8k.app.type.param.type.A8kSamplePos ;
import a8k.app.type.ui.TubeHolderSetting ;
import a8k.app.type.ui.TubeSetting ;
@ -94,17 +96,17 @@ public class ExperimentConsistencyTestingService {
/ *
* 控制器
* /
final private TubePreProcesModuleCtrlService tubePreProcesModuleCtrlService ;
final private TubePreProcesModuleCtrlService tubePreProcesModuleCtrlService ;
final private TubeFeedingCtrlService tubeFeedingCtrlService ;
final private TubePreProcessModuleExCtrlService tubePreProcessModuleExCtrlService ;
final private OptScanModuleCtrlService optScanModuleCtrlService ;
final private PlateBoxCtrlService plateBoxCtrlService ;
final private TurnableMoveCtrlService turnableMoveCtrlService ;
final private LiquidOperationCtrService liquidOperationCtrService ;
final private HbotMoveExCtrlService hbotMoveExCtrlService ;
private final OptModuleDriver optModuleDriver ;
private final HbotMoveCtrlService hbotMoveCtrlService ;
private final TipOperationCtrlModule tipOperationCtrlModule ;
final private PlateBoxCtrlService plateBoxCtrlService ;
final private TurnableMoveCtrlService turnableMoveCtrlService ;
final private LiquidOperationCtrService liquidOperationCtrService ;
final private HbotMoveExCtrlService hbotMoveExCtrlService ;
private final OptModuleDriver optModuleDriver ;
private final HbotMoveCtrlService hbotMoveCtrlService ;
private final TipOperationCtrlModule tipOperationCtrlModule ;
private TubeHolderSetting curTubeHolderSetting ;
private A8kSamplePos samplePos ;
@ -179,362 +181,362 @@ public class ExperimentConsistencyTestingService {
log . info ( "开始试剂实验一致性检测" ) ;
curTubeHolderSetting = tubeHolderSetting ;
actionExecutor . start ( this : : action ) ;
}
void docmd ( String mark , A8kCmdRunnable runnable , A8kCmdRunnable virtualRunable ) throws AppException {
actionExecutor . sleep ( 2 ) ;
actionExecutor . docmd ( mark , runnable , virtualRunable ) ;
}
void docmd ( String mark , A8kCmdRunnable runnable ) throws AppException {
UISender . txInfoMsg ( log , mark ) ;
actionExecutor . docmd ( mark , runnable ) ;
}
public void action ( ) {
try {
doAction ( ) ;
} catch ( Exception e ) {
processException ( e ) ;
}
}
public void processException ( Exception e ) {
try {
log . error ( "Catch exception: " , e ) ;
if ( ! ( e instanceof EngineerTaskBreakException ) ) {
UISender . txErrorPrompt ( e ) ;
}
/ /
/ / Action
/ /
if ( actionExecutor . isInRealMode ( ) ) {
optScanModuleCtrlService . dropPlate ( ) ;
tipOperationCtrlModule . dropTip ( ) ;
tubeFeedingCtrlService . ejectTubeHolder ( ) ;
List < IncubationSubTank > all = incubationPlateStateMgr . getAllNotFreeIncubationSubTanks ( ) ;
for ( IncubationSubTank notFreeTank : all ) {
optScanModuleCtrlService . pullPlate ( notFreeTank . pos ) ;
optScanModuleCtrlService . dropPlate ( ) ;
}
}
/ /
/ / State
/ /
optScanModuleStateMgr . changeOptScanModuleStateToEmpty ( ) ;
incubationPlateStateMgr . resetAll ( ) ;
} catch ( AppException ex ) {
log . error ( "Catch exception: " , e ) ;
UISender . txErrorPrompt ( e ) ;
gStateMgrService . setFatalError ( ex . error ) ;
} catch ( Exception ex ) {
log . error ( "Catch exception: " , e ) ;
UISender . txErrorPrompt ( e ) ;
gStateMgrService . setFatalError ( new AppError ( A8kEcode . SYS_EXCEPTION , ex . getMessage ( ) ) ) ;
}
}
Boolean hasTubeHolder ;
TubeFeedingCtrlService . TubeHolderScanResult scanResult ;
public void doAction ( ) throws AppException {
/ *
* 1 . 核对是否存在试管配置是否只有一个
* 2 . 核对耗材是否充足
*
*
* 1 . 入料
* 2 . 核对试管架类型
*
* Loop
* 1 . 样本准备
*
* Loop
* 1 . 检查孵育盘是否有空闲位 ( 没有空闲位 , 则等待空闲位 )
* 2 . 检查是否有孵育完成的样本 ( 有孵育完成的样本 , 则进行光学扫描 )
* 3 . 入板
* 4 . 取样
* 5 . 预反应
* 6 . 滴定
*
* End :
* 1 . 等待所有反应板孵育完成
* /
/ / 入料
hasTubeHolder = false ;
docmd ( "入料" , ( ) - > {
hasTubeHolder = tubeFeedingCtrlService . enterTubeHolder ( ) ;
} , ( ) - > hasTubeHolder = true ) ;
if ( ! hasTubeHolder ) {
throw AppException . of ( A8kEcode . ERROR_OPERATION , "入料超时,未检测到试管架" ) ;
}
/ / 扫描试管架
scanResult = null ;
docmd ( "扫描试管架" , ( ) - > {
scanResult = tubeFeedingCtrlService . scanTubeHodler ( ) ;
} , ( ) - > {
scanResult = new TubeFeedingCtrlService . TubeHolderScanResult ( ) ;
for ( int i = 0 ; i < curTubeHolderSetting . tubeSettings . length ; i + + ) {
scanResult . tube [ i ] = new TubeFeedingCtrlService . TubesScanResult ( ) ;
if ( ! curTubeHolderSetting . tubeSettings [ i ] . projId . isEmpty ( ) ) {
scanResult . tube [ i ] . isTubeExist = true ;
}
}
} ) ;
/ / 核对试管架信息
verifyTubeHolderSettingAndTubeHolderScanResult ( curTubeHolderSetting , scanResult ) ;
/ /
A8kTubeHolderType tubeHolderType = A8kTubeHolderType . of ( scanResult . tubeHolderType ) ;
if ( A8kTubeHolderType . BulletTube1P5 . equals ( tubeHolderType ) ) {
samplePos = A8kSamplePos . Bulltube1P5Pos ;
} else if ( A8kTubeHolderType . BulletTube0P5 . equals ( tubeHolderType ) ) {
samplePos = A8kSamplePos . Bulltube0P5Pos ;
} else {
throw AppException . of ( A8kEcode . APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT , "请使用子弹头1.5ml或者子弹头0.5ml试管架" ) ;
}
/ / 构建试管架
/ / setTubeHolderDirect
for ( int tubeoff = 0 ; tubeoff < curTubeHolderSetting . tubeSettings . length ; tubeoff + + ) {
TubeSetting tubeSetting = curTubeHolderSetting . tubeSettings [ tubeoff ] ;
if ( tubeSetting . projId . isEmpty ( ) ) {
continue ;
}
Assert . isTrue ( scanResult . tube [ tubeoff ] . isTubeExist , String . format ( "位置[%d]未放入是试管" , tubeoff + 1 ) ) ;
/ / 移动试管架到预处理位置
int finalTubeoff = tubeoff ;
UISender . txInfoMsg ( log , "开始处理第%d个试管" , finalTubeoff + 1 ) ;
docmd ( "移动试管到处理位" , ( ) - > tubeFeedingCtrlService . moveTubeToPreProcessPos ( finalTubeoff ) ) ;
for ( int j = 0 ; j < getRepeatTimes ( tubeoff ) ; j + + ) {
/ / 尝试处理孵育完成的反应板
incubationPlateProcess ( false ) ;
ProjBuildinInfo projBuildinInfo = projInfoMgrService . getProjBuildInInfo ( expectedProjId ) ;
/ / 申请耗材
var consumableInfo = consumablesMgrService . reserveConsumable ( projBuildinInfo . reactionFlowType , expectedProjId ) ;
if ( consumableInfo = = null ) {
throw AppException . of ( A8kEcode . CODEERROR , "耗材不足?" ) ; / / 理论上开始阶段已经核对过了耗材数量 , 此时应该不会不足
}
consumablesMgrService . useReserveConsumable ( consumableInfo ) ;
/ / 构造项目信息
ProjExtInfoCard projExtInfoCard = projInfoMgrService . getProjExtInfoCard ( consumableInfo . lotid ) ;
ProjBriefInfo projBriefInfo = ProjInfoUtils . buildProjBrefInfo ( projBuildinInfo ) ;
Assert . notNull ( projBuildinInfo , "projBuildInInfo is null" ) ;
Assert . notNull ( projExtInfoCard , "projExtInfoCard is null" ) ;
/ / 处理样本
Tube tube = new Tube ( tubeoff ) ;
tube . setIsHighTube ( false ) ;
tube . setIsEmergency ( false ) ;
tube . setBloodType ( tubeSetting . bloodType ) ;
tube . setSampleBarcode ( tubeSetting . sampleBarcode ) ;
tube . setUserid ( tubeSetting . userid ) ;
tube . setProjInfo ( ZList . of ( projBriefInfo ) ) ;
tube . setProjIds ( ZList . of ( expectedProjId ) ) ;
String sampleId = tubeStateMgrService . newSample ( tube ) ;
tube . setSampleId ( sampleId ) ;
/ / 处理试管
processTube ( tube , tubeoff , consumableInfo , tubeSetting ) ;
if ( ! tube . getErrors ( ) . isEmpty ( ) ) {
log . warn ( "样本异常,跳过当前样本" ) ;
UISender . txErrorMsg ( log , tube . getErrors ( ) . getFirst ( ) , "样本异常,跳过当前样本" ) ;
break ;
}
docmd ( "HBOT复位" , hbotMoveExCtrlService : : moveQuickToZero ) ;
}
}
tubeFeedingCtrlService . ejectTubeHolder ( ) ;
incubationPlateProcess ( true ) ;
incubationPlateStateMgr . resetAll ( ) ;
UISender . txInfoPrompt ( log , "试剂实验一致性检测完成" ) ;
}
private void processTube ( Tube tube , Integer offset , ConsumableInfo consumableInfo , TubeSetting tubeSetting ) throws AppException {
ProjBuildinInfo projBuildinInfo = projInfoMgrService . getProjBuildInInfo ( expectedProjId ) ;
ProjExtInfoCard projExtInfoCard = projInfoMgrService . getProjExtInfoCard ( consumableInfo . lotid ) ;
/ / 拉取一个板夹到孵育盘
var freeIncubationPos = incubationPlateStateMgr . takeOneIncubationIDLEPos (
( IncubatorPos pos ) - > {
incubationPlateStateMgr . syncProjInfo ( pos , projBuildinInfo , projExtInfoCard ) ;
incubationPlateStateMgr . syncSampleInfo ( pos , tube . getSampleInfo ( ) ) ;
}
) ;
/ / 强制清空一下光学模组和孵育盘
/ / optScanModuleCtrlService . dropPlate ( ) ;
/ / optScanModuleCtrlService . pullPlate ( freeIncubationPos ) ;
/ / optScanModuleCtrlService . dropPlate ( ) ;
docmd ( "丢反应板" , optScanModuleCtrlService : : dropPlate ) ;
docmd ( "拉取反应板" , ( ) - > optScanModuleCtrlService . pullPlate ( freeIncubationPos ) ) ;
docmd ( "丢反应板" , optScanModuleCtrlService : : dropPlate ) ;
/ / plateBoxCtrlService . pushPlateQuick ( consumableInfo . group , freeIncubationPos ) ;
docmd ( "推入新的反应板" , ( ) - > plateBoxCtrlService . pushPlateQuick ( consumableInfo . group , freeIncubationPos ) ) ;
/ / 移动当前板夹到滴定位
/ / turnableMoveCtrlService . trunableMoveToDropLiquidPos ( freeIncubationPos ) ;
docmd ( "移动到滴定位" , ( ) - > turnableMoveCtrlService . trunableMoveToDropLiquidPos ( freeIncubationPos ) ) ;
docmd ( "样本处理" , ( ) - > {
try {
liquidOperationCtrService . setProjContext ( projBuildinInfo , projExtInfoCard ) ;
var preProcessPos = new PreReactionPos ( ConsumableType . SmallBottleBuffer , consumableInfo . group , consumableInfo . pos ) ;
/ / 取tip
tipOperationCtrlModule . tryTakeTip ( ( ) - > ! actionExecutor . isStopping ( ) ) ;
actionExecutor . sleep ( 1 ) ;
/ / 刺破缓冲液
hbotMoveExCtrlService . moveToLittleBufferPiercePos ( consumableInfo . group , consumableInfo . pos ) ;
/ / 取样品
Assert . isTrue ( ! samplePos . equals ( A8kSamplePos . EmergencyTubePos ) , "samplePos cannot be EmergencyTubePos" ) ;
Assert . isTrue ( ! samplePos . equals ( A8kSamplePos . BloodHTubePos ) , "samplePos cannot be BloodHTubePos" ) ;
Assert . isTrue ( ! samplePos . equals ( A8kSamplePos . BloodSTubePos ) , "samplePos cannot be BloodSTubePos" ) ;
liquidOperationCtrService . takeSampleToPreReactionPos ( samplePos , preProcessPos , takeSampleUl ) ;
actionExecutor . sleep ( 1 ) ;
/ / 取混合液到预反应位
liquidOperationCtrService . takePreReactionLiquid ( preProcessPos ) ;
liquidOperationCtrService . dropLiquidToReactionPlate ( ) ;
actionExecutor . sleep ( 1 ) ;
incubationPlateStateMgr . startIncubating ( freeIncubationPos , System . currentTimeMillis ( ) , projBuildinInfo . reactionPlateIncubationTimeMin * 60 ) ;
actionExecutor . sleep ( 1 ) ;
} catch ( AppException e ) {
if ( e . getError ( ) . eq ( A8kEcode . APPE_TAKE_SAMPLE_FAIL ) ) {
hbotMoveExCtrlService . moveQuickToZero ( ) ;
tube . setErrors ( ZList . of ( e . getError ( ) ) ) ;
incubationPlateStateMgr . resetIncubatorPos ( freeIncubationPos ) ;
/ / 丢反应板
optScanModuleCtrlService . forceDropPlate ( freeIncubationPos ) ;
UISender . txErrorMsg ( log , e , "取样失败" ) ;
} else {
throw e ;
}
}
} , ( ) - > {
incubationPlateStateMgr . startIncubating ( freeIncubationPos , System . currentTimeMillis ( ) , projBuildinInfo . reactionPlateIncubationTimeMin * 60 ) ;
} ) ;
{ / / 开始孵育
}
}
private void incubationPlateProcess ( Boolean waittingForAll ) throws AppException {
do {
IncubationSubTank tankPos = incubationPlateStateMgr . getOneExpiredPlate ( ) ;
if ( ! waittingForAll ) {
if ( incubationPlateStateMgr . isHasEnoughIncubationIDLEPos ( 1 ) & & tankPos = = null ) {
break ;
}
} else {
if ( incubationPlateStateMgr . isAllIncubationSubTanksFree ( ) ) {
break ;
}
}
if ( tankPos ! = null ) {
/ / 拉取反应板到光学模组
docmd ( "拉取反应板到光学模块" , ( ) - > { optScanModuleCtrlService . pullPlate ( tankPos . getPos ( ) ) ; } ) ;
/ / 设置光学模组状态
optScanModuleStateMgr . changeOptScanModuleStateToPlateIsReady ( tankPos . projInfo , tankPos . toSampleInfo ( ) ) ;
optScanModuleStateMgr . syncProjInfo ( tankPos . projBuildinInfo , tankPos . projExtInfoCard ) ;
/ / 复位孵育盘状态
incubationPlateStateMgr . resetIncubatorPos ( tankPos . getPos ( ) ) ;
/ /
/ / 光学扫描
/ /
/ / 光学扫描
optScanModuleStateMgr . changeOptScanModuleStateToScanning ( ) ;
doOptScan ( ) ;
/ / 丢板
docmd ( "丢弃反应板" , optScanModuleCtrlService : : dropPlate ) ;
optScanModuleStateMgr . changeOptScanModuleStateToEmpty ( ) ;
}
actionExecutor . sleep ( 100 ) ;
} while ( true ) ;
}
private void doOptScan ( ) throws AppException {
/ *
* HsCrp只有一个项目
* /
Assert . isTrue ( Objects . equals ( expectedProjId , 1 ) , "1 != expectedProjId" ) ;
int subProjIndex = 0 ;
A8kOptType optType = optScanModuleStateMgr . getOptScanModule ( ) . getProjBuildinInfo ( ) . getOptType ( subProjIndex ) ;
var buildInInfo = optScanModuleStateMgr . getOptScanModule ( ) . getProjBuildinInfo ( ) ;
SampleInfo sampleInfo = optScanModuleStateMgr . getOptScanModule ( ) . getSampleInfo ( ) ;
ProjInfo projInfo = optScanModuleStateMgr . getOptScanModule ( ) . getProjInfo ( ) ;
/ / a8kOptPeakInfo
docmd ( "光学扫描" , ( ) - > {
OptScanResult optScanResult = optScanModuleCtrlService . optScan ( buildInInfo , subProjIndex ) ;
ReactionReport . ReactionResult result = A8kPeakAnalyzer . analysisPeakInfo ( sampleInfo , projInfo , subProjIndex , optScanResult . analysResult ) ;
log . info ( "光学扫描结果: {}" , result ) ;
reactionRecordMgrService . addRecord ( optScanModuleStateMgr . getOptScanModule ( ) . getSampleInfo ( ) , projInfo , ZList . of ( optScanResult ) , ZList . of ( result ) ) ;
}
, ( ) - > {
OS . hsleep ( 1000 ) ;
}
) ;
}
/ *
* Utils
* /
private void verifyTubeHolderSettingAndTubeHolderScanResult ( TubeHolderSetting tubeHolderSetting , TubeFeedingCtrlService . TubeHolderScanResult scanResult ) throws AppException {
A8kTubeHolderType tubeHolderType = A8kTubeHolderType . of ( scanResult . tubeHolderType ) ;
if ( ! tubeHolderType . equals ( A8kTubeHolderType . BulletTube1P5 ) & & ! tubeHolderType . equals ( A8kTubeHolderType . BulletTube0P5 ) ) {
throw AppException . of ( A8kEcode . APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT , "请使用子弹头1.5ml或者子弹头0.5ml试管架" ) ;
}
for ( int i = 0 ; i < tubeHolderSetting . tubeSettings . length ; i + + ) {
TubeSetting tubeSetting = tubeHolderSetting . tubeSettings [ i ] ;
if ( tubeSetting . projId . isEmpty ( ) & & ! scanResult . tube [ i ] . isTubeExist ) {
continue ;
}
if ( tubeSetting . projId . isEmpty ( ) ) {
throw AppException . of ( A8kEcode . APPE_TUBEHOLDER_SETTING_ERROR , String . format ( "试管[%d]缺少项目配置" , i + 1 ) ) ;
}
if ( ! scanResult . tube [ i ] . isTubeExist ) {
throw AppException . of ( A8kEcode . APPE_TUBEHOLDER_SETTING_ERROR , String . format ( "位置[%d]未放入是试管" , i + 1 ) ) ;
}
}
/ / actionExecutor . start ( this : : action ) ;
}
/ /
/ / void docmd ( String mark , A8kCmdRunnable runnable , A8kCmdRunnable virtualRunable ) throws AppException {
/ / actionExecutor . sleep ( 2 ) ;
/ / actionExecutor . docmd ( mark , runnable , virtualRunable ) ;
/ /
/ / }
/ /
/ / void docmd ( String mark , A8kCmdRunnable runnable ) throws AppException {
/ / UISender . txInfoMsg ( log , mark ) ;
/ / actionExecutor . docmd ( mark , runnable ) ;
/ / }
/ /
/ /
/ / public void action ( ) {
/ /
/ / try {
/ / doAction ( ) ;
/ / } catch ( Exception e ) {
/ / processException ( e ) ;
/ / }
/ / }
/ /
/ / public void processException ( Exception e ) {
/ / try {
/ / log . error ( "Catch exception: " , e ) ;
/ / if ( ! ( e instanceof EngineerTaskBreakException ) ) {
/ / UISender . txErrorPrompt ( e ) ;
/ / }
/ / / /
/ / / / Action
/ / / /
/ / if ( actionExecutor . isInRealMode ( ) ) {
/ / optScanModuleCtrlService . dropPlate ( ) ;
/ / tipOperationCtrlModule . dropTip ( ) ;
/ / tubeFeedingCtrlService . ejectTubeHolder ( ) ;
/ / List < IncubationSubTank > all = incubationPlateStateMgr . getAllNotFreeIncubationSubTanks ( ) ;
/ / for ( IncubationSubTank notFreeTank : all ) {
/ / optScanModuleCtrlService . pullPlate ( notFreeTank . pos ) ;
/ / optScanModuleCtrlService . dropPlate ( ) ;
/ / }
/ / }
/ / / /
/ / / / State
/ / / /
/ / optScanModuleStateMgr . changeOptScanModuleStateToEmpty ( ) ;
/ / incubationPlateStateMgr . resetAll ( ) ;
/ / } catch ( AppException ex ) {
/ / log . error ( "Catch exception: " , e ) ;
/ / UISender . txErrorPrompt ( e ) ;
/ / gStateMgrService . setFatalError ( ex . error ) ;
/ / } catch ( Exception ex ) {
/ / log . error ( "Catch exception: " , e ) ;
/ / UISender . txErrorPrompt ( e ) ;
/ / gStateMgrService . setFatalError ( new AppError ( A8kEcode . SYS_EXCEPTION , ex . getMessage ( ) ) ) ;
/ / }
/ /
/ / }
/ /
/ / Boolean hasTubeHolder ;
/ / TubeHolderScanResult scanResult ;
/ /
/ / public void doAction ( ) throws AppException {
/ / / *
/ / * 1 . 核对是否存在试管配置是否只有一个
/ / * 2 . 核对耗材是否充足
/ / *
/ / *
/ / * 1 . 入料
/ / * 2 . 核对试管架类型
/ / *
/ / * Loop
/ / * 1 . 样本准备
/ / *
/ / * Loop
/ / * 1 . 检查孵育盘是否有空闲位 ( 没有空闲位 , 则等待空闲位 )
/ / * 2 . 检查是否有孵育完成的样本 ( 有孵育完成的样本 , 则进行光学扫描 )
/ / * 3 . 入板
/ / * 4 . 取样
/ / * 5 . 预反应
/ / * 6 . 滴定
/ / *
/ / * End :
/ / * 1 . 等待所有反应板孵育完成
/ / * /
/ /
/ / / / 入料
/ / hasTubeHolder = false ;
/ / docmd ( "入料" , ( ) - > {
/ / hasTubeHolder = tubeFeedingCtrlService . enterTubeHolder ( ) ;
/ / } , ( ) - > hasTubeHolder = true ) ;
/ / if ( ! hasTubeHolder ) {
/ / throw AppException . of ( A8kEcode . ERROR_OPERATION , "入料超时,未检测到试管架" ) ;
/ / }
/ /
/ / / / 扫描试管架
/ / scanResult = null ;
/ / docmd ( "扫描试管架" , ( ) - > {
/ / scanResult = tubeFeedingCtrlService . scanTubeHodler ( ) ;
/ / } , ( ) - > {
/ / scanResult = new TubeHolderScanResult ( ) ;
/ / for ( int i = 0 ; i < curTubeHolderSetting . tubeSettings . length ; i + + ) {
/ / scanResult . tube [ i ] = new TubeScanResult ( ) ;
/ / if ( ! curTubeHolderSetting . tubeSettings [ i ] . projId . isEmpty ( ) ) {
/ / scanResult . tube [ i ] . isTubeExist = true ;
/ / }
/ / }
/ / } ) ;
/ / / / 核对试管架信息
/ / verifyTubeHolderSettingAndTubeHolderScanResult ( curTubeHolderSetting , scanResult ) ;
/ / / /
/ / A8kTubeHolderType tubeHolderType = A8kTubeHolderType . of ( scanResult . tubeHolderType ) ;
/ / if ( A8kTubeHolderType . BulletTube1P5 . equals ( tubeHolderType ) ) {
/ / samplePos = A8kSamplePos . Bulltube1P5Pos ;
/ / } else if ( A8kTubeHolderType . BulletTube0P5 . equals ( tubeHolderType ) ) {
/ / samplePos = A8kSamplePos . Bulltube0P5Pos ;
/ / } else {
/ / throw AppException . of ( A8kEcode . APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT , "请使用子弹头1.5ml或者子弹头0.5ml试管架" ) ;
/ / }
/ /
/ /
/ / / / 构建试管架
/ / / / setTubeHolderDirect
/ / for ( int tubeoff = 0 ; tubeoff < curTubeHolderSetting . tubeSettings . length ; tubeoff + + ) {
/ / TubeSetting tubeSetting = curTubeHolderSetting . tubeSettings [ tubeoff ] ;
/ / if ( tubeSetting . projId . isEmpty ( ) ) {
/ / continue ;
/ / }
/ / Assert . isTrue ( scanResult . tube [ tubeoff ] . isTubeExist , String . format ( "位置[%d]未放入是试管" , tubeoff + 1 ) ) ;
/ /
/ / / / 移动试管架到预处理位置
/ / int finalTubeoff = tubeoff ;
/ / UISender . txInfoMsg ( log , "开始处理第%d个试管" , finalTubeoff + 1 ) ;
/ / docmd ( "移动试管到处理位" , ( ) - > tubeFeedingCtrlService . moveTubeToPreProcessPos ( finalTubeoff ) ) ;
/ /
/ / for ( int j = 0 ; j < getRepeatTimes ( tubeoff ) ; j + + ) {
/ /
/ / / / 尝试处理孵育完成的反应板
/ / incubationPlateProcess ( false ) ;
/ / ProjBuildInInfo projBuildinInfo = projInfoMgrService . getProjBuildInInfo ( expectedProjId ) ;
/ /
/ / / / 申请耗材
/ / var consumableInfo = consumablesMgrService . reserveConsumable ( projBuildinInfo . reactionFlowType , expectedProjId ) ;
/ / if ( consumableInfo = = null ) {
/ / throw AppException . of ( A8kEcode . CODEERROR , "耗材不足?" ) ; / / 理论上开始阶段已经核对过了耗材数量 , 此时应该不会不足
/ / }
/ / consumablesMgrService . useReserveConsumable ( consumableInfo ) ;
/ /
/ / / / 构造项目信息
/ / ProjExtInfoCard projExtInfoCard = projInfoMgrService . getProjExtInfoCard ( consumableInfo . lotid ) ;
/ / ProjBriefInfo projBriefInfo = ProjInfoUtils . buildProjBrefInfo ( projBuildinInfo ) ;
/ /
/ / Assert . notNull ( projBuildinInfo , "projBuildInInfo is null" ) ;
/ / Assert . notNull ( projExtInfoCard , "projExtInfoCard is null" ) ;
/ /
/ / / / 处理样本
/ / Tube tube = new Tube ( tubeoff ) ;
/ / tube . setIsHighTube ( false ) ;
/ / tube . setIsEmergency ( false ) ;
/ / tube . setBloodType ( tubeSetting . bloodType ) ;
/ / tube . setSampleBarcode ( tubeSetting . sampleBarcode ) ;
/ / tube . setUserid ( tubeSetting . userid ) ;
/ / tube . setProjInfo ( ZList . of ( projBriefInfo ) ) ;
/ / tube . setProjIds ( ZList . of ( expectedProjId ) ) ;
/ / String sampleId = tubeStateMgrService . newSample ( tube ) ;
/ / tube . setSampleId ( sampleId ) ;
/ /
/ /
/ / / / 处理试管
/ / processTube ( tube , tubeoff , consumableInfo , tubeSetting ) ;
/ / if ( ! tube . getErrors ( ) . isEmpty ( ) ) {
/ / log . warn ( "样本异常,跳过当前样本" ) ;
/ / UISender . txErrorMsg ( log , tube . getErrors ( ) . getFirst ( ) , "样本异常,跳过当前样本" ) ;
/ / break ;
/ / }
/ / docmd ( "HBOT复位" , hbotMoveExCtrlService : : moveQuickToZero ) ;
/ / }
/ / }
/ / tubeFeedingCtrlService . ejectTubeHolder ( ) ;
/ /
/ / incubationPlateProcess ( true ) ;
/ / incubationPlateStateMgr . resetAll ( ) ;
/ / UISender . txInfoPrompt ( log , "试剂实验一致性检测完成" ) ;
/ / }
/ /
/ / private void processTube ( Tube tube , Integer offset , ConsumableInfo consumableInfo , TubeSetting tubeSetting ) throws AppException {
/ /
/ / ProjBuildInInfo projBuildinInfo = projInfoMgrService . getProjBuildInInfo ( expectedProjId ) ;
/ / ProjExtInfoCard projExtInfoCard = projInfoMgrService . getProjExtInfoCard ( consumableInfo . lotid ) ;
/ /
/ /
/ / / / 拉取一个板夹到孵育盘
/ / var freeIncubationPos = incubationPlateStateMgr . takeOneIncubationIDLEPos (
/ / ( IncubatorPos pos ) - > {
/ / incubationPlateStateMgr . syncProjInfo ( pos , projBuildinInfo , projExtInfoCard ) ;
/ / incubationPlateStateMgr . syncSampleInfo ( pos , tube . getSampleInfo ( ) ) ;
/ / }
/ / ) ;
/ /
/ / / / 强制清空一下光学模组和孵育盘
/ / / / optScanModuleCtrlService . dropPlate ( ) ;
/ / / / optScanModuleCtrlService . pullPlate ( freeIncubationPos ) ;
/ / / / optScanModuleCtrlService . dropPlate ( ) ;
/ /
/ / docmd ( "丢反应板" , optScanModuleCtrlService : : dropPlate ) ;
/ / docmd ( "拉取反应板" , ( ) - > optScanModuleCtrlService . pullPlate ( freeIncubationPos ) ) ;
/ / docmd ( "丢反应板" , optScanModuleCtrlService : : dropPlate ) ;
/ /
/ /
/ / / / plateBoxCtrlService . pushPlateQuick ( consumableInfo . group , freeIncubationPos ) ;
/ / docmd ( "推入新的反应板" , ( ) - > plateBoxCtrlService . pushPlateQuick ( consumableInfo . group , freeIncubationPos ) ) ;
/ / / / 移动当前板夹到滴定位
/ / / / turnableMoveCtrlService . trunableMoveToDropLiquidPos ( freeIncubationPos ) ;
/ / docmd ( "移动到滴定位" , ( ) - > turnableMoveCtrlService . trunableMoveToDropLiquidPos ( freeIncubationPos ) ) ;
/ /
/ /
/ / docmd ( "样本处理" , ( ) - > {
/ / try {
/ / liquidOperationCtrService . setProjContext ( projBuildinInfo , projExtInfoCard ) ;
/ / var preProcessPos = new PreReactionPos ( ConsumableType . SmallBottleBuffer , consumableInfo . group , consumableInfo . pos ) ;
/ / / / 取tip
/ / tipOperationCtrlModule . tryTakeTip ( ( ) - > ! actionExecutor . isStopping ( ) ) ;
/ / actionExecutor . sleep ( 1 ) ;
/ / / / 刺破缓冲液
/ / hbotMoveExCtrlService . moveToLittleBufferPiercePos ( consumableInfo . group , consumableInfo . pos ) ;
/ / / / 取样品
/ / Assert . isTrue ( ! samplePos . equals ( A8kSamplePos . EmergencyTubePos ) , "samplePos cannot be EmergencyTubePos" ) ;
/ / Assert . isTrue ( ! samplePos . equals ( A8kSamplePos . BloodHTubePos ) , "samplePos cannot be BloodHTubePos" ) ;
/ / Assert . isTrue ( ! samplePos . equals ( A8kSamplePos . BloodSTubePos ) , "samplePos cannot be BloodSTubePos" ) ;
/ / liquidOperationCtrService . takeSampleToPreReactionPos ( samplePos , preProcessPos , takeSampleUl ) ;
/ / actionExecutor . sleep ( 1 ) ;
/ / / / 取混合液到预反应位
/ / liquidOperationCtrService . takePreReactionLiquid ( preProcessPos ) ;
/ / liquidOperationCtrService . dropLiquidToReactionPlate ( ) ;
/ / actionExecutor . sleep ( 1 ) ;
/ / incubationPlateStateMgr . startIncubating ( freeIncubationPos , System . currentTimeMillis ( ) , projBuildinInfo . reactionPlateIncubationTimeMin * 60 ) ;
/ / actionExecutor . sleep ( 1 ) ;
/ / } catch ( AppException e ) {
/ / if ( e . getError ( ) . eq ( A8kEcode . APPE_TAKE_SAMPLE_FAIL ) ) {
/ / hbotMoveExCtrlService . moveQuickToZero ( ) ;
/ / tube . setErrors ( ZList . of ( e . getError ( ) ) ) ;
/ / incubationPlateStateMgr . resetIncubatorPos ( freeIncubationPos ) ;
/ / / / 丢反应板
/ / optScanModuleCtrlService . forceDropPlate ( freeIncubationPos ) ;
/ / UISender . txErrorMsg ( log , e , "取样失败" ) ;
/ / } else {
/ / throw e ;
/ / }
/ / }
/ / } , ( ) - > {
/ / incubationPlateStateMgr . startIncubating ( freeIncubationPos , System . currentTimeMillis ( ) , projBuildinInfo . reactionPlateIncubationTimeMin * 60 ) ;
/ / } ) ;
/ /
/ /
/ / { / / 开始孵育
/ / }
/ / }
/ /
/ /
/ / private void incubationPlateProcess ( Boolean waittingForAll ) throws AppException {
/ / do {
/ / IncubationSubTank tankPos = incubationPlateStateMgr . getOneExpiredPlate ( ) ;
/ / if ( ! waittingForAll ) {
/ / if ( incubationPlateStateMgr . isHasEnoughIncubationIDLEPos ( 1 ) & & tankPos = = null ) {
/ / break ;
/ / }
/ / } else {
/ / if ( incubationPlateStateMgr . isAllIncubationSubTanksFree ( ) ) {
/ / break ;
/ / }
/ / }
/ /
/ / if ( tankPos ! = null ) {
/ /
/ / / / 拉取反应板到光学模组
/ / docmd ( "拉取反应板到光学模块" , ( ) - > { optScanModuleCtrlService . pullPlate ( tankPos . getPos ( ) ) ; } ) ;
/ /
/ / / / 设置光学模组状态
/ / optScanModuleStateMgr . changeOptScanModuleStateToPlateIsReady ( tankPos . projInfo , tankPos . toSampleInfo ( ) ) ;
/ / optScanModuleStateMgr . syncProjInfo ( tankPos . projBuildinInfo , tankPos . projExtInfoCard ) ;
/ / / / 复位孵育盘状态
/ / incubationPlateStateMgr . resetIncubatorPos ( tankPos . getPos ( ) ) ;
/ /
/ / / /
/ / / / 光学扫描
/ / / /
/ /
/ / / / 光学扫描
/ / optScanModuleStateMgr . changeOptScanModuleStateToScanning ( ) ;
/ / doOptScan ( ) ;
/ / / / 丢板
/ /
/ / docmd ( "丢弃反应板" , optScanModuleCtrlService : : dropPlate ) ;
/ /
/ / optScanModuleStateMgr . changeOptScanModuleStateToEmpty ( ) ;
/ / }
/ /
/ / actionExecutor . sleep ( 100 ) ;
/ / } while ( true ) ;
/ / }
/ /
/ / private void doOptScan ( ) throws AppException {
/ / / *
/ / * HsCrp只有一个项目
/ / * /
/ / Assert . isTrue ( Objects . equals ( expectedProjId , 1 ) , "1 != expectedProjId" ) ;
/ /
/ / int subProjIndex = 0 ;
/ /
/ / A8kOptType optType = optScanModuleStateMgr . getOptScanModule ( ) . getProjBuildinInfo ( ) . getOptType ( subProjIndex ) ;
/ / var buildInInfo = optScanModuleStateMgr . getOptScanModule ( ) . getProjBuildinInfo ( ) ;
/ / SampleInfo sampleInfo = optScanModuleStateMgr . getOptScanModule ( ) . getSampleInfo ( ) ;
/ / ProjInfo projInfo = optScanModuleStateMgr . getOptScanModule ( ) . getProjInfo ( ) ;
/ /
/ / / / a8kOptPeakInfo
/ / docmd ( "光学扫描" , ( ) - > {
/ / OptScanResult optScanResult = optScanModuleCtrlService . optScan ( buildInInfo , subProjIndex ) ;
/ / ReactionReport . ReactionResult result = A8kPeakAnalyzer . analysisPeakInfo ( sampleInfo , projInfo , subProjIndex , optScanResult . analysResult ) ;
/ /
/ / log . info ( "光学扫描结果: {}" , result ) ;
/ / reactionRecordMgrService . addRecord ( optScanModuleStateMgr . getOptScanModule ( ) . getSampleInfo ( ) , projInfo , ZList . of ( optScanResult ) , ZList . of ( result ) ) ;
/ / }
/ / , ( ) - > {
/ / OS . hsleep ( 1000 ) ;
/ / }
/ / ) ;
/ / }
/ /
/ /
/ /
/ / / *
/ / * Utils
/ / * /
/ /
/ / private void verifyTubeHolderSettingAndTubeHolderScanResult ( TubeHolderSetting tubeHolderSetting , TubeHolderScanResult scanResult ) throws AppException {
/ / A8kTubeHolderType tubeHolderType = A8kTubeHolderType . of ( scanResult . tubeHolderType ) ;
/ / if ( ! tubeHolderType . equals ( A8kTubeHolderType . BulletTube1P5 ) & & ! tubeHolderType . equals ( A8kTubeHolderType . BulletTube0P5 ) ) {
/ / throw AppException . of ( A8kEcode . APPE_TUBE_HOLDER_TYPE_IS_NOT_SUPPORT , "请使用子弹头1.5ml或者子弹头0.5ml试管架" ) ;
/ / }
/ /
/ / for ( int i = 0 ; i < tubeHolderSetting . tubeSettings . length ; i + + ) {
/ / TubeSetting tubeSetting = tubeHolderSetting . tubeSettings [ i ] ;
/ / if ( tubeSetting . projId . isEmpty ( ) & & ! scanResult . tube [ i ] . isTubeExist ) {
/ / continue ;
/ / }
/ /
/ / if ( tubeSetting . projId . isEmpty ( ) ) {
/ / throw AppException . of ( A8kEcode . APPE_TUBEHOLDER_SETTING_ERROR , String . format ( "试管[%d]缺少项目配置" , i + 1 ) ) ;
/ / }
/ /
/ / if ( ! scanResult . tube [ i ] . isTubeExist ) {
/ / throw AppException . of ( A8kEcode . APPE_TUBEHOLDER_SETTING_ERROR , String . format ( "位置[%d]未放入是试管" , i + 1 ) ) ;
/ / }
/ /
/ / }
/ / }
}