Guide to calculate the run rate in a customization with sample code
This guide will step through the process of coding a Schedulability customization working together with a Required Capacity customization. If you are just getting started, please take a look at the following guides to getting started with customizations, learn about the schedulability customization point basics and the required capacity customization point basics
This walk through will show how to set up a Variable Run Rate customization. In order to specify the run rate based on item(s) produced we will need to provide the run rate data via UDF values on the resource object affected by the modification. The UDF values format is determined by the customer and must be uniform. A basic run rate UDF should have the item and rate values separated by a delimiter between item and rate and between combination items and rates.
Here is how a basic run rate UDF should look:
Single item and rate: ItemA_Rate1|ItemB_Rate2
Multiple items and rates: ItemA_Rate3_ItemB_Rate4|ItemC_Rate5
In this example, the rate is seen to be adjusted for each item depending on the set of items produced. When ItemA is produced alone it has Rate1. When ItemA is produced at the same time as ItemB both items now run at a different rates—ItemA runs at Rate3 and ItemB runs at Rate4.
Calculating Run Rate
First, the run rate data must be retrieved from the UDF values placed on the affected resources and be parsed from within the SimulationInitialization method inside of the SchedulabilityCustomization class itself and data provided to the RequiredCapacityCustomization class. Alternatively, the SimulationInitialization method inside of the SchedulabilityCustomization can trigger a SimulationInitialization method inside the RequiredCapacityCustomization class to perform the parsing.
Once the data is parsed it can be used inside the BeforeRequiredCapacityCalculation method of the RequiredCapacityCustomization class along with the provided input to determine the new run rate based on the item(s) being produced.
Once the new run rate is calculated it can be used to assign the CycleSpan value on the ChangableActivityValues reference object, effectively changing the run rate based on the item produced.
Note: The ChangableActivityValues object must be initialized prior to use.
Provided here is the SimulationInitialization method of the SchedulabilityCustomization class set to both parse the data and initialize the RequiredCapacityCustomization:
/// This function is called before the system performs a simulation and can be used to collect the run rate data
protected override void SimulationInitialization(ScenarioDetail a_sd, SchedulabilitySimulationInitializationHelper a_schedulabilityHelper, ScenarioDetail.SimulationType a_simulationType, ScenarioBaseT a_transmission)
//Collect the run rate data from resource UDF
foreach (Resource resource in a_sd.PlantManager.GetResourceList())
if (resource.GetUserFieldValue("runRateUDF", out object runRateInfo))
//Parse UDF data into a collection (runRateDataCollection)
if (m_requiredCapacityCust == null && a_sd.CustomizationInstances.SchedulerCustomizationsDictionary.ContainsKey(RequiredCapacityCust.CustomizationName))
m_requiredCapacityCust = (RequiredCapacityCust)a_sd.CustomizationInstances.SchedulerCustomizationsDictionary[RequiredCapacityCust.CustomizationName];
m_requiredCapacityCust?.SimulationInitialization(a_sd, a_simulationType, a_transmission, runRateDataCollection);
Provided here is the BeforeRequiredCapacityCalculation method of the RequiredCapacityCustomization class setup to determine the items used for use in the calculation of related run rate.
/// This function is used to determine the run rate based on item produced by operation
protected override void BeforeRequiredCapacityCalculation(long a_simClock, BaseActivity a_activity, BaseResource a_resource, ref ChangableActivityValues r_changeValues)
//Create the internal activity object from input
InternalActivity act = a_activity as InternalActivity;
//Create the operation object from input
InternalOperation op = act.Operation;
//Create the products collection object from input and determine products being produced
ProductsCollection products = act.Operation.Products;
for (var prodI = 0; prodI < products.Count; prodI++)
Product product = products[prodI];
//Initialize runRate to default
decimal calculatedRunRate = Decimal.MinValue;
//Use ProductsCollection and RunRateDataCollection data to assign new calculatedRunRate value
/*Place run rate calculation code here*/
//Initialize the update object from reference input and assign the new calculated run rate
r_changeValues = new ChangableActivityValues();
decimal hoursPerCycle = act.Operation.QtyPerCycle / calculatedRunRate;
decimal runRateTicks = hoursPerCycle * TimeSpan.FromHours(1).Ticks;
long runRateTicksLong = Convert.ToInt64(runRateTicks);
r_changeValues.CycleSpan = TimeSpan.FromTicks(runRateTicksLong);
To expand your customization, meet other types of scheduling requirements or to learn how to better navigate the PlanetTogether data objects explore the following articles: