bool HIVSimpleDiagnostic::Distribute( IIndividualHumanInterventionsContext *context, ICampaignCostObserver * const pICCO ) { parent = context->GetParent(); LOG_DEBUG_F( "Individual %d is getting tested.\n", parent->GetSuid().data ); if( qualifiesToGetIntervention( parent ) ) { return BaseIntervention::Distribute( context, pICCO ); } else { expired = true ; return false ; } }
//returns false if didn't get the intervention bool NodeLevelHealthTriggeredIV::notifyOnEvent( IIndividualHumanEventContext *pIndiv, const EventTrigger& trigger ) { // ---------------------------------------------------------------------- // --- Ignore events for nodes that don't qualify due to their properties // ---------------------------------------------------------------------- if( !node_property_restrictions.Qualifies( parent->GetNodeContext()->GetNodeProperties() ) ) { return false; } IIndividualHuman *p_human = nullptr; if (s_OK != pIndiv->QueryInterface(GET_IID(IIndividualHuman), (void**)&p_human)) { throw QueryInterfaceException( __FILE__, __LINE__, __FUNCTION__, "pIndiv", "IIndividualHuman", "IIndividualHumanEventContext" ); } bool missed_intervention = false ; if( distribute_on_return_home && (trigger == EventTrigger::Emigrating) ) { if( p_human->AtHome() ) { // ------------------------------------------------------------------------------------------------ // --- If the individual is leaving his node of residence, then we want to keep track that he left // --- so that when he returns we can give him the interventions that he missed. // ------------------------------------------------------------------------------------------------ release_assert( event_occurred_while_resident_away.count( pIndiv->GetSuid() ) == 0 ); event_occurred_while_resident_away.insert( make_pair( pIndiv->GetSuid(), false ) ); } return false ; } else if( distribute_on_return_home && (trigger == EventTrigger::Immigrating) ) { if( p_human->AtHome() ) { // ------------------------------------------------------------------------------ // --- If the individual has returned home and they missed the intervention, then // --- we want them to get it, assuming they qualify. // ------------------------------------------------------------------------------ release_assert( event_occurred_while_resident_away.count( pIndiv->GetSuid() ) > 0 ); missed_intervention = event_occurred_while_resident_away[ pIndiv->GetSuid() ] ; event_occurred_while_resident_away.erase( pIndiv->GetSuid() ); if( missed_intervention ) { LOG_DEBUG_F( "Resident %d came home and intervention was distributed while away.\n", pIndiv->GetSuid().data ); } } if( !missed_intervention ) { return false ; } } else // the trigger event { // -------------------------------------------------------------------------------------------- // --- If this is one of the non-migrating events that they intervention is listening for // --- and this is not a blackout period, then record that the residents that are away missed // --- the intervention. // -------------------------------------------------------------------------------------------- if( blackout_time_remaining <= 0.0f ) { for( auto& rEntry : event_occurred_while_resident_away ) { rEntry.second = true ; } } } if( !blackout_event_trigger.IsUninitialized() && (blackout_period > 0.0) ) { if( (event_occured_list[ trigger.GetIndex() ].count( pIndiv->GetSuid().data ) > 0) || (!missed_intervention && (blackout_time_remaining > 0.0f)) ) { INodeTriggeredInterventionConsumer * pNTIC = NULL; if (s_OK != parent->QueryInterface(GET_IID(INodeTriggeredInterventionConsumer), (void**)&pNTIC) ) { throw QueryInterfaceException( __FILE__, __LINE__, __FUNCTION__, "parent", "INodeTriggeredInterventionConsumer", "INodeEventContext" ); } pNTIC->TriggerNodeEventObservers( pIndiv, blackout_event_trigger ); return false; } } LOG_DEBUG_F("Individual %d experienced event %s, check to see if they pass the conditions before distributing actual_intervention \n", pIndiv->GetInterventionsContext()->GetParent()->GetSuid().data, trigger.c_str() ); assert( parent ); assert( parent->GetRng() ); bool distributed = false; if( _di != nullptr ) { //initialize this flag by individual (not by node) m_disqualified_by_coverage_only = false; if( qualifiesToGetIntervention( pIndiv ) == false ) { LOG_DEBUG_F("Individual failed to qualify for intervention, m_disqualified_by_coverage_only is %d \n", m_disqualified_by_coverage_only); if (m_disqualified_by_coverage_only == true) { onDisqualifiedByCoverage( pIndiv ); } return false; } // Query for campaign cost observer interface from INodeEventContext *parent ICampaignCostObserver *iCCO; if (s_OK != parent->QueryInterface(GET_IID(ICampaignCostObserver), (void**)&iCCO)) { throw QueryInterfaceException( __FILE__, __LINE__, __FUNCTION__, "parent", "ICampaignCostObserver", "INodeEventContext" ); } // Huge performance win by cloning instead of configuring. IDistributableIntervention *di = _di->Clone(); release_assert( di ); di->AddRef(); distributed = di->Distribute( pIndiv->GetInterventionsContext(), iCCO ); if( distributed ) { std::string classname = GetInterventionClassName(); LOG_DEBUG_F("A Node level health-triggered intervention (%s) was successfully distributed to individual %d\n", classname.c_str(), pIndiv->GetInterventionsContext()->GetParent()->GetSuid().data ); } else { LOG_DEBUG_F( "Intervention not distributed?\n" ); } di->Release(); } else { release_assert( _ndi ); // Huge performance win by cloning instead of configuring. INodeDistributableIntervention *ndi = _ndi->Clone(); release_assert( ndi ); ndi->AddRef(); distributed = ndi->Distribute( parent, nullptr ); if( distributed ) { std::string classname = GetInterventionClassName(); LOG_INFO_F("Distributed '%s' intervention to node %d\n", classname.c_str(), parent->GetExternalId() ); } ndi->Release(); } if( distributed ) { if( blackout_on_first_occurrence ) { blackout_time_remaining = blackout_period ; } else { notification_occured = true ; } event_occured_list[ trigger.GetIndex() ].insert( pIndiv->GetSuid().data ); } return distributed; }