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 );

    }