bool StandardInterventionDistributionEventCoordinator::visitIndividualCallback( IIndividualHumanEventContext *ihec, float & incrementalCostOut, ICampaignCostObserver * pICCO ) { { // Add real checks on demographics based on intervention demographic targetting. // Return immediately if we hit a non-distribute condition if( qualifiesDemographically( ihec ) == false ) { LOG_DEBUG("Individual not given intervention because not in target demographic\n"); return false; } LOG_DEBUG("Individual meets demographic targeting criteria\n"); if (!TargetedIndividualIsCovered(ihec)) { incrementalCostOut = 0; return false; } else { incrementalCostOut = 0; // instantiate and distribute intervention LOG_DEBUG_F( "Attempting to instantiate intervention of class %s\n", std::string(json::QuickInterpreter(intervention_config._json)["class"].As<json::String>()).c_str() ); IDistributableIntervention *di = _di->Clone(); release_assert(di); if (di) { di->AddRef(); di->Distribute( ihec->GetInterventionsContext(), pICCO ); di->Release(); // a bit wasteful for now, could cache it for the next fellow LOG_DEBUG_F("Distributed an intervention %p to individual %d at a cost of %f\n", di, ihec->GetSuid().data, incrementalCostOut); } } } return true; }
bool MultiInterventionEventCoordinator::visitIndividualCallback( IIndividualHumanEventContext *ihec, float & incrementalCostOut, ICampaignCostObserver * pICCO ) { // Less of this would need to be copied from the base class with a more thoughtful encapsulation of functions // In particular, only the give-intervention(s)-to-individual stuff inside the try statement is different. if( !demographic_restrictions.HasDefaultRestrictions() ) // don't waste any more time with checks if we're giving to everyone { if( qualifiesDemographically( ihec ) == false ) { LOG_DEBUG("Individual not given intervention because not in target demographic\n"); return false; } } LOG_DEBUG("Individual meets demographic targeting criteria\n"); if (!TargetedIndividualIsCovered(ihec)) { incrementalCostOut = 0; return false; } else { incrementalCostOut = 0; try { const json::Array & interventions_array = json::QuickInterpreter( intervention_config._json ).As<json::Array>(); LOG_DEBUG_F("interventions array size = %d\n", interventions_array.Size()); for( int idx=0; idx<interventions_array.Size(); idx++ ) { const json::Object& actualIntervention = json_cast<const json::Object&>(interventions_array[idx]); Configuration * tmpConfig = Configuration::CopyFromElement(actualIntervention); assert( tmpConfig ); // instantiate and distribute intervention LOG_DEBUG_F( "Attempting to instantiate intervention of class %s\n", std::string((*tmpConfig)["class"].As<json::String>()).c_str() ); IDistributableIntervention *di = InterventionFactory::getInstance()->CreateIntervention(tmpConfig); assert(di); delete tmpConfig; tmpConfig = nullptr; if (di) { if (!di->Distribute( ihec->GetInterventionsContext(), pICCO ) ) { di->Release(); // a bit wasteful for now, could cache it for the next fellow } LOG_DEBUG_F("Distributed an intervention %p to individual %d at a cost of %f\n", di, ihec->GetSuid().data, incrementalCostOut); } } } catch(json::Exception &e) { // ERROR: ::cerr << "exception casting intervention_config to array! " << e.what() << std::endl; throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, e.what() ); // ( "InterventionConfigs json problem: intervention_config is valid json but needs to be an array." ); } } return true; }
// The purpose of this function is to calculate the existing coverage of the intervention in question // and then to set the target coverage based on the error between measured and configured (for current time). void ReferenceTrackingEventCoordinator::preDistribute() { LOG_DEBUG_F( "preDistributed.\n" ); // Two variables that will be used by lambda function that's called for each individual; // these vars accumulate values across the population. NonNegativeFloat totalWithIntervention = 0.0f; NonNegativeFloat totalQualifyingPop = 0.0f; haves.clear(); // This is the function that will be called for each individual in this node (event_context) INodeEventContext::individual_visit_function_t fn = [ this, &totalWithIntervention, &totalQualifyingPop ](IIndividualHumanEventContext *ihec) { if( qualifiesDemographically( ihec ) ) { auto mcw = ihec->GetMonteCarloWeight(); totalQualifyingPop += mcw; // Check whether this individual has this intervention auto better_ptr = ihec->GetInterventionsContext(); std::string intervention_name = _di->GetName(); if( better_ptr->ContainsExistingByName( intervention_name ) ) { totalWithIntervention += mcw; haves.push_back( ihec->GetSuid().data ); } } }; // foreach node... for (auto event_context : cached_nodes) { event_context->VisitIndividuals( fn ); // does not return value, updates total existing coverage by capture } float dc = 0.0f; if( totalQualifyingPop > 0 ) { Fraction currentCoverageForIntervention = totalWithIntervention/totalQualifyingPop; NonNegativeFloat totalWithoutIntervention = totalQualifyingPop - totalWithIntervention; float default_value = 0.0f; float year = parent->GetSimulationTime().Year(); target_coverage = year2ValueMap.getValueLinearInterpolation(year, default_value); float totalToIntervene = ( target_coverage * totalQualifyingPop ) - totalWithIntervention; NO_LESS_THAN( totalToIntervene, 0 ); if( totalWithoutIntervention > 0 ) { dc = totalToIntervene / totalWithoutIntervention; } LOG_INFO_F( "Setting demographic_coverage to %f based on target_coverage = %f, currentCoverageForIntervention = %f, total without intervention = %f, total with intervention = %f.\n", dc, float(target_coverage), float(currentCoverageForIntervention), float(totalWithoutIntervention), float(totalWithIntervention) ); } else { LOG_INFO( "Setting demographic_coverage to 0 since 0 qualifying population.\n"); } demographic_restrictions.SetDemographicCoverage( dc ); }