diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java index f01e342..5fd6038 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PLATE_OPT_SCAN.java @@ -107,7 +107,7 @@ public class PLATE_OPT_SCAN extends A8kStepAction { List scanResults = null; @Override public void beforeDoAction() { - optScanModuleStateMgrService.changeOptScanModuleStateTo(OptScanModuleState.SCANNING); + optScanModuleStateMgrService.changeOptScanModuleStateToScanning(); scanResults = null; } diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java index 3b46321..a8dc609 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/PROCESS_INCUBATE_COMPLETED_PLATE.java @@ -7,7 +7,10 @@ import a8k.service.app.appctrl.mainflowctrl.base.A8kStepAction; import a8k.service.app.appctrl.mainflowctrl.base.MainFlowProcesser; import a8k.service.app.appstate.statemgr.IncubationPlateStateMgrService; import a8k.service.app.appstate.statemgr.OptScanModuleStateMgrService; +import a8k.service.app.appstate.statemgr.ProjectContextMgrService; import a8k.service.app.appstate.type.IncubationSubTank; +import a8k.service.app.appstate.type.ProjectTaskContext; +import a8k.service.app.appstate.type.state.OptScanModuleState; import a8k.service.app.devicectrl.ctrlservice.OptScanModuleCtrlService; import a8k.service.test.state.VirtualDevice; import a8k.type.ecode.AppError; @@ -32,17 +35,24 @@ public class PROCESS_INCUBATE_COMPLETED_PLATE extends A8kStepAction { @Resource VirtualDevice virtualDevice; + // + // STATE + // @Resource IncubationPlateStateMgrService incubationPlateStateMgrService; @Resource OptScanModuleStateMgrService optScanModuleStateMgrService; + @Resource + ProjectContextMgrService projectContextMgrService; + // + // CTRL + // @Resource OptScanModuleCtrlService optScanModuleCtrlService; - @Resource - PublicAreaResourceMgr publicAreaResourceMgr; + PublicAreaResourceMgr publicAreaResourceMgr; public Boolean isReady() { @@ -50,19 +60,6 @@ public class PROCESS_INCUBATE_COMPLETED_PLATE extends A8kStepAction { && optScanModuleStateMgrService.isEmpty(); } - IncubationSubTank getToBeProcessedTank() { - return incubationPlateStateMgrService.getOneExpiredPlate(); - } - - - void doEjectPlate(IncubationSubTank tank) throws AppException { - if (virtualDevice.isEnable()) { - virtualDevice.doVirtualThings(String.format("推出反应板夹从%s到光学模组", tank.getPos())); - return; - } - optScanModuleCtrlService.pullPlate(tank.getPos()); - } - IncubationSubTank toBeProcesstank; @Override public List doAction() { @@ -91,8 +88,29 @@ public class PROCESS_INCUBATE_COMPLETED_PLATE extends A8kStepAction { if (!errors.isEmpty()) { return errors; } + ProjectTaskContext cxt = projectContextMgrService.findCxt(toBeProcesstank.getSampleId(), toBeProcesstank.projId); + optScanModuleStateMgrService.changeOptScanModuleStateToPlateIsReady(cxt.getProjBriefInfo(),cxt.getSampleInfo()); incubationPlateStateMgrService.resetIncubatorPos(toBeProcesstank.getPos()); return List.of(); } + + // + // Utils + // + + IncubationSubTank getToBeProcessedTank() { + return incubationPlateStateMgrService.getOneExpiredPlate(); + } + + + void doEjectPlate(IncubationSubTank tank) throws AppException { + if (virtualDevice.isEnable()) { + virtualDevice.doVirtualThings(String.format("推出反应板夹从%s到光学模组", tank.getPos())); + return; + } + optScanModuleCtrlService.pullPlate(tank.getPos()); + } + + } diff --git a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java index 10dc887..5567a66 100644 --- a/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java +++ b/src/main/java/a8k/service/app/appctrl/mainflowctrl/action/SEQ5_PROCESS.java @@ -102,9 +102,6 @@ public class SEQ5_PROCESS extends A8kStepAction { BoolCondition sampleIsReady = new BoolCondition(); BoolCondition sampleProcessFinished = new BoolCondition(); - //待设置状态的孵育盘 - List incubationStateCache = new ArrayList<>(); - // // UTILS @@ -123,7 +120,6 @@ public class SEQ5_PROCESS extends A8kStepAction { sampleIsReady.clear(); sampleProcessFinished.clear(); tubeStateMgrService.changeTubeStateToProcessing(); - incubationStateCache.clear(); } @@ -157,16 +153,14 @@ public class SEQ5_PROCESS extends A8kStepAction { for (ProjectTaskContext cxt : ctxs) { incubationPlateStateMgrService.setIncubationToErrorState(cxt.getIncubatorPos(), errors); + incubationPlateStateMgrService.startIncubating(cxt.getIncubatorPos(), cxt.getStartIncubatedTime(), cxt.getIncubatedTimeSec()); + incubationPlateStateMgrService.syncSampleInfo(cxt.getIncubatorPos(), cxt.getProjBriefInfo(),cxt.getSampleInfo()); } tubeStateMgrService.changeTubeStateToError(errors); return List.of(); } - tubeStateMgrService.changeTubeStateToProcessed(); - for (IncubationStateCache cache : incubationStateCache) { - incubationPlateStateMgrService.startIncubating(cache.pos, cache.startIncubatedTime, cache.incubatedTimeSec); - } return List.of(); } @@ -292,12 +286,8 @@ public class SEQ5_PROCESS extends A8kStepAction { deviceCtrlScripter.doSampleProcessPostProcess(cxt); } - - incubationStateCache.add( - new IncubationStateCache( - cxt.getIncubatorPos(), - System.currentTimeMillis(), - cxt.getProjInfo().getReactionPlateIncubationTimeMin() * 60)); + cxt.setStartIncubatedTime(System.currentTimeMillis()); + cxt.setIncubatedTimeSec(cxt.getProjInfo().getReactionPlateIncubationTimeMin() * 60); } } diff --git a/src/main/java/a8k/service/app/appstate/statemgr/IncubationPlateStateMgrService.java b/src/main/java/a8k/service/app/appstate/statemgr/IncubationPlateStateMgrService.java index 5ec2a96..0bda626 100644 --- a/src/main/java/a8k/service/app/appstate/statemgr/IncubationPlateStateMgrService.java +++ b/src/main/java/a8k/service/app/appstate/statemgr/IncubationPlateStateMgrService.java @@ -6,6 +6,7 @@ import a8k.service.app.appstate.type.IncubationSubTank; import a8k.service.app.appstate.type.SampleInfo; import a8k.service.app.appstate.type.state.IncubationSubTankState; import a8k.type.IncubatorPos; +import a8k.type.ProjBriefInfo; import a8k.type.ecode.AppError; import cn.hutool.core.util.ObjectUtil; import jakarta.annotation.Resource; @@ -126,13 +127,17 @@ public class IncubationPlateStateMgrService { } } - synchronized public void syncSampleInfo(IncubatorPos pos,SampleInfo sampleInfo){ + synchronized public void syncSampleInfo(IncubatorPos pos, ProjBriefInfo projBriefInfo, SampleInfo sampleInfo) { var subtanks = incubationPlate.subtanks; - subtanks[pos.off] - + subtanks[pos.off].sampleId = sampleInfo.sampleId; + subtanks[pos.off].projId = projBriefInfo.projId; + subtanks[pos.off].bloodType = sampleInfo.bloodType; + subtanks[pos.off].sampleBarcode = sampleInfo.sampleBarcode; + subtanks[pos.off].userid = sampleInfo.userid; + subtanks[pos.off].projInfo = projBriefInfo; } - synchronized public void startIncubating(IncubatorPos pos, Long startIncubatedTime,Integer incubatedTimeSec) { + synchronized public void startIncubating(IncubatorPos pos, Long startIncubatedTime, Integer incubatedTimeSec) { var subtanks = incubationPlate.subtanks; subtanks[pos.off].state = IncubationSubTankState.INCUBATING; subtanks[pos.off].startIncubatedTime = startIncubatedTime; diff --git a/src/main/java/a8k/service/app/appstate/statemgr/OptScanModuleStateMgrService.java b/src/main/java/a8k/service/app/appstate/statemgr/OptScanModuleStateMgrService.java index 67b8b48..a575334 100644 --- a/src/main/java/a8k/service/app/appstate/statemgr/OptScanModuleStateMgrService.java +++ b/src/main/java/a8k/service/app/appstate/statemgr/OptScanModuleStateMgrService.java @@ -2,7 +2,9 @@ package a8k.service.app.appstate.statemgr; import a8k.service.app.appstate.GStateService; import a8k.service.app.appstate.type.OptScanModule; +import a8k.service.app.appstate.type.SampleInfo; import a8k.service.app.appstate.type.state.OptScanModuleState; +import a8k.type.ProjBriefInfo; import cn.hutool.core.util.ObjectUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; @@ -11,7 +13,7 @@ import org.springframework.stereotype.Component; public class OptScanModuleStateMgrService { //光学模组状态 - private OptScanModule optScanModule = new OptScanModule(); + private final OptScanModule optScanModule = new OptScanModule(); synchronized public Boolean isEmpty() { return optScanModule.state.equals(OptScanModuleState.EMPTY); @@ -21,8 +23,31 @@ public class OptScanModuleStateMgrService { return ObjectUtil.cloneByStream(optScanModule); } - synchronized public void changeOptScanModuleStateTo(OptScanModuleState state) { - optScanModule.state = state; + synchronized public void changeOptScanModuleStateToEmpty() { + optScanModule.state = OptScanModuleState.EMPTY; + optScanModule.setIsErrorPlate(false); + optScanModule.setBloodType(null); + optScanModule.setSampleBarcode(""); + optScanModule.setUserid(""); + optScanModule.setProjInfo(null); + optScanModule.setSampleId(""); + optScanModule.setProjId(null); } + synchronized public void changeOptScanModuleStateToPlateIsReady(ProjBriefInfo projBriefInfo, SampleInfo sampleInfo) { + optScanModule.state = OptScanModuleState.PLATE_IS_READY; + optScanModule.setIsErrorPlate(false); + optScanModule.setBloodType(sampleInfo.bloodType); + optScanModule.setSampleBarcode(sampleInfo.sampleBarcode); + optScanModule.setUserid(sampleInfo.userid); + optScanModule.setProjInfo(projBriefInfo); + optScanModule.setSampleId(sampleInfo.sampleId); + optScanModule.setProjId(projBriefInfo.projId); + } + + synchronized public void changeOptScanModuleStateToScanning() { + optScanModule.state = OptScanModuleState.SCANNING; + } + + } diff --git a/src/main/java/a8k/service/app/appstate/statemgr/ProjectContextMgrService.java b/src/main/java/a8k/service/app/appstate/statemgr/ProjectContextMgrService.java index 113d743..3b16da3 100644 --- a/src/main/java/a8k/service/app/appstate/statemgr/ProjectContextMgrService.java +++ b/src/main/java/a8k/service/app/appstate/statemgr/ProjectContextMgrService.java @@ -33,7 +33,7 @@ public class ProjectContextMgrService { List toBeRemoved = new ArrayList<>(); for (ProjectTaskContext cxt : contexts) { if (cxt.getSampleInfo().sampleId.equals(sampleId)) { - log.info("移除项目处理上下文 sampleId:{} projId:{}", sampleId, cxt.getSampleInfo().projId); + log.info("移除项目处理上下文 sampleId:{} projId:{}", sampleId, cxt.getProjInfo().getProjId()); toBeRemoved.add(cxt); } } @@ -46,7 +46,6 @@ public class ProjectContextMgrService { synchronized public void newCxt(TubeHolder holder, Tube tube, Integer projId, ProjBuildinInfo buildinInfo) { SampleInfo sampleInfo = new SampleInfo(); sampleInfo.sampleId = tube.getSampleId(); - sampleInfo.projId = projId; sampleInfo.isHighTube = tube.getIsHighTube(); sampleInfo.isEmergency = tube.getIsEmergency(); sampleInfo.bloodType = tube.getBloodType(); @@ -68,7 +67,7 @@ public class ProjectContextMgrService { } } - synchronized public void newCxt(TubeHolder tubeHolder) { + synchronized public void newCxt(TubeHolder tubeHolder) { for (Tube tube : tubeHolder.getTubes()) { if (tube.getState().equals(TubeState.EMPTY)) { continue; @@ -77,7 +76,7 @@ public class ProjectContextMgrService { } } - synchronized public void updateCxt(TubeHolder holder, Tube tube, List buildinInfos) { + synchronized public void updateCxt(TubeHolder holder, Tube tube, List buildinInfos) { priRemoveCxt(tube.getSampleId()); newCxt(holder, tube, buildinInfos); } @@ -89,7 +88,7 @@ public class ProjectContextMgrService { synchronized public ProjectTaskContext findCxt(String sampleId, Integer projId) { for (ProjectTaskContext context : contexts) { SampleInfo sampleInfo = context.getSampleInfo(); - if (sampleInfo.sampleId.equals(sampleId) && sampleInfo.projId.equals(projId)) { + if (sampleInfo.sampleId.equals(sampleId) && context.getProjInfo().getProjId().equals(projId)) { return context; } } diff --git a/src/main/java/a8k/service/app/appstate/type/IncubationSubTank.java b/src/main/java/a8k/service/app/appstate/type/IncubationSubTank.java index 1c109c7..6cd5747 100644 --- a/src/main/java/a8k/service/app/appstate/type/IncubationSubTank.java +++ b/src/main/java/a8k/service/app/appstate/type/IncubationSubTank.java @@ -1,6 +1,7 @@ package a8k.service.app.appstate.type; import a8k.service.app.appstate.type.state.IncubationSubTankState; +import a8k.service.dao.type.ProjExtInfoCard; import a8k.type.IncubatorPos; import a8k.type.ecode.AppError; import a8k.type.type.BloodType; @@ -19,26 +20,26 @@ import java.util.List; public class IncubationSubTank implements Serializable { //位置 @Schema(description = "位置") - IncubatorPos pos; + public IncubatorPos pos; @Schema(description = "孵育状态") public IncubationSubTankState state = IncubationSubTankState.EMPTY; //孵育盘状态 //Info @Schema(description = "血液类型") - BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型 + public BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型 @Schema(description = "试管上的二维码") - String sampleBarcode = ""; //用于请求用户信息的条码ID + public String sampleBarcode = ""; //用于请求用户信息的条码ID @Schema(description = "用户输入的样本ID,不做逻辑,只做展示") - String userid = ""; //用户输入的样本ID,不做逻辑,只做展示 + public String userid = ""; //用户输入的样本ID,不做逻辑,只做展示 @Schema(description = "项目信息,用于显示") - ProjBriefInfo projInfo = new ProjBriefInfo(); //项目信息 + public ProjBriefInfo projInfo = new ProjBriefInfo(); //项目信息 @Schema(description = "样本ID,系统内部使用(不显示)") - String sampleId = ""; + public String sampleId = ""; @Schema(description = "项目ID") - Integer projId = 0; + public Integer projId = 0; // //孵育时间 diff --git a/src/main/java/a8k/service/app/appstate/type/OptScanModule.java b/src/main/java/a8k/service/app/appstate/type/OptScanModule.java index 79441d1..2b7ab9c 100644 --- a/src/main/java/a8k/service/app/appstate/type/OptScanModule.java +++ b/src/main/java/a8k/service/app/appstate/type/OptScanModule.java @@ -5,48 +5,29 @@ import a8k.service.app.appstate.type.state.OptScanModuleState; import a8k.type.type.BloodType; import a8k.type.ProjBriefInfo; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; import lombok.Getter; import java.io.Serializable; -@Getter +@Data public class OptScanModule implements Serializable { @Schema(description = "模块状态") public OptScanModuleState state = OptScanModuleState.EMPTY; //模块状态 - @Schema(description = "是否是错误板(标识当前光学模组中的反应板存在异常)") - Boolean isErrorPlate = false; //是否是错误板 + Boolean isErrorPlate = false; @Schema(description = "血液类型(用于显示)") - BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型 + BloodType bloodType = BloodType.WHOLE_BLOOD; @Schema(description = "样本条码(用于显示)") - String sampleBarcode = ""; //用于请求用户信息的条码ID + String sampleBarcode = ""; @Schema(description = "用户ID(用于显示)") - String userid = ""; //用户输入的样本ID,不做逻辑,只做展示 + String userid = ""; @Schema(description = "项目信息(用于显示)") ProjBriefInfo projInfo = new ProjBriefInfo(); - @Schema(description = "样本ID(后端使用)") - String sampleId = ""; + String sampleId = ""; @Schema(description = "项目ID") - Integer projId = 0; - - - public void syncCfg(IncubationSubTank tank) { - this.bloodType = tank.bloodType; - this.sampleBarcode = tank.sampleBarcode; - this.userid = tank.userid; - this.projInfo = tank.projInfo; - this.sampleId = tank.sampleId; - this.projId = tank.projId; - this.isErrorPlate = tank.state.equals(IncubationSubTankState.ERROR); - } - - public String getProjInfoStr() { - if (projInfo == null) { - return "null"; - } - return String.format("%s(%d)", projInfo.projShortName, projInfo.projId); - } + Integer projId = 0; } diff --git a/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java b/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java index b14ebd9..406fc60 100644 --- a/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java +++ b/src/main/java/a8k/service/app/appstate/type/ProjectTaskContext.java @@ -4,6 +4,7 @@ import a8k.a8kproj.optalgo.type.OptScanResult; import a8k.service.dao.type.ProjExtInfoCard; import a8k.service.dao.type.a8kidcard.zenum.A8kOptType; import a8k.type.IncubatorPos; +import a8k.type.ProjBriefInfo; import a8k.type.pos.*; import a8k.utils.ProjBuildinInfo; import a8k.utils.ProjInfo; @@ -26,6 +27,10 @@ public class ProjectTaskContext { List tipPos = null;//吸头位置 IncubatorPos incubatorPos = null;//孵育位置 + //孵育时间 + Long startIncubatedTime = 0L; //开始孵育时间 + Integer incubatedTimeSec = 0; //目标孵育时间 + //光学扫描结果 OptScanResult tOptScanResults = null; OptScanResult fOptScanResults = null; @@ -36,6 +41,22 @@ public class ProjectTaskContext { this.sampleInfo = sampleInfo; } + synchronized public void setStartIncubatedTime(Long startIncubatedTime) { + this.startIncubatedTime = startIncubatedTime; + } + + synchronized public void setIncubatedTimeSec(Integer incubatedTimeSec) { + this.incubatedTimeSec = incubatedTimeSec; + } + + synchronized public Long getStartIncubatedTime() { + return startIncubatedTime; + } + + synchronized public Integer getIncubatedTimeSec() { + return incubatedTimeSec; + } + synchronized public void setProjBuildinInfo(ProjBuildinInfo projBuildinInfo) { this.projBuildinInfo = projBuildinInfo; } @@ -113,5 +134,11 @@ public class ProjectTaskContext { projInfo.projExtInfoCard = ObjectUtil.cloneByStream((projExtInfoCard)); return projInfo; } + + synchronized public ProjBriefInfo getProjBriefInfo() { + return new ProjBriefInfo(projBuildinInfo.projBaseInfo.projId, projBuildinInfo.projBaseInfo.projName, projBuildinInfo.projBaseInfo.projShortName, projBuildinInfo.projBaseInfo.color); + } + + } diff --git a/src/main/java/a8k/service/app/appstate/type/SampleInfo.java b/src/main/java/a8k/service/app/appstate/type/SampleInfo.java index 0741be4..ea71038 100644 --- a/src/main/java/a8k/service/app/appstate/type/SampleInfo.java +++ b/src/main/java/a8k/service/app/appstate/type/SampleInfo.java @@ -6,14 +6,11 @@ import a8k.type.type.BloodType; import java.io.Serializable; public class SampleInfo implements Serializable { - public String sampleId = ""; //样本ID-系统生成-唯一标识一个样本 - public Integer projId = 0; + public String sampleId = ""; //样本ID-系统生成-唯一标识一个样本 public A8kTubeHolderType tubeHolderType; - - public Boolean isHighTube = false; - public Boolean isEmergency = false; - - public BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型 - public String sampleBarcode = ""; //用于请求用户信息的条码ID - public String userid = ""; //用户输入的样本ID,不做逻辑,只做展示 + public Boolean isHighTube = false; + public Boolean isEmergency = false; + public BloodType bloodType = BloodType.WHOLE_BLOOD; //血液类型 + public String sampleBarcode = ""; //用于请求用户信息的条码ID + public String userid = ""; //用户输入的样本ID,不做逻辑,只做展示 } diff --git a/src/main/java/a8k/unittest/TestOptAnalyzer.java b/src/main/java/a8k/unittest/TestOptAnalyzer.java index 2847f40..03baf0c 100644 --- a/src/main/java/a8k/unittest/TestOptAnalyzer.java +++ b/src/main/java/a8k/unittest/TestOptAnalyzer.java @@ -25,7 +25,6 @@ public class TestOptAnalyzer { ProjInfo projInfoContext = FakeProjInfoContextFactory.build(cfg); SampleInfo sampleInfo = new SampleInfo(); - sampleInfo.projId = cfg.projId; OptAlgoAnalysResult optAlgoAnalysResult = new OptAlgoAnalysResult(); optAlgoAnalysResult.pdR = 1.0; diff --git a/src/main/java/a8k/utils/ProjBuildinInfo.java b/src/main/java/a8k/utils/ProjBuildinInfo.java index a35bf97..b7a057e 100644 --- a/src/main/java/a8k/utils/ProjBuildinInfo.java +++ b/src/main/java/a8k/utils/ProjBuildinInfo.java @@ -3,6 +3,7 @@ package a8k.utils; import a8k.service.dao.type.ProjOptInfo; import a8k.service.dao.type.ProjectBaseInfo; import a8k.service.dao.type.a8kidcard.zenum.A8kReactionFlowType; +import a8k.type.ProjBriefInfo; import java.util.List; @@ -25,4 +26,5 @@ public class ProjBuildinInfo { public Integer getSubProjNum() { return projBaseInfo.subProjNum; } + } \ No newline at end of file