Exemplo n.º 1
0
    bool ImportPressure::Configure( const Configuration * inputJson )
    {
        LOG_DEBUG_F( "%s\n", __FUNCTION__ );
        // TODO: specification for rate, seasonality, and age-biting function
        initConfigTypeMap( "Durations",              &durations,              IP_Durations_DESC_TEXT,               0, INT_MAX, 1 );
        initConfigTypeMap( "Daily_Import_Pressures", &daily_import_pressures, IP_Daily_Import_Pressures_DESC_TEXT , 0, FLT_MAX, 0 );

        bool configured = Outbreak::Configure( inputJson );

        if( configured && !JsonConfigurable::_dryrun )
        {
            if( durations.size() != (daily_import_pressures.size()) )
            {
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__,
                    "ImportPressure intervention requires Durations must be the same size as Daily_Import_Pressures" );
            }
            if( durations.size() <= 0 )
            {
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__,
                    "Empty Durations parameter in ImportPressure intervention." );
            }
            ConstructDistributionCalendar();
        }
        return configured;
    }
Exemplo n.º 2
0
 void CalendarEventCoordinator::BuildDistributionCalendar(
     std::vector<int> distribution_times,
     std::vector<float> distribution_coverages
 )  
 {
     NaturalNumber last_time = 0;
     while (!distribution_times.empty())
     {
         NaturalNumber time = distribution_times.front();
         if( time == last_time )
         {
             throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, ( std::string( "Duplicate distribution time entries: " ) + std::to_string( time ) ).c_str() );
         }
         else if( time < last_time )
         {
             std::stringstream msg;
             msg << "Distribution time mis-ordered: " << (int) last_time << " > " << (int) time << std::endl;
             throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, msg.str().c_str() );
         }
         Fraction coverage = distribution_coverages.front();
         distribution_times.erase( distribution_times.begin() );
         distribution_coverages.erase( distribution_coverages.begin() );
         times_and_coverages.insert( std::make_pair( time, coverage ) );
         last_time = time;
     }
 }
Exemplo n.º 3
0
    void
    DiagnosticTreatNeg::onPatientDefault()
    {
        LOG_DEBUG_F( "Individual %d got the test but defaulted, receiving Defaulters intervention without waiting for days_to_diagnosis (actually means days_to_intervention) \n", parent->GetSuid().data );

        // Important: Use the instance method to obtain the intervention factory obj instead of static method to cross the DLL boundary
        IGlobalContext *pGC = nullptr;
        const IInterventionFactory* ifobj = nullptr;
        if (s_OK == parent->QueryInterface(GET_IID(IGlobalContext), (void**)&pGC))
        {
            ifobj = pGC->GetInterventionFactory();
        }
        if (!ifobj)
        {
            throw NullPointerException( __FILE__, __LINE__, __FUNCTION__, "parent->GetInterventionFactoryObj()" );
        }


        if( !defaulters_event.IsUninitialized() )
        {
            if( defaulters_event != NO_TRIGGER_STR )
            {
                INodeTriggeredInterventionConsumer* broadcaster = nullptr;

                if (s_OK != parent->GetEventContext()->GetNodeEventContext()->QueryInterface(GET_IID(INodeTriggeredInterventionConsumer), (void**)&broadcaster))

                {

                    throw QueryInterfaceException( __FILE__, __LINE__, __FUNCTION__, "parent->GetEventContext()->GetNodeEventContext()", "INodeTriggeredInterventionConsumer", "INodeEventContext" );
                }
                broadcaster->TriggerNodeEventObserversByString( parent->GetEventContext(), defaulters_event );
            }
        }
        else if( defaulters_config._json.Type() != ElementType::NULL_ELEMENT )
        {
            auto tmp_config = Configuration::CopyFromElement(defaulters_config._json);

            // Distribute the defaulters intervention, right away (do not use the days_to_diagnosis
            IDistributableIntervention *di = const_cast<IInterventionFactory*>(ifobj)->CreateIntervention( tmp_config );

            delete tmp_config;
            tmp_config = nullptr;

            ICampaignCostObserver* pICCO;
            // Now make sure cost of the test-positive intervention is reported back to node
            if (s_OK == parent->GetEventContext()->GetNodeEventContext()->QueryInterface(GET_IID(ICampaignCostObserver), (void**)&pICCO) )
            {
                di->Distribute( parent->GetInterventionsContext(), pICCO );
                pICCO->notifyCampaignEventOccurred( (IBaseIntervention*)di, (IBaseIntervention*)this, parent );
            }
            else
            {
                throw QueryInterfaceException( __FILE__, __LINE__, __FUNCTION__, "parent->GetEventContext()->GetNodeEventContext()", "ICampaignCostObserver", "INodeEventContext" );
            }
        }
        else
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "neither event or config defined" );
        }
    }
Exemplo n.º 4
0
    void CheckSimType( const std::string& rSimTypeStr,
                       const json::Object& rJsonObject,
                       const char* pClassName )
    {
        json::QuickInterpreter sim_type_qi( rJsonObject[ "Sim_Types" ] );
        json::QuickInterpreter sim_type_array( sim_type_qi.As<json::Array>() );

        int num_types = sim_type_qi.As<json::Array>().Size() ;
        assert( num_types > 0 );

        if( std::string(sim_type_array[0].As<json::String>()) == std::string("*") )
        {
            // wild card means it is valid for any simulation type
            return ;
        }

        std::string supported ;
        for( int i = 0 ; i < num_types ; i++ )
        {
            std::string supported_sim_type = std::string(sim_type_array[i].As<json::String>()) ;
            if( rSimTypeStr == supported_sim_type )
            {
                return ;
            }
            supported += "'"+supported_sim_type + "', " ;
        }
        supported = supported.substr( 0, supported.length() - 2 );

        std::stringstream ss ;
        ss << "The '" << pClassName << "' intervention is not valid with the current 'Simulation_Type' (='" << rSimTypeStr << "').  " ;
        ss << "This intervention is only supported for the following simulation types: " << supported ;
        throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, ss.str().c_str() );
    }
    bool MultiInterventionEventCoordinator::HasNodeLevelIntervention() const
    {
        bool has_node_level_intervention = false;
        bool has_individual_level_intervention = false;

        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]);
            auto config = Configuration::CopyFromElement( actualIntervention, "campaign" );
            INodeDistributableIntervention *ndi = InterventionFactory::getInstance()->CreateNDIIntervention(config);
            if( ndi != nullptr )
            {
                has_node_level_intervention = true;
                ndi->Release();
            }
            else
            {
                has_individual_level_intervention = true;
            }
            delete config;
            config = nullptr;
        }

        if( has_node_level_intervention && has_individual_level_intervention )
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "You cannot mix individual and nodel-level interventions." );
        }

        return has_node_level_intervention;
    }
    void NodeLevelHealthTriggeredIVScaleUpSwitch::onDisqualifiedByCoverage(
                IIndividualHumanEventContext *pIndiv
    )
    {
        //if qualify by everything except demographic coverage, give the not_covered_individualintervention_config 
        // this intervention is the one phased out as the actual_individualintervention_config is phased in
        // if the not_covered_individualintervention_config is NULL, then there is no intervention to phase out
        LOG_DEBUG("The person qualified by everything except demographic coverage, give the not_covered_individualintervention_config \n");


        // 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" );
        }

        // Important: Use the instance method to obtain the intervention factory obj instead of static method to cross the DLL boundary
        //const IInterventionFactory* ifobj = dynamic_cast<NodeEventContextHost *>(parent)->GetInterventionFactoryObj();
        IGlobalContext *pGC = nullptr;
        const IInterventionFactory* ifobj = nullptr;
        if (s_OK == parent->QueryInterface(GET_IID(IGlobalContext), (void**)&pGC))
        {
            ifobj = pGC->GetInterventionFactory();
        }
        if (!ifobj)
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "The pointer to IInterventionFactory object is not valid (could be DLL specific)" );
        }

        const json::Array & interventions_array = json::QuickInterpreter(not_covered_intervention_configs._json).As<json::Array>();
        LOG_DEBUG_F("not_covered_intervention_configs array size = %d\n", interventions_array.Size());
       
        if (interventions_array.Size() == 0 )
        {
            LOG_DEBUG("nothing to phase out \n"); 
        }
        else
        {
            for( int idx=0; idx<interventions_array.Size(); idx++ )
            {
                const json::Object& notcoveredIntervention = json_cast<const json::Object&>(interventions_array[idx]);
                Configuration * tmpConfig = Configuration::CopyFromElement( notcoveredIntervention, "campaign" );
                assert( tmpConfig );
                LOG_DEBUG_F("NodeHTIScaleUpSwitch will distribute notcoveredintervention #%d\n", idx);

                IDistributableIntervention *di = const_cast<IInterventionFactory*>(ifobj)->CreateIntervention(tmpConfig); 
                delete tmpConfig;
                tmpConfig = nullptr;

                if( di )
                {
                    di->Distribute( pIndiv->GetInterventionsContext(), iCCO );
                    LOG_DEBUG("A Node level health-triggered intervention was successfully distributed, gave the not_covered_intervention_configs\n");
                    // It's not at all clear to me that we would incur cost at this point, but we could.
                    //iCCO->notifyCampaignExpenseIncurred( interventionCost, pIndiv );
                }
            }
         }       
    }
Exemplo n.º 7
0
    bool DiagnosticTreatNeg::Configure(
        const Configuration * inputJson
    )
    {
        EventOrConfig::Enum use_event_or_config;
        initConfig( "Event_Or_Config", use_event_or_config, inputJson, MetadataDescriptor::Enum("EventOrConfig", Event_Or_Config_DESC_TEXT, MDD_ENUM_ARGS( EventOrConfig ) ) );
        if( use_event_or_config == EventOrConfig::Event || JsonConfigurable::_dryrun )
        {
            initConfigTypeMap( "Negative_Diagnosis_Event", &negative_diagnosis_event, DTN_Negative_Diagnosis_Config_Event_DESC_TEXT );
            initConfigTypeMap( "Defaulters_Event", &defaulters_event, DTN_Defaulters_Diagnosis_Config_Event_DESC_TEXT );
        }

        if( use_event_or_config == EventOrConfig::Config || JsonConfigurable::_dryrun )
        {
            initConfigComplexType("Negative_Diagnosis_Config", &negative_diagnosis_config, DTN_Negative_Diagnosis_Config_DESC_TEXT, "Event_Or_Config", "Config" );
            initConfigComplexType("Defaulters_Config", &defaulters_config, DTN_Defaulters_Diagnosis_Config_DESC_TEXT, "Event_Or_Config", "Config" );
        }

        bool ret = SimpleDiagnostic::Configure( inputJson );
        if( ret  )
        {
            if( use_event_or_config == EventOrConfig::Config || JsonConfigurable::_dryrun )
            {
                InterventionValidator::ValidateIntervention( negative_diagnosis_config._json );
                InterventionValidator::ValidateIntervention( defaulters_config._json );
            }

            if( !JsonConfigurable::_dryrun && 
                negative_diagnosis_event.IsUninitialized() &&
                (negative_diagnosis_config._json.Type() == ElementType::NULL_ELEMENT) )
            {
                const char* msg = "You must define either Negative_Diagnosis_Event or Negative_Diagnosis_Config";
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, msg );
            }

            if( !JsonConfigurable::_dryrun && 
                defaulters_event.IsUninitialized() &&
                (defaulters_config._json.Type() == ElementType::NULL_ELEMENT) )
            {
                const char* msg = "You must define either Defaulters_Event or Defaulters_Config";
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, msg );
            }
        }
        return ret ;
    }
Exemplo n.º 8
0
    void DiagnosticTreatNeg::negativeTestDistribute()
    {

        LOG_DEBUG_F( "Individual %d tested 'negative', receiving negative intervention.\n", parent->GetSuid().data );
        // Important: Use the instance method to obtain the intervention factory obj instead of static method to cross the DLL boundary
        IGlobalContext *pGC = nullptr;
        const IInterventionFactory* ifobj = nullptr;
        if (s_OK == parent->QueryInterface(GET_IID(IGlobalContext), (void**)&pGC))
        {
            ifobj = pGC->GetInterventionFactory();
        }
        if (!ifobj)
        {
            throw NullPointerException( __FILE__, __LINE__, __FUNCTION__, "parent->GetInterventionFactoryObj()" );
        }

        if( use_event_or_config == EventOrConfig::Event )
        {
            INodeTriggeredInterventionConsumer* broadcaster = nullptr;

            if (s_OK != parent->GetEventContext()->GetNodeEventContext()->QueryInterface(GET_IID(INodeTriggeredInterventionConsumer), (void**)&broadcaster))

            {

                throw QueryInterfaceException( __FILE__, __LINE__, __FUNCTION__, "parent->GetEventContext()->GetNodeEventContext()", "INodeTriggeredInterventionConsumer", "INodeEventContext" );
            }
            broadcaster->TriggerNodeEventObservers( parent->GetEventContext(), negative_diagnosis_event );
        }
        else if( negative_diagnosis_config._json.Type() != ElementType::NULL_ELEMENT )
        {
            auto tmp_config = Configuration::CopyFromElement( negative_diagnosis_config._json, "campaign" );

            // Distribute the test-negative intervention
            IDistributableIntervention *di = const_cast<IInterventionFactory*>(ifobj)->CreateIntervention( tmp_config );

            delete tmp_config;
            tmp_config = nullptr;

            ICampaignCostObserver* pICCO;
            // Now make sure cost of the test-positive intervention is reported back to node
            if (s_OK == parent->GetEventContext()->GetNodeEventContext()->QueryInterface(GET_IID(ICampaignCostObserver), (void**)&pICCO) )
            {
                di->Distribute( parent->GetInterventionsContext(), pICCO );
                pICCO->notifyCampaignEventOccurred( (IBaseIntervention*)di, (IBaseIntervention*)this, parent );
            }
            else
            {
                throw QueryInterfaceException( __FILE__, __LINE__, __FUNCTION__, "parent->GetEventContext()->GetNodeEventContext()", "ICampaignCostObserver", "INodeEventContext" );
            }
        }
        else
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "neither event or config defined" );
        }
        expired = true;
    }
Exemplo n.º 9
0
    void GenericDrug::ResetForNextDose(float dt)
    {
        dosing_timer = time_between_doses;
        remaining_doses--;

        if (remaining_doses != 0 && time_between_doses < dt)
        {
            std::ostringstream oss;
            oss << "Time to next dose (" << time_between_doses << ") is shorter than the time-step, dt (" << dt << ")" << std::endl;
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, oss.str().c_str() );
        }
    }
Exemplo n.º 10
0
    void SimpleTransmissionGroups::AddPropertyValueListToPropertyToValueMap( const string& route, const string& property, const PropertyValueList_t& values )
    {
        if (transmissionRouteName.length() == 0)
        {
            transmissionRouteName = string(route);
        }
        else if (route != transmissionRouteName)
        {
            throw GeneralConfigurationException(__FILE__, __LINE__, __FUNCTION__, "SimpleTransmissionGroups only supports one route.");
        }

        propertyNameToValuesMap[property] = values;
        LOG_DEBUG_F( "Adding list of %d values to propertyNameToValuesMap for key/property %s\n", values.size(), property.c_str() );
    }
Exemplo n.º 11
0
    Kernel::StrainIdentity* Outbreak::GetNewStrainIdentity(INodeEventContext *context)
    {
        StrainIdentity *outbreak_strainID = nullptr;

        // Important: Use the instance method to obtain the intervention factory obj instead of static method to cross the DLL boundary
        // NO usage of GET_CONFIGURABLE(SimulationConfig)->number_substrains in DLL
        IGlobalContext *pGC = nullptr;
        const SimulationConfig* simConfigObj = nullptr;
        if (s_OK == context->QueryInterface(GET_IID(IGlobalContext), (void**)&pGC))
        {
            simConfigObj = pGC->GetSimulationConfigObj();
        }
        if (!simConfigObj)
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "The pointer to IInterventionFactory object is not valid (could be DLL specific)" );
        }

        if (( antigen < 0 ) || ( antigen >= simConfigObj->number_basestrains ))
        {
            throw IncoherentConfigurationException( __FILE__, __LINE__, __FUNCTION__, "antigen", antigen, "number_basestrains", simConfigObj->number_basestrains );
        }

        if ( genome < 0 )
        {
            int ss = simConfigObj->number_substrains;
            if (ss & (ss-1))
            {
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "Only supporting random genome generation for Number_Substrains as factor of two." );
            }
            unsigned int BARCODE_BITS = 0;
            while(ss >>= 1) ++BARCODE_BITS;
            uint32_t genome = context->GetRng()->ul() & ((1 << BARCODE_BITS)-1);
            //genome = context->GetRng()->i(simConfigObj->number_substrains);
            outbreak_strainID = _new_ StrainIdentity(antigen, genome);
            LOG_DEBUG_F("random genome generation... antigen: %d\t genome: %d\n", antigen, genome);
        }
Exemplo n.º 12
0
    bool
    StandardInterventionDistributionEventCoordinator::Configure(
        const Configuration * inputJson
    )
    {
        initializeInterventionConfig( inputJson );

        //initConfigTypeMap("Number_Distributions", &num_distributions, Number_Distributions_DESC_TEXT, -1, 1e6, -1 ); // by convention, -1 means no limit

        initConfigTypeMap("Number_Repetitions", &num_repetitions, Number_Repetitions_DESC_TEXT, -1, 1000, -1 );
        //if( num_repetitions > 1 ) // -1 = repeat without end, 0 is meaningless. want to think this one through more
        {
            initConfigTypeMap("Timesteps_Between_Repetitions", &tsteps_between_reps, Timesteps_Between_Repetitions_DESC_TEXT, -1, 10000 /*undefined*/, -1 /*off*/, "Number_Repetitions", "<>0" );
        }
        //initConfigTypeMap("Include_Departures", &include_emigrants, Include_Departures_DESC_TEXT, false );
        //initConfigTypeMap("Include_Arrivals", &include_immigrants, Include_Arrivals_DESC_TEXT, false );

        demographic_restrictions.ConfigureRestrictions( this, inputJson );


        bool retValue = JsonConfigurable::Configure( inputJson );
        if( retValue && !JsonConfigurable::_dryrun)
        {
            demographic_restrictions.CheckConfiguration();

            validateInterventionConfig( intervention_config._json );

            if( HasNodeLevelIntervention() )
            {
                // ---------------------------------------------------------------------------
                // --- If the user is attempting to define demographic restrictions when they
                // --- are using a node level intervention, then we need to error because these
                // --- restrictions are not doing anything.
                // ---------------------------------------------------------------------------
                if( !demographic_restrictions.HasDefaultRestrictions() )
                {
                    std::ostringstream msg ;
                    msg << "In StandardInterventionDistributionEventCoordinator, demographic restrictions such as 'Demographic_Coverage'\n";
                    msg << "and 'Target_Gender' do not apply when distributing node level interventions such as ";
                    msg << std::string( json::QuickInterpreter(intervention_config._json)["class"].As<json::String>() );
                    msg << ".\nThe node level intervention must handle the demographic restrictions.";
                    throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, msg.str().c_str() );
                }
            }
        }

        return retValue;
    }
    void
    CoverageByNodeJson::ConfigureFromJsonAndKey(
        const Configuration* inputJson,
        const std::string& key
    )
    {
        try {
            json::QuickInterpreter json_array( (*inputJson)[key].As<json::Array>() );
            for( unsigned int idx = 0; idx < (*inputJson)[key].As<json::Array>().Size(); idx++ )
            {
                json::QuickInterpreter node_coverage_pair( json_array[idx] );
                if (node_coverage_pair.As<json::Array>().Size() != 2)
                {
                    throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "Coverage_By_Node parameter needs to be an array of [nodeID,coverage] pairs." );
                }
                uint32_t nodeid = 0;
                float coverage = 0.0f;
                try {
                    nodeid = (uint32_t) node_coverage_pair[0].As<json::Number>();
                }
                catch( const json::Exception & )
                {
                    throw Kernel::JsonTypeConfigurationException( __FILE__, __LINE__, __FUNCTION__, "0", node_coverage_pair, "Expected NUMBER" );
                }
                try {
                    coverage = (float) node_coverage_pair[1].As<json::Number>();
                }
                catch( const json::Exception & )
                {
                    throw Kernel::JsonTypeConfigurationException( __FILE__, __LINE__, __FUNCTION__, "1", node_coverage_pair, "Expected NUMBER" );
                }

                LOG_DEBUG_F("Parsing Coverage_By_Node property: nodeid=%d, coverage=%0.2f.\n", nodeid, coverage);

                auto ret = node_coverage_map.insert(std::pair<uint32_t,float>(nodeid,coverage));
                if (ret.second == false)
                {
                    LOG_WARN_F("Duplicate coverage specified for node with ID=%d. Using first coverage value specified.\n", nodeid);
                }
            }
        }
        catch( const json::Exception & )
        {
            throw Kernel::JsonTypeConfigurationException( __FILE__, __LINE__, __FUNCTION__, key.c_str(), (*inputJson), "Expected ARRAY" );
        }
    }
    bool CoverageByNodeEventCoordinator::Configure( const Configuration * inputJson )
    {
        initConfigComplexType("Coverage_By_Node", &coverage_by_node, Coverage_By_Node_DESC_TEXT );
        bool configured = StandardInterventionDistributionEventCoordinator::Configure(inputJson);

        try
        {
            if( !JsonConfigurable::_dryrun )
            {
            }
        }
        catch( const json::Exception &e )
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, e.what() ); // ( "Coverage_By_Node json problem: Coverage_By_Node is valid json but needs to be an array of (nodeID,coverage) pairs." );
        }

        return configured;
    }
Exemplo n.º 15
0
    bool
    CalendarEventCoordinator::Configure(
        const Configuration * inputJson
    )
    {
        std::vector<int> distribution_times;
        std::vector<float> distribution_coverages;
        initConfigTypeMap("Distribution_Times", &distribution_times, Distribution_Times_DESC_TEXT, 1, INT_MAX, 0 );
        initConfigTypeMap("Distribution_Coverages", &distribution_coverages, Distribution_Coverages_DESC_TEXT, 0.0f, 1.0f, 0.0f );
        bool retValue = StandardInterventionDistributionEventCoordinator::Configure( inputJson );

        if(distribution_times.size() != distribution_coverages.size())
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "In a Calendar Event Coordinator, vector of distribution coverages must match vector of distribution times" );
        }

        BuildDistributionCalendar(distribution_times, distribution_coverages);

        return retValue;
    }
Exemplo n.º 16
0
    void NodeLevelHealthTriggeredIV::SetContextTo(INodeEventContext *context)
    {
        BaseNodeIntervention::SetContextTo( context );

        // Important: Use the instance method to obtain the intervention factory obj instead of static method to cross the DLL boundary
        //const IInterventionFactory* ifobj = dynamic_cast<NodeEventContextHost *>(parent)->GetInterventionFactoryObj();
        IGlobalContext *pGC = nullptr;
        const IInterventionFactory* ifobj = nullptr;
        if (s_OK == parent->QueryInterface(GET_IID(IGlobalContext), (void**)&pGC))
        {
            ifobj = pGC->GetInterventionFactory();
        }
        if (!ifobj)
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "The pointer to IInterventionFactory object is not valid (could be DLL specific)" );
        }
        if( (_di == nullptr) && (_ndi == nullptr) )
        {
            Configuration* config = nullptr;
            if( using_individual_config )
            {
                config = Configuration::CopyFromElement( (actual_individual_intervention_config._json), "campaign" );
            }
            else
            {
                config = Configuration::CopyFromElement( (actual_node_intervention_config._json), "campaign" );
            }

            _di = const_cast<IInterventionFactory*>(ifobj)->CreateIntervention( config );

            if( _di == nullptr )
            {
                _ndi = const_cast<IInterventionFactory*>(ifobj)->CreateNDIIntervention( config );
            }
            release_assert( (_di !=nullptr) || (_ndi != nullptr) );

            delete config;
            config = nullptr;
        }
    }
Exemplo n.º 17
0
    bool InputEIR::Configure( const Configuration * inputJson )
    {
        initConfig( "Age_Dependence", age_dependence, inputJson, MetadataDescriptor::Enum("Age_Dependence", IE_Age_Dependence_DESC_TEXT, MDD_ENUM_ARGS(AgeDependentBitingRisk)) );
        initConfigComplexType( "Monthly_EIR", &monthly_EIR, IE_Config_Type_DESC_TEXT);

        switch(age_dependence)
        {
            case AgeDependentBitingRisk::OFF:
                risk_function=nullptr;
                break;

            case AgeDependentBitingRisk::LINEAR:
                risk_function = SusceptibilityVector::LinearBitingFunction;
                break;

            case AgeDependentBitingRisk::SURFACE_AREA_DEPENDENT:
                risk_function = SusceptibilityVector::SurfaceAreaBitingFunction;
                break;

            default:
                if( !JsonConfigurable::_dryrun )
                {
                    throw BadEnumInSwitchStatementException( __FILE__, __LINE__, __FUNCTION__, 
                        "age_dependence", age_dependence, 
                        AgeDependentBitingRisk::pairs::lookup_key(age_dependence) );
                }
        }

        bool configured = BaseNodeIntervention::Configure( inputJson );

        if(monthly_EIR.size() != MONTHSPERYEAR && JsonConfigurable::_dryrun == false )
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, 
                "'Monthly_EIR' parameterizes the mean number of infectious bites experienced by an individual for each month of the year.  As such, it must be an array of EXACTLY length 12." );
        }

        return configured;
    }
Exemplo n.º 18
0
    void NodeEventCoordinator::UpdateNodes( float dt )
    {
        // Intervention class names for informative logging
        std::ostringstream intervention_name;
        intervention_name << std::string( json::QuickInterpreter(intervention_config._json)["class"].As<json::String>() );

        // Simplest NDI distribution without repetition
        INodeDistributableIntervention *ndi = nullptr;
        for(auto *nec : cached_nodes)
        {
            auto tmp_config = Configuration::CopyFromElement( intervention_config._json );
            ndi = InterventionFactory::getInstance()->CreateNDIIntervention( tmp_config );
            delete tmp_config;
            tmp_config = nullptr;
            if(ndi)
            {
                if (!ndi->Distribute( nec, this ) )
                {
                    ndi->Release(); // a bit wasteful for now, could cache it for the next fellow
                }
                else
                {
                    LOG_INFO_F("UpdateNodes() distributed '%s' intervention to node %d\n", intervention_name.str().c_str(), nec->GetId().data );
                }
            }
            else
            {
                // add NDI-only exception
                std::string err = "Unable to create an instance of " + intervention_name.str() + " as an INodeDistributableIntervention.";
                throw GeneralConfigurationException(__FILE__, __LINE__, __FUNCTION__, err.c_str());
            }
        }

        // Dispose
        if(ndi) ndi->Release();
        distribution_complete = true;
    }
    // copy/paste to remove single-intervention-specific logging
    // TODO: could be handled more gracefully
    // also not robust in case of array containing NTI not just ITI
    void MultiInterventionEventCoordinator::UpdateNodes( float dt )
    {
        // Only call VisitNodes on first call and if countdown == 0
        if( tsteps_since_last != tsteps_between_reps )
        {
            return;
        }

        int grandTotal = 0;
        int limitPerNode = -1;

        LOG_DEBUG_F("[UpdateNodes] limitPerNode = %d\n", limitPerNode);
        for (auto nec : cached_nodes)
        {
            try
            {
                // For now, distribute evenly across nodes. 
                int totalIndivGivenIntervention = nec->VisitIndividuals( this, limitPerNode );
                grandTotal += totalIndivGivenIntervention;
                LOG_INFO_F( "UpdateNodes() gave out %d interventions at node %d\n", totalIndivGivenIntervention, nec->GetId().data );
            }
            catch(json::Exception &e)
            {
                // ERROR: not ITI???
                // ERROR: ::cerr << "exception casting intervention_config to array! " << e.what() << std::endl;
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, e.what() ); // ( "Intervention_Configs json problem: intervention_config is valid json but needs to be an array." );
            }
        }

        tsteps_since_last = 0;
        num_repetitions--;
        if( num_repetitions == 0 )
        {
            distribution_complete = true; // we're done, signal disposal ok
        }
    }
Exemplo n.º 20
0
    bool MultiInterventionDistributor::Distribute(IIndividualHumanInterventionsContext *context, ICampaignCostObserver * const pICCO )
    {
        // ----------------------------------------------------------------------------------
        // --- Putting this here because we don't want anything to happen if we are aborting
        // ----------------------------------------------------------------------------------
        if( AbortDueToDisqualifyingInterventionStatus( context->GetParent() ) )
        {
            return false;
        }

        // Important: Use the instance method to obtain the intervention factory obj instead of static method to cross the DLL boundary
        IGlobalContext *pGC = nullptr;
        const IInterventionFactory* ifobj = nullptr;
        release_assert(context->GetParent());
        if (s_OK == context->GetParent()->QueryInterface(GET_IID(IGlobalContext), (void**)&pGC))
        {
            ifobj = pGC->GetInterventionFactory();
        }
        if (!ifobj)
        {
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, "The pointer to IInterventionFactory object is not valid (could be DLL specific)" );
        } 

        try
        {
            // Parse intervention_list
            const json::Array & interventions_array = json::QuickInterpreter(intervention_list._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, "campaign" );
                assert( tmpConfig );

                // Instantiate and distribute interventions
                LOG_DEBUG_F( "Attempting to instantiate intervention of class %s\n", std::string((*tmpConfig)["class"].As<json::String>()).c_str() );
                IDistributableIntervention *di = const_cast<IInterventionFactory*>(ifobj)->CreateIntervention(tmpConfig);
                if (di)
                {
                    if (!di->Distribute( context, pICCO ) )
                    {
                        di->Release();
                    }
                }
                else
                {
                    INodeDistributableIntervention* ndi = const_cast<IInterventionFactory*>(ifobj)->CreateNDIIntervention( tmpConfig );
                    release_assert(ndi);
                    if( !ndi->Distribute( context->GetParent()->GetEventContext()->GetNodeEventContext(), nullptr ) )
                    {
                        ndi->Release();
                    }
                }
                delete tmpConfig;
                tmpConfig = nullptr;
            }
        }
        catch(json::Exception &e)
        {
            // ERROR: ::cerr << "exception casting intervention_config to array! " << e.what() << std::endl;
            throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, e.what() ); // ( "Intervention_List json problem: intervention_list is valid json but needs to be an array." );
        }

        // Nothing more for this class to do...
        Expire();

        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;
    }
Exemplo n.º 22
0
    void CalendarEventCoordinator::UpdateNodes( float dt )
    {
        // Now issue events as they come up, including anything currently in the past or present
        while( parent->GetSimulationTime().time >= times_and_coverages.begin()->first)
        {
            int grandTotal = 0;
            int limitPerNode = -1;

            // intervention class names for informative logging
            std::ostringstream intervention_name;
            intervention_name << std::string( json::QuickInterpreter(intervention_config._json)["class"].As<json::String>() );

            auto qi_as_config = Configuration::CopyFromElement( (intervention_config._json), "campaign" );
            _di = InterventionFactory::getInstance()->CreateIntervention(qi_as_config);
            // including deeper information for "distributing" interventions (e.g. calendars)
            formatInterventionClassNames( intervention_name, &json::QuickInterpreter(intervention_config._json) );

            // Only visit individuals if this is NOT an NTI. Check...
            // Check to see if intervention is an INodeDistributable...
            INodeDistributableIntervention *ndi = InterventionFactory::getInstance()->CreateNDIIntervention(qi_as_config);
            INodeDistributableIntervention *ndi2 = nullptr;

            LOG_DEBUG_F("[UpdateNodes] limitPerNode = %d\n", limitPerNode);
            for (auto nec : cached_nodes)
            {
                if (ndi)
                {
                    throw NotYetImplementedException( __FILE__, __LINE__, __FUNCTION__ );
#if 0
                    ndi2 = InterventionFactory::getInstance()->CreateNDIIntervention( qi_as_config );
                    if(ndi2)
                    {
                        float duration = -1;
                        if (times_and_coverages.size() > 1)
                        {
                            auto iter = times_and_coverages.end(); 
                            //A node-targeted intervention issued through the calender coordinator lasts until the next NDI.  
                            //Is there an overlap of one day here?  Should there be a -1?
                            duration = (float)(prev(iter,2)->first - prev(iter, 1)->first);   
                        }
                        
                        INodeDistributableInterventionParameterSetterInterface* pNDIPSI = nullptr;
                        if (s_OK == ndi2->QueryInterface(GET_IID(INodeDistributableInterventionParameterSetterInterface), (void**)&pNDIPSI) )
                        {
                            pNDIPSI->SetDemographicCoverage(times_and_coverages.begin()->second);
                            pNDIPSI->SetMaxDuration(duration);
                        }
                                                
                        if (!ndi2->Distribute( nec, this ) )
                        {
                            LOG_INFO_F("UpdateNodes() distributed '%s' intervention to node %d\n", intervention_name.str().c_str(), nec->GetId().data );
                        }
                        ndi2->Release();
                    }
#endif
                }
                else
                {
                    try
                    {
                        // For now, distribute evenly across nodes. 
                        int totalIndivGivenIntervention = nec->VisitIndividuals( this, limitPerNode );
                        grandTotal += totalIndivGivenIntervention;
                        LOG_INFO_F( "UpdateNodes() gave out %d interventions at node %d\n", totalIndivGivenIntervention, nec->GetId().data );
                    }                   
                    catch( const json::Exception &e )
                    {
                        throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, e.what() );
                    }
                }
            }
            delete qi_as_config;
            qi_as_config = nullptr;

            times_and_coverages.erase(times_and_coverages.begin());
            LOG_DEBUG_F("%d Distributions remaining from CalendarEventCoordinator\n", times_and_coverages.size());
            if( times_and_coverages.empty() )
            {
                LOG_DEBUG_F("Signaling for disposal of CalendarEventCoordinator\n");
                distribution_complete = true; // we're done, signal disposal ok
                break;
            }
        }
        return;
    }
    bool CommunityHealthWorkerEventCoordinator::Configure( const Configuration * inputJson )
    {
        initConfigTypeMap("Duration",                &m_CoordinatorDaysRemaining, CHW_Duration_DESC_TEXT,                0.0f,     FLT_MAX, FLT_MAX );
        initConfigTypeMap("Max_Distributed_Per_Day", &m_MaxDistributedPerDay,     CHW_Max_Distributed_Per_Day_DESC_TEXT, 1,        INT_MAX, INT_MAX );
        initConfigTypeMap("Waiting_Period",          &m_QueueWaitingPeriodDays,   CHW_Waiting_Period_DESC_TEXT,          0.0f,     FLT_MAX, FLT_MAX );
        initConfigTypeMap("Days_Between_Shipments",  &m_DaysBetweenShipments,     CHW_Days_Between_Shipments_DESC_TEXT,  1.0f,     FLT_MAX, FLT_MAX );
        initConfigTypeMap("Amount_In_Shipment",      &m_AmountInShipment,         CHW_Amount_In_Shipment_DESC_TEXT,      0,        INT_MAX, INT_MAX );
        initConfigTypeMap("Max_Stock",               &m_MaxStock,                 CHW_Max_Stock_DESC_TEXT,               0,        INT_MAX, INT_MAX );

        DurationDistribution initial_amount;
        initial_amount.SetTypeNameDesc( "Initial_Amount_Distribution_Type", CHW_Initial_Amount_Distribution_Type_DESC_TEXT );
        initial_amount.AddSupportedType( DistributionFunction::FIXED_DURATION,       "Initial_Amount",      CHW_Initial_Amount_DESC_TEXT,      "", "" );
        initial_amount.AddSupportedType( DistributionFunction::UNIFORM_DURATION,     "Initial_Amount_Min",  CHW_Initial_Amount_Min_DESC_TEXT,  "Initial_Amount_Max",     CHW_Initial_Amount_Max_DESC_TEXT );
        initial_amount.AddSupportedType( DistributionFunction::GAUSSIAN_DURATION,    "Initial_Amount_Mean", CHW_Initial_Amount_Mean_DESC_TEXT, "Initial_Amount_Std_Dev", CHW_Initial_Amount_Std_Dev_DESC_TEXT );
        initial_amount.AddSupportedType( DistributionFunction::EXPONENTIAL_DURATION, "Initial_Amount",      CHW_Initial_Amount_DESC_TEXT,      "", "" );

        initial_amount.Configure( this, inputJson );
        m_DemographicRestrictions.ConfigureRestrictions( this, inputJson );

        initConfigTypeMap("Trigger_Condition_List", &m_TriggerConditionList, CHW_Trigger_Condition_List_DESC_TEXT );

        initConfigComplexType( "Node_Property_Restrictions", &m_NodePropertyRestrictions, CHW_Node_Property_Restriction_DESC_TEXT );

        initConfigComplexType( "Intervention_Config", &m_InterventionConfig, CHW_Intervention_Config_DESC_TEXT );

        bool retValue = JsonConfigurable::Configure( inputJson );

        if( retValue && !JsonConfigurable::_dryrun)
        {
            // ------------------------------------------------------
            // --- Check that the intervention exists and initialize
            // ------------------------------------------------------
            InterventionValidator::ValidateIntervention( m_InterventionConfig._json, inputJson->GetDataLocation() );

            m_DemographicRestrictions.CheckConfiguration();

            Configuration* qi_as_config = Configuration::CopyFromElement( m_InterventionConfig._json );

            m_InterventionName = std::string( json::QuickInterpreter(m_InterventionConfig._json)["class"].As<json::String>() );

            m_pInterventionIndividual = InterventionFactory::getInstance()->CreateIntervention( qi_as_config );
            if( m_pInterventionIndividual == nullptr )
            {
                m_pInterventionNode = InterventionFactory::getInstance()->CreateNDIIntervention( qi_as_config );
            }
            
            delete qi_as_config;
            qi_as_config = nullptr;

            // ---------------------------------------------------------------------------
            // --- If the user is attempting to define demographic restrictions when they
            // --- are using a node level intervention, then we need to error because these
            // --- restrictions are not doing anything.
            // ---------------------------------------------------------------------------
            if( (m_pInterventionNode != nullptr) && !m_DemographicRestrictions.HasDefaultRestrictions() )
            {
                std::ostringstream msg ;
                msg << "In CommunityHealthWorkerEventCoordinator, demographic restrictions such as 'Demographic_Coverage'\n";
                msg << "and 'Target_Gender' do not apply when distributing nodel level interventions such as ";
                msg << m_InterventionName;
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, msg.str().c_str() );
            }
            else if( (m_pInterventionNode == nullptr) && (m_NodePropertyRestrictions.Size() > 0) )
            {
                std::ostringstream msg;
                msg << "In CommunityHealthWorkerEventCoordinator, Node_Property_Restrictions only works when distributing node-level interventions.\n";
                msg << m_InterventionName << " is a individual-targeted intervention.\n";
                throw GeneralConfigurationException( __FILE__, __LINE__, __FUNCTION__, msg.str().c_str() );
            }

            for( auto& event_name : m_RemoveIndividualEventList )
            {
                m_TriggerConditionList.push_back( event_name );
            }

            // --------------------
            // --- Initialize Stock
            // --------------------
            initial_amount.CheckConfiguration();
            m_CurrentStock = int( initial_amount.CalculateDuration() + 0.5); // round up
            if( m_CurrentStock > m_MaxStock )
            {
                m_CurrentStock = m_MaxStock;
            }

            m_DaysToNextShipment = int( float(m_CurrentStock) / float(m_MaxDistributedPerDay) );
            if( m_DaysToNextShipment > m_DaysBetweenShipments )
            {
                m_DaysToNextShipment = m_DaysBetweenShipments;
            }
        }

        return retValue;
    }