How to implement Menus with dynamic Menu Item ordering
Symptoms
The task is to create a menu that not only has menu items that can be activated and deactivated dynamically, but also with dynamic ordering of the menu items. So, for one caller the menu might sound "For A press 1, for B press 2, for C press 3", while for the second caller it may sound "For C press 1, for A press 2". The order of the menu can change even within a call.
Example: One menu item is a subscription to a special service; once this has been selected and confirmed in a call, next time the same menu will no longer offer this service, and maybe other menu items will have been re-ordered.
Design goals
- Dynamic ordering and (de-)activation of menu items with dynamic assignment of DTMF keys and according sort order of menu item prompts
- Static assignment of menu items to a Menu object, so as to preserve documentation readability and reporting features (menu item labels are assigned statically, so the reports will present these readable and meaningful labels). This goal rules out full dynamic configuration of a generic "template" Menu object. It requires that Menu item labels, destination object, and voice grammars are defined at design time, not at runtime.
- The sort order of the menu items should be determined by priorities. The menu item with the highest priority is played first. Priority 0 means that the menu item is inactive.
Resolution
Implementation Concept
- Start with a standard, static menu definition.
- Make the DTMF keys dynamic.
- Make sure the menu item prompts ("For X, say "X" or press <key>") are played in the right order. This can be achieved by creating a single menu item Output object, where each of the Output items maps to a specific menu item and is activated using a specific Layer condition.
Implementation Details
Please download the example here.
The menu item priorities are managed by a Priorities Collection object.
Example content:
<root>
<row>
<col name="priority">100</col>
<col name="option">A</col>
</row>
<row>
<col name="priority">90</col>
<col name="option">B</col>
</row>
<row>
<col name="priority">80</col>
<col name="option">C</col>
</row>
<row>
<col name="priority">0</col>
<col name="option">D</col>
</row>
</root>
Priorities can be changed using the ":=" expression, and the Priorities Collection can be re-ordered using the SORTROW expression. (De-)activation of each menu item is controlled by assigning expressions "Priority A > 0" etc. to the Layer field of each menu item.
The DTMF keys for the menu items A, B, C, ... are calculated using the expressions FINDROW(Priorities, "option", "A") and assigned to the variables "DTMF key A" etc. These "DTMF key ..." variables are assigned to the DTMF key field in each menu item.
The correct mapping and sorting order of the menu item prompts is managed through a single Output object that is embedded in each menu item's output field: "[O:Menu Item Output Template]". This Output object has one output item per menu item, cf. screenshot below.
The mapping and sorting of the output items is controlled in the following way:
- Before the Menu object is executed, a counter variable "DTMF Counter" is reset to 0.
- In the Precondition of the Menu Item Output object, this DTMF Counter is incremented by 1 (note that this needs to be defined as a Precondition of the Output object, not as a Preprocessing ? the latter gets executed even when the Output object is used as an embedded object, the former does not). Since only menu items with priority > 0 are executed, this counter is incremented only for active menu items.
- The Layer "Current Menu Item" now compares this DTMF key counter with the DTMF key assigned to each topic.
Example for the resulting menu output:
| Priorities defined in Collection, DTMF keys from SORTROW |
Evaluated during item-by-item processing of Menu items
|
| Menu Item |
Priority |
DTMF key |
DTMF counter |
Active State of Layer "Current Menu Item" |
Generated output text (in this order!)
|
| A |
80 |
2 |
1 |
DTMF B |
"For topic B, press 1"
|
| B |
100 |
1 |
2 |
DTMF A |
"For topic A, press 2"
|
| C |
0 |
n/a |
2 |
n/a |
n/a
|
| D |
30 |
3 |
3 |
DTMF D |
"For topic D, press 3"
|
The full call flow for a dynamic menu is displayed on the right hand side. In Menu Preprocessing, the DTMF counter is reset, the menu options are being sorted, and the DTMF keys are assigned. In this example, the menu definition is changed after menu option A is selected: Option A is deactivated (priority A set to 0), and the priority of option F is increased so that is announced earlier the next time the menu is played. Note that the Menu must have the option "Return to the menu after the subdialog processing of a Menu item" disabled, and the Menu must be invoked explicitely instead in order to get back there ? this is the only way that the Preprocessing (and hence the re-ordering and re-assignment of DTMF keys) gets re-executed. Also, auto-numbering must be turned off. |
|
Using the Dynamic Menu Template
When using the dynamic menu in a project, proceed as follows:
- Make a copy of the "Menu Template" Menu.
- Rename "Topic A" etc. by the actual Menu items, like "Money Transfer" or "Credit Card Details".
- Create of copy of the "Menu Item Output Template" Output object and embed it into your new Menu object's item output fields.
We recommend not to change the variables "DTMF key A", ..., "DTMF Counter"; the expressions "Assign dtmf A", ..., "Find row for option A", ..., "Priority A", ..., "Priority A is not 0", ...; and the Layer "Current Menu Item" etc. All these objects are designed to be generic and to be reused in any new dynamic Menu object.
Example
This is an example from a demo prepared for a Telco customer: A dynamic menu with 3 menu items.
After a few test calls, this is an excerpt from the "Utterances by Input State" report that you get. Notice that the menu item "Modify Customer Data" was activated by DTMF keys 1 and 2, respectively, depending on its position in the menu.