CHECKLIST EXAMPLES
This section presents a couple of examples of how to correctly format Checklist and Checklist Library *.xml
files. You can find more information about the different XML elements used in these examples from the following page:
Simple Checklist
The example below shows a minimal checklist with a single checkpoint that includes all of the essential items for the checkpoint to meet the Checklist Best Practices:
<?xml version="1.0" encoding="Windows-1252"?>
<SimBase.Document Type="Checklist" version="1,0">
<Checkpoint>
<CheckpointDesc SubjectTT="TT:GAME.CHECKLIST_PARKING_BRAKE" ExpectationTT="TT:GAME.CHECKLIST_SET"/>
<Test>
<TestValue>
<Val SimVarName="BRAKE PARKING POSITION" Units="Boolean"/>
</TestValue>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="PARKING_BRAKES"/>
<Instrument id="PARKING_BRAKE"/>
</Test>
</Checkpoint>
</SimBase.Document>
The above checkpoint will:
- enable highlighting of an instrument using a visual helper.
- validate it in Automatic mode as soon as the user meets the requirement. In this case the SimVar "
BRAKE PARKING POSITION
" must be TRUE (1) for the requirements to be fulfilled. - automatically be executed in Copilot mode - and only in this mode - if the
testValue
is FALSE (0), i.e: if the parking brake is not set. This action will only be performed once. The action sends the event ofEventID
"PARKING_BRAKES", which will activate the parking brake of the aircraft. This checkpoint will still wait until thetestValue
is TRUE (1) before being automatically validated, i.e: setting an unrelated action will cause the Copilot mode to wait until the user resolves the issue by themselves.
Checkpoint Libraries
A checkpoint library is a file that contain one or more checkpoints that can be shared across various aircraft. Below is a minimal example of a library file containing two checkpoints - Parking_Brake_Set
and Brakes_Released
- that we'll then reference in the actual checklist file:
<?xml version="1.0" encoding="Windows-1252"?>
<SimBase.Document Type="CheckpointLibrary" version="1,0">
<Checklist.CheckpointLibrary>
<Checkpoint Id="Parking_Brake_Set">
<Clue name="TT:CLUE.PARKING_BRAKE_SET"/>
<CheckpointDesc SubjectTT="TT:GAME.CHECKLIST_PARKING_BRAKE" ExpectationTT="TT:GAME.CHECKLIST_SET"/>
<Test>
<TestValue>
<Val SimVarName="BRAKE PARKING POSITION" Units="Boolean"/>
</TestValue>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="PARKING_BRAKES"/>
<Instrument Id="LANDING_GEAR_Switch_ParkingBrake"/>
</Test>
</Checkpoint>
<Checkpoint Id="Brakes_Released">
<Clue name="TT:CLUE.BRAKES_RELEASED"/>
<CheckpointDesc SubjectTT="TT:GAME.CHECKLIST_BRAKES" ExpectationTT="TT:GAME.CHECKLIST_RELEASED"/>
<Sequence SeqType="Unordered">
<Test>
<TestValue>
<Operator OpType="NOT">
<Val SimVarName="BRAKE PARKING POSITION" Units="Boolean"/>
</Operator>
</TestValue>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="PARKING_BRAKES"/>
<Instrument Id="LANDING_GEAR_Switch_ParkingBrake"/>
</Test>
<Test>
<Instrument Id="HANDLING_RudderPedals_Rudder"/>
<Instrument Id="HANDLING_RudderPedals"/>
<Instrument Id="HANDLING_RudderPedals1"/>
<Instrument Id="HANDLING_RudderPedals2"/>
<TestValue>
<Operator OpType="AND">
<Operator OpType="EQUAL">
<Val SimVarName="BRAKE LEFT POSITION" Units="percent"/>
<Val Value="0"/>
</Operator>
<Operator OpType="EQUAL">
<Val SimVarName="BRAKE RIGHT POSITION" Units="percent"/>
<Val Value="0"/>
</Operator>
</Operator>
</TestValue>
<Action Copilot="True" Condition="TestValueFalse" EventID="AXIS_LEFT_BRAKE_SET" EventParam="-16383"/>
<Action Copilot="True" Condition="TestValueFalse" EventID="AXIS_RIGHT_BRAKE_SET" EventParam="-16383"/>
</Test>
</Sequence>
</Checkpoint>
</Checklist.CheckpointLibrary>
</SimBase.Document>
This library file can then be accessed in the checklist file using the <IncludeCheckpointLibrary />
element, and the checkpoint ID (defined using the <Checkpoint>
element in the library file) is used to select the required checkpoints - Parking_Brake_Set
and Brakes_Released
- from it:
<?xml version="1.0" encoding="Windows-1252"?>
<SimBase.Document Type="Checklist" version="1,0">
<Checklist.Checklist>
<IncludeCheckpointLibrary FileName="MY_AIRCRAFTCheckpointLibrary.xml"/>
<Step ChecklistStepId="PREFLIGHT_GATE">
<Page SubjectTT="TT:GAME.CHECKLIST_PREFLIGHT_1_1">
<Checkpoint ReferenceId="Parking_Brake_Set"/>
</Page>
<Page SubjectTT="TT:GAME.CHECKLIST_PREFLIGHT_1_2">
<Checkpoint>
<CheckpointDesc SubjectTT="TT:GAME.CHECKLIST_NAVIGATION_LIGHTS" ExpectationTT="TT:GAME.CHECKLIST_ON"/>
<Test>
<TestValue>
<Val SimVarName="LIGHT NAV" Units="Boolean"/>
</TestValue>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="TOGGLE_NAV_LIGHTS"/>
<Instrument id="LIGHT_NAV_SWITCH"/>
</Test>
</Checkpoint>
</Page>
</Step>
<Step ChecklistStepId="PREFLIGHT_PUSHBACK">
<Page SubjectTT = "TT:GAME.CHECKLIST_PUSHBACK">
<Checkpoint ReferenceId="Brakes_Released"/>
</Page>
</Step>
</Checklist.Checklist>
</SimBase.Document>
Automatic Action (Copilot) Example
In this example, the two WaitUntilTestValueValidated <Action />
elements are what is most important. Without them, in Copilot mode, both Tests would be automatically skipped because they would have no Copilot Action, and they would have a TestValue
"True" for the Sequence. This in turn means the sequence action with Condition="TestValueFalse"
atribute would not trigger:
<Checkpoint Id="SPEED_BRAKES_TEST">
<CheckpointDesc SubjectTT="TT:GAME.CHECKLIST_SPEED_BRAKES" ExpectationTT="TT:GAME.CHECKLIST_CHECK"/>
<Sequence SeqType="PARALLEL">
<Test>
<TestValue>
<Operator OpType="EQUAL" Tolerance="2">
<Val Code="(A:SPOILERS LEFT POSITION, percent)"/>
<Val Value="100"/>
</Operator>
</TestValue>
<Action Copilot="True" Condition="TestValueFalse" SpecialAction="WaitUntilTestValueValidated"/>
</Test>
<Test>
<TestValue>
<Operator OpType="EQUAL" Tolerance="2">
<Val Code="(A:SPOILERS RIGHT POSITION, percent)"/>
<Val Value="100"/>
</Operator>
</TestValue>
<Action Copilot="True" Condition="TestValueFalse" SpecialAction="WaitUntilTestValueValidated"/>
</Test>
<Action Copilot="True" Condition="TestValueFalse" Once="False" Code="(>B:HANDLING_Spoilers_Deploy)"/>
</Sequence>
</Checkpoint>
Advanced Checkpoint Example
Here we have a more complex example of two checkpoints that share variables (created in the <Action />
element using the StoreVar attribute) and these variables are also being used to ensure that only one of two sequences will actually be executed. A more thorough explanation of the example is given at the end:
<Checkpoint Id="Magneto_150_RPM_Max_Decrease">
<CheckpointDesc SubjectTT="TT:GAME.CHECKLIST_MAGNETOS" ExpectationTT="TT:GAME.CHECKLIST_150RPM_MAX_DECREASE"/>
<Action Condition="Init" StoreVar="Magneto_RPM_BOTH" Value="0"/>
<Action Condition="Init" StoreVar="Magneto_RPM_LEFT" Value="0"/>
<Action Condition="Init" StoreVar="Magneto_RPM_RIGHT" Value="0"/>
<Sequence SeqType="Ordered">
<Test>
<TestValue>
<Operator OpType="And">
<Val SimVarName="RECIP ENG LEFT MAGNETO:1" Units="Boolean"/>
<Val SimVarName="RECIP ENG RIGHT MAGNETO:1" Units="Boolean"/>
</Operator>
</TestValue>
<Duration Value="1.0" Cumulative="False"/>
<Once>True</Once>
<Instrument id="MAGNETO"/>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="MAGNETO_BOTH"/>
<Action Condition="TestValueTrue" Once="false" StoreVar="Magneto_RPM_BOTH">
<Val SimVarName="GENERAL ENG RPM:1" Units="rpm"/>
</Action>
</Test>
<Sequence SeqType="Unordered">
<Sequence SeqType="Ordered">
<Once>True</Once>
<Test>
<TestValue>
<Operator OpType="OR"> <!-- Skips if Magneto_RPM_RIGHT is already set -->
<Val ReadVar="Magneto_RPM_RIGHT"/>
<Operator OpType="And">
<Val SimVarName="RECIP ENG LEFT MAGNETO:1" Units="Boolean"/>
<Operator OpType="Not">
<Val SimVarName="RECIP ENG RIGHT MAGNETO:1" Units="Boolean"/>
</Operator>
</Operator>
</Operator>
</TestValue>
<Duration Value="1.5" Cumulative="False"/>
<Instrument id="MAGNETO"/>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="MAGNETO_LEFT"/>
</Test>
<Test>
<TestValue>
<Operator OpType="OR"> <!-- Skips if Magneto_RPM_RIGHT is already set -->
<Val ReadVar="Magneto_RPM_RIGHT"/>
<Operator OpType="Greater">
<Val SimVarName="GENERAL ENG RPM:1" Units="rpm"/>
<Operator OpType="Minus">
<Val ReadVar="Magneto_RPM_BOTH"/>
<Val Value="150"/>
</Operator>
</Operator>
</Operator>
</TestValue>
</Test>
<Test> <!-- Store the current rpm in Magneto_RPM_LEFT, unless Magneto_RPM_RIGHT is already set -->
<TestValue>
<Operator OpType="OR"> <!-- Verifies if one of the var is set -->
<Val ReadVar="Magneto_RPM_LEFT"/>
<Val ReadVar="Magneto_RPM_RIGHT"/>
</Operator>
</TestValue>
<Action Condition="TestValueFalse" Once="True" StoreVar="Magneto_RPM_LEFT">
<Val SimVarName="GENERAL ENG RPM:1" Units="rpm"/>
</Action>
</Test>
</Sequence>
<Sequence SeqType="Ordered">
<Once>True</Once>
<Test>
<TestValue>
<Operator OpType="OR"> <!-- Skips if Magneto_RPM_LEFT is already set -->
<Val ReadVar="Magneto_RPM_LEFT"/>
<Operator OpType="And">
<Val SimVarName="RECIP ENG RIGHT MAGNETO:1" Units="Boolean"/>
<Operator OpType="Not">
<Val SimVarName="RECIP ENG LEFT MAGNETO:1" Units="Boolean"/>
</Operator>
</Operator>
</Operator>
</TestValue>
<Duration Value="1.5" Cumulative="False"/>
<Instrument id="MAGNETO"/>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="MAGNETO_RIGHT"/>
</Test>
<Test>
<TestValue>
<Operator OpType="OR"> <!-- Skips if Magneto_RPM_LEFT is already set -->
<Val ReadVar="Magneto_RPM_LEFT"/>
<Operator OpType="Greater">
<Val SimVarName="GENERAL ENG RPM:1" Units="rpm"/>
<Operator OpType="Minus">
<Val ReadVar="Magneto_RPM_BOTH"/>
<Val Value="150"/>
</Operator>
</Operator>
</Operator>
</TestValue>
</Test>
<Test> <!-- Store the current rpm in Magneto_RPM_RIGHT, unless Magneto_RPM_LEFT is already set -->
<TestValue>
<Operator OpType="OR"> <!-- Verifies if one of the var is set -->
<Val ReadVar="Magneto_RPM_LEFT"/>
<Val ReadVar="Magneto_RPM_RIGHT"/>
</Operator>
</TestValue>
<Action Condition="TestValueFalse" Once="True" StoreVar="Magneto_RPM_RIGHT">
<Val SimVarName="GENERAL ENG RPM:1" Units="rpm"/>
</Action>
</Test>
</Sequence>
</Sequence>
</Sequence>
</Checkpoint>
<Checkpoint Id="Magneto_50_RPM_Difference_Max">
<CheckpointDesc SubjectTT="TT:GAME.CHECKLIST_MAGNETOS" ExpectationTT="TT:GAME.CHECKLIST_50RPM_MAX_DIFFERENCE"/>
<Sequence SeqType="Ordered">
<Sequence SeqType="Ordered">
<Once>True</Once>
<Test>
<TestValue>
<Operator OpType="OR"> <!-- Skips if Magneto_RPM_RIGHT is already set -->
<Val ReadVar="Magneto_RPM_RIGHT"/>
<Operator OpType="And">
<Val SimVarName="RECIP ENG RIGHT MAGNETO:1" Units="Boolean"/>
<Operator OpType="Not">
<Val SimVarName="RECIP ENG LEFT MAGNETO:1" Units="Boolean"/>
</Operator>
</Operator>
</Operator>
</TestValue>
<Duration Value="1.5" Cumulative="False"/>
<Instrument id="MAGNETO"/>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="MAGNETO_RIGHT"/>
</Test>
<Test>
<TestValue>
<Val ReadVar="Magneto_RPM_RIGHT"/>
</TestValue>
<Action Condition="TestValueFalse" Once="True" StoreVar="Magneto_RPM_RIGHT">
<Val SimVarName="GENERAL ENG RPM:1" Units="rpm"/>
</Action>
</Test>
</Sequence>
<Sequence SeqType="Ordered">
<Once>True</Once>
<Test>
<TestValue>
<Operator OpType="OR"> <!-- Skips if Magneto_RPM_LEFT is already set -->
<Val ReadVar="Magneto_RPM_LEFT"/>
<Operator OpType="And">
<Val SimVarName="RECIP ENG LEFT MAGNETO:1" Units="Boolean"/>
<Operator OpType="Not">
<Val SimVarName="RECIP ENG RIGHT MAGNETO:1" Units="Boolean"/>
</Operator>
</Operator>
</Operator>
</TestValue>
<Duration Value="1.5" Cumulative="False"/>
<Instrument id="MAGNETO"/>
<Action Copilot="True" Condition="TestValueFalse" Once="true" EventID="MAGNETO_LEFT"/>
</Test>
<Test>
<TestValue>
<Val ReadVar="Magneto_RPM_LEFT"/>
</TestValue>
<Action Condition="TestValueFalse" Once="True" StoreVar="Magneto_RPM_LEFT">
<Val SimVarName="GENERAL ENG RPM:1" Units="rpm"/>
</Action>
</Test>
</Sequence>
<Test>
<TestValue>
<Operator OpType="Equal" Tolerance="50">
<Val ReadVar="Magneto_RPM_LEFT"/>
<Val ReadVar="Magneto_RPM_RIGHT"/>
</Operator>
</TestValue>
</Test>
</Sequence>
</Checkpoint>
So, how does this last example work? The user is supposed to set the magneto to "Both", then wait some time for the RPM to stabilize, then measure the current RPM. He then does the same for "Left" and "Right", in any order. The RPM for "Left" or "Right" should be no less than 150 RPM below the RPM for "Both". The RPM for "Left" and "Right" should not be further apart than 50 RPM.
Here, the first checkpoint starts by initializing variables to 0, to avoid possible side-effects. Then, the first test measures the RPM for the "Both" setting. The following un-ordered sequence is composed of two ordered sequences, each set up so that only one actually needs to be properly executed, one for "Left" and the other for "Right". The sequence waits 1.5 seconds in the correct settings, and measures the RPM. The difference of RPM between "Both" and "Left/Right" is computed, and if small enough, the corresponding RPM is stored in the appropriate variable. The other "Right/Left" variable will keep a value of 0.
In the second checkpoint, only one of the first two ordered sub-sequences is actually executed, and the other is skipped, based on which variable among "Left" and "Right" is set, and which still contains 0. The correct sequence will set the corresponding "Left/Right" settings, and measure the RPM. Finally, the last test verifies that the two "Left" and "Right" variables are close enough.