In my previous blog, I discussed the newly available in TP2016.0 (16.0.6187.2) API feature of calibration. Now reliable and repeatable calibrations can be set up through the TruePlanning API easily and quickly. For most users the standard calibration usage will be all they need. That said, there are some users who would like to use a feature that is available the TruePlanning Calibration GUI: the ability to calibrate multiple inputs in one calibration. 

The most common reason to use a constant in a calibration is to find a single value, such as Organizational Productivity, across multiple Cost Objects that yields a specific value on a parent Cost Objects like an Assembly. Organizational Productivity is a prime target for this because it is an input that reflects the nature of an organization’s ability to produce software and should be consistent across Software Component under the same Assembly.

In the TruePlanning Calibration GUI this is accomplished by selecting a constant instead of a specific input for a Cost Object. When a constant is chosen and the calibration is run, the constant is updated with a new value with each iteration of the calibration, and this value is then set on all inputs that are linked to the constant. In the TruePlanning Calibration GUI the constant must already exist and be assigned for it to be used.

In the TruePlanning API, the Constant object supports the ability to select a constant at the input value instead of a specific Input object. Where it really gets interesting is that the API also supports the creation and assignment of constants as well, so a new project can be created, a constant can be created in that project, and that constant can be assigned to inputs, and then used in a calibration… all through the API.

Below is a sample VBA Macro subroutine that shows how to work with constants and calibrations.  It performs the following steps: 

  1. Opens as existing project.
  2. Creates a new Constant object and gives it a name.
  3. Sets a value for the new constant.
  4. Creates a "variant" object to reference the new Constant object. This step is required because a "Variant" type is required by "SetLink" method on TruePlanningApi_16_0.Input objects.
  5. The code then loops through the project’s PBS looking for a specific Cost Object by name. A reference to the targeted Cost Object is held in a TruePlanningApi_16_0.CostObject variable.
  6. For each child of the targeted parent Cost Object, the newly created constant is assigned using the “SetLink” method and the “Variant” that references the constant.
  7.  A new Calibration object is created.
  8.  The required information to perform a calibration is set on the Calibration object.
  9.  The “Sheet1” worksheet is selected to hold the output of the calibrations.
  10.  A look from 1 to 10 is executed.
  11.  For each loop the calibration is executed with a new target value.  The results of the calibration are output to Excel.
  12.  The project is saved with a new name so the results can be viewed. 

Public Sub Calib_NewConst_TestSub()


   Dim app As TruePlanningApi_16_0.Application

   Set app = New TruePlanningApi_16_0.Application


   Dim p As TruePlanningApi_16_0.Project

   Set p = app.OpenProject("c:\a\testProject.tpprj")



   ' create new constant


   Dim newConst As TruePlanningApi_16_0.Constant

   Set newConst = p.Constants.New("NewTestConst")

   newConst.Value = 2



   '' NOTE:

   '' Because the "SetLink" method will eventually accept different types of objects

   '' the value passed into needs to be a Variant

   '' so we will put the constant object we just create into a Variant object here

   '' if you try to use the Constant object in the "SetLink" call Excel will explode

   Dim constV As Variant

   Set constV = newConst


   Dim targetCOName As String

   targetCOName = "SoftwareAssembly"


   Dim targetAsmCO As TruePlanningApi_16_0.CostObject


   Dim targetOutputPath As String


   Dim parentLevel As Long

   Dim stillLooking As Boolean

   stillLooking = False


   Dim co As TruePlanningApi_16_0.CostObject

   For Each co In p.CostObjects


      If ((stillLooking = True) And (co.Level <= parentLevel)) Then

         stillLooking = False 'hit a sibling or parent of the target assembly

      End If



      If (co.Name = targetCOName) Then


         ' in this example, we are targeting the same CO for the input and the output value, but the output value could belong to any CO in the PBS,

         ' just remember to make sure the input you are altering impacts the selected output Cost Object

         targetOutputPath = co.Path

         stillLooking = True

         parentLevel = co.Level

      End If


      If ((stillLooking = True) And (co.Level > parentLevel)) Then

         ' set constant for input on children


         If (co.Definition.InternalName = "Software Component") Then

            Dim targetInput As TruePlanningApi_16_0.Input

            Set targetInput = co.Inputs.ItemByName("Organizational Productivity")



            '' NOTE: use the Varaint with the Constant object in "SetLink"

            Call targetInput.SetLink(LinkTypeConstant, constV)


         End If

      End If

   Next co



   Dim cTest As TruePlanningApi_16_0.Calibration

   Set cTest = p.Calibrations.New("COne")


   'cTest.Input = tInput

   cTest.SetConstant newConst


   targetOutputPath = targetOutputPath & "::Labor Requirement"

   cTest.CostObjectOutput = targetOutputPath

   cTest.Tolerance = 1  ' this is a % value 1 = 1%, 10 = 10%

   cTest.MaxIterations = 100


   ' Initial Adapted Size: 6821

   ' Initial Labor Requirement: 61.5

   Dim ws As Worksheet

   Set ws = ActiveWorkbook.Worksheets("Sheet1")



   Dim startTargetLaborReqForCSCI As Long

   startTargetLaborReqForCSCI = 9000


   Dim cnt As Long

   cnt = 2

   Dim laborRateScale As Long

   For laborRateScale = 0 To 10

      Dim lr As Double

      lr = startTargetLaborReqForCSCI + (laborRateScale * 100)

      cTest.Target = lr



        ws.Cells(cnt, 1).Value = cTest.InputName

        ws.Cells(cnt, 2).Value = cTest.CalibratedInput

        ws.Cells(cnt, 3).Value = cTest.OutputName

        ws.Cells(cnt, 4).Value = cTest.OutputAnswer

        ws.Cells(cnt, 5).Value = cTest.Target

        ws.Cells(cnt, 6).Value = cTest.LastIteration

        ws.Cells(cnt, 7).Value = cTest.Tolerance

        ws.Cells(cnt, 8).Value = cTest.MaxIterations

        ws.Cells(cnt, 9).Value = targetOutputPath


      cnt = cnt + 1


   Next laborRateScale


    cnt = 1

    ws.Cells(cnt, 1).Value = "Constant name: cTest.InputName"

    ws.Cells(cnt, 2).Value = "Calbiration input result: cTest.CalibratedInput"

    ws.Cells(cnt, 3).Value = "Ouput Name: cTest.OutputName"

    ws.Cells(cnt, 4).Value = "Output results within Tolerance: cTest.OutputAnswer"

    ws.Cells(cnt, 5).Value = "Taret value of output: cTest.Target"

    ws.Cells(cnt, 6).Value = "Number Iterations: cTest.LastIteration"

    ws.Cells(cnt, 7).Value = "Tolernce used: cTest.Tolerance"

    ws.Cells(cnt, 8).Value = "Max Iterations: cTest.MaxIterations"

    ws.Cells(cnt, 9).Value = "Target output path: targetOutputPath"


    Call p.SaveAs("c:\a\testProject_b.tpprj")


    Set p = Nothing

    Set app = Nothing



End Sub

Examination of the resulting saved TruePlanning project will show the creation of a new constant and its linking to multiple Cost Objects.  A working copy of the above code is available upon request.

Please feel free to contact PRICE if you have any questions about this feature, TruePlanning, TrueMapper, or any other PRICE products and services.