import mapValues from 'lodash/mapValues' ; import type { Action , Error } from '../../types' ; import { HOME } from '../../robot-controls' ; import type { Mount , Slot } from '../types' ; import { actionTypes } from '../actions' ; import type { ConfirmProbedAction , PipetteCalibrationAction , LabwareCalibrationAction , CalibrationSuccessAction , CalibrationFailureAction , SetModulesReviewedAction , ReturnTipResponseAction , ReturnTipAction , SetDeckPopulatedAction , MoveToFrontAction , MoveToFrontResponseAction , ProbeTipAction , ProbeTipResponseAction , ConfirmLabwareAction , } from '../actions' ; type CalibrationRequestType = '' | 'MOVE_TO_FRONT' | 'PROBE_TIP' | 'MOVE_TO' | 'JOG' | 'PICKUP_AND_HOME' | 'DROP_TIP_AND_HOME' | 'CONFIRM_TIPRACK' | 'UPDATE_OFFSET' | 'SET_MODULES_REVIEWED' | 'RETURN_TIP' ; export interface CalibrationRequest { readonly type : CalibrationRequestType ; readonly mount ? : Mount ; readonly slot ? : Slot ; readonly inProgress : boolean ; readonly error : Error | null ; } export interface CalibrationState { readonly deckPopulated : boolean | null | undefined ; readonly modulesReviewed : boolean | null | undefined ; readonly probedByMount : { [ mount in Mount ] ? : boolean ; } ; readonly tipOnByMount : { [ mount in Mount ] ? : boolean ; } ; readonly confirmedBySlot : { [ slot in Slot ] ? : boolean ; } ; readonly calibrationRequest : CalibrationRequest ; } const { SET_DECK_POPULATED , MOVE_TO_FRONT , MOVE_TO_FRONT_RESPONSE , PROBE_TIP , PROBE_TIP_RESPONSE , CONFIRM_LABWARE , } = actionTypes ; const INITIAL_STATE = { deckPopulated : null , modulesReviewed : null , probedByMount : { } , tipOnByMount : { } , confirmedBySlot : { } , calibrationRequest : { type : '' , inProgress : false , error : null } , } ; export function calibrationReducer ( state = INITIAL_STATE , action ) { switch ( action . type ) { case 'robot:DISCONNECT_RESPONSE' : case 'robot:REFRESH_SESSION' : case 'protocol:UPLOAD' : return INITIAL_STATE ; case HOME : case 'robot:CLEAR_CALIBRATION_REQUEST' : return { ... state , calibrationRequest : { type : '' , inProgress : false , error : null } , } ; case 'robot:CONFIRM_PROBED' : return handleConfirmProbed ( state , action ) ; case 'robot:MOVE_TO' : return handleMoveTo ( state , action ) ; case 'robot:MOVE_TO_SUCCESS' : return handleMoveToSuccess ( state , action ) ; case 'robot:MOVE_TO_FAILURE' : return handleMoveToFailure ( state , action ) ; case 'robot:JOG' : return handleJog ( state , action ) ; case 'robot:JOG_SUCCESS' : return handleJogSuccess ( state , action ) ; case 'robot:JOG_FAILURE' : return handleJogFailure ( state , action ) ; case 'robot:PICKUP_AND_HOME' : return handlePickupAndHome ( state , action ) ; case 'robot:PICKUP_AND_HOME_SUCCESS' : return handlePickupAndHomeSuccess ( state , action ) ; case 'robot:PICKUP_AND_HOME_FAILURE' : return handlePickupAndHomeFailure ( state , action ) ; case 'robot:DROP_TIP_AND_HOME' : return handleDropTipAndHome ( state , action ) ; case 'robot:DROP_TIP_AND_HOME_SUCCESS' : return handleDropTipAndHomeSuccess ( state , action ) ; case 'robot:DROP_TIP_AND_HOME_FAILURE' : return handleDropTipAndHomeFailure ( state , action ) ; case 'robot:CONFIRM_TIPRACK' : return handleConfirmTiprack ( state , action ) ; case 'robot:CONFIRM_TIPRACK_SUCCESS' : return handleConfirmTiprackSuccess ( state , action ) ; case 'robot:CONFIRM_TIPRACK_FAILURE' : return handleConfirmTiprackFailure ( state , action ) ; case 'robot:UPDATE_OFFSET' : return handleUpdateOffset ( state , action ) ; case 'robot:UPDATE_OFFSET_SUCCESS' : return handleUpdateOffsetSuccess ( state , action ) ; case 'robot:UPDATE_OFFSET_FAILURE' : return handleUpdateOffsetFailure ( state , action ) ; case 'robot:SET_MODULES_REVIEWED' : return handleSetModulesReviewed ( state , action ) ; case 'robot:RETURN_TIP' : return handleReturnTip ( state , action ) ; case 'robot:RETURN_TIP_RESPONSE' : return handleReturnTipResponse ( state , action ) ; case SET_DECK_POPULATED : return handleSetDeckPopulated ( state , action as any ) ; case MOVE_TO_FRONT : return handleMoveToFront ( state , action as any ) ; case MOVE_TO_FRONT_RESPONSE : return handleMoveToFrontResponse ( state , action as any ) ; case PROBE_TIP : return handleProbeTip ( state , action as any ) ; case PROBE_TIP_RESPONSE : return handleProbeTipResponse ( state , action as any ) ; case CONFIRM_LABWARE : return handleConfirmLabware ( state , action as any ) ; } return state ; } function handleSetDeckPopulated ( state , action ) { return { ... state , deckPopulated : action . payload } ; } function handleSetModulesReviewed ( state , action ) { return { ... state , modulesReviewed : action . payload } ; } function handleMoveToFront ( state , action ) { if ( ! action . payload || ! action . payload . mount ) return state ; const { payload : { mount } , } = action ; return { ... state , deckPopulated : false , modulesReviewed : false , calibrationRequest : { type : 'MOVE_TO_FRONT' , inProgress : true , error : null , mount , } , } ; } function handleMoveToFrontResponse ( state , action ) { const error = action . error && action . payload ? action . payload : null ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error , } , } ; } function handleProbeTip ( state , action ) { if ( ! action . payload || ! action . payload . mount ) return state ; const { mount } = action . payload ; const probedByMount = { ... state . probedByMount } ; probedByMount [ mount ] = false ; return { ... state , calibrationRequest : { type : 'PROBE_TIP' , mount : mount , inProgress : true , error : null , } , probedByMount , } ; } function handleProbeTipResponse ( state , action ) { const { payload , error } = action ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error : error && payload ? payload : null , } , confirmedBySlot : { } , } ; } function handleConfirmProbed ( state , action ) { const nextProbedByMount = { ... state . probedByMount } ; nextProbedByMount [ action . payload ] = true ; return { ... state , probedByMount : nextProbedByMount } ; } function handleMoveTo ( state , action ) { const { mount , slot } = action . payload ; return { ... state , deckPopulated : true , modulesReviewed : true , calibrationRequest : { type : 'MOVE_TO' , inProgress : true , error : null , mount , slot , } , } ; } function handleMoveToSuccess ( state , action ) { const { calibrationRequest : { slot } , } = state ; if ( ! slot ) return state ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error : null , } , } ; } function handleMoveToFailure ( state , action ) { const { calibrationRequest : { slot } , } = state ; if ( ! slot ) return state ; const error = action . payload ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error : error , } , } ; } function handlePickupAndHome ( state , action ) { const { payload : { mount , slot } , } = action ; return { ... state , deckPopulated : true , modulesReviewed : true , calibrationRequest : { type : 'PICKUP_AND_HOME' , inProgress : true , error : null , mount , slot , } , } ; } function handlePickupAndHomeSuccess ( state , action ) { const { calibrationRequest , tipOnByMount } = state ; const { mount , slot } = calibrationRequest ; if ( ! slot || ! mount ) return state ; const nextTipOnByMount = mapValues ( tipOnByMount , ( ) => false ) ; nextTipOnByMount [ mount ] = true ; return { ... state , calibrationRequest : { ... calibrationRequest , inProgress : false , error : null , } , tipOnByMount : nextTipOnByMount , } ; } function handlePickupAndHomeFailure ( state , action ) { const { calibrationRequest : { mount , slot } , } = state ; if ( ! slot || ! mount ) return state ; const error = action . payload ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error , } , } ; } function handleDropTipAndHome ( state , action ) { const { payload : { mount , slot } , } = action ; return { ... state , calibrationRequest : { type : 'DROP_TIP_AND_HOME' , inProgress : true , error : null , mount , slot , } , } ; } function handleDropTipAndHomeSuccess ( state , action ) { const { calibrationRequest , tipOnByMount } = state ; const { mount , slot } = calibrationRequest ; if ( ! slot || ! mount ) return state ; const nextTipOnByMount = { ... tipOnByMount } ; nextTipOnByMount [ mount ] = false ; return { ... state , calibrationRequest : { ... calibrationRequest , inProgress : false , error : null , } , tipOnByMount : nextTipOnByMount , } ; } function handleDropTipAndHomeFailure ( state , action ) { const { calibrationRequest : { mount , slot } , } = state ; if ( ! slot || ! mount ) return state ; const error = action . payload ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error , } , } ; } function handleConfirmTiprack ( state , action ) { const { payload : { mount , slot } , } = action ; return { ... state , calibrationRequest : { type : 'CONFIRM_TIPRACK' , inProgress : true , error : null , mount , slot , } , } ; } function handleConfirmTiprackSuccess ( state , action ) { const { calibrationRequest , tipOnByMount , confirmedBySlot } = state ; const { mount , slot } = calibrationRequest ; if ( ! slot || ! mount ) return state ; const tipOn = action . payload . tipOn || false ; const nextTipOnByMount = { ... tipOnByMount } ; const nextConfirmedBySlot = { ... confirmedBySlot } ; nextTipOnByMount [ mount ] = tipOn ; nextConfirmedBySlot [ slot ] = true ; return { ... state , calibrationRequest : { ... calibrationRequest , inProgress : false , error : null , } , tipOnByMount : nextTipOnByMount , confirmedBySlot : nextConfirmedBySlot , } ; } function handleConfirmTiprackFailure ( state , action ) { const { calibrationRequest : { mount , slot } , } = state ; if ( ! slot || ! mount ) return state ; const error = action . payload ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error , } , } ; } function handleJog ( state , action ) { const { payload : { mount } , } = action ; return { ... state , calibrationRequest : { ... state . calibrationRequest , type : 'JOG' , inProgress : true , error : null , mount , } , } ; } function handleJogSuccess ( state , action ) { return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error : null , } , } ; } function handleJogFailure ( state , action ) { const error = action . payload ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error , } , } ; } function handleUpdateOffset ( state , action ) { const { payload : { mount , slot } , } = action ; return { ... state , calibrationRequest : { type : 'UPDATE_OFFSET' , inProgress : true , error : null , mount , slot , } , } ; } function handleUpdateOffsetSuccess ( state , action ) { const { calibrationRequest , confirmedBySlot } = state ; const { mount , slot } = calibrationRequest ; if ( ! slot || ! mount ) return state ; const nextConfirmBySlot = { ... confirmedBySlot } ; nextConfirmBySlot [ slot ] = true ; return { ... state , calibrationRequest : { ... calibrationRequest , inProgress : false , error : null , } , confirmedBySlot : nextConfirmBySlot , } ; } function handleUpdateOffsetFailure ( state , action ) { const { calibrationRequest : { mount , slot } , } = state ; if ( ! mount || ! slot ) return state ; const error = action . payload ; return { ... state , calibrationRequest : { ... state . calibrationRequest , inProgress : false , error , } , } ; } function handleConfirmLabware ( state , action ) { if ( ! action . payload || ! action . payload . labware ) return state ; const { labware : slot } = action . payload ; const confirmedBySlot = { ... state . confirmedBySlot } ; confirmedBySlot [ slot ] = true ; return { ... state , confirmedBySlot } ; } function handleReturnTip ( state , action ) { const { payload : { mount } , } = action ; return { ... state , calibrationRequest : { type : 'RETURN_TIP' , inProgress : true , error : null , mount , } , } ; } function handleReturnTipResponse ( state , action ) { const { calibrationRequest , tipOnByMount } = state ; const { mount } = calibrationRequest ; if ( ! mount ) return state ; const error = action . error && action . payload ? action . payload : null ; const nextTipOnByMount = { ... tipOnByMount } ; nextTipOnByMount [ mount ] = false ; return { ... state , calibrationRequest : { ... calibrationRequest , inProgress : false , error , } , tipOnByMount : nextTipOnByMount , } ; }