I want to restart my watterfall dialog at it's beginning when it ends, using C# - dialog

I'm using the Bot Framework .Net SDK4.
I start my Dialog at MainDialog.
I'm trying to restart my dialog when the watterfall dialog conversation ends. I have multiple watterfall that redirect to other watterfall dialogs, unti they reach the final one.
When I'm using stepContext.EndDialogAsync(null, cancellationToken) or stepContext.CancellAllDialogsAsync(cancellationToken), the dialog just returns to the previous parent dialog.
I also can't just use BeginDialogAsync(nameof(MainDialog), null, cancellationToke) because of circular dependency issues.
Is there anything I can do to restart my dialog at MainDialog, where it reruns tehe dialog again.

use
return await sc.ReplaceDialogAsync(nameof(NoUnderstandDialog), cancellationToken);
To restart the waterfall dialog you are currently in.
ReplaceDialogAsync :
Starts a new dialog and replaces on the stack the currently active dialog with
the new one. This is particularly useful for creating loops or redirecting to
another dialog.
You can use this for multiple reasons, validation for example if the user inputs a wrong value, you can restart the dialog to prompt again. Be careful though your waterfall dialog should always "ends" meaning it should have a EndDialogAsync so you don't get stuck in an endless loop

Related

Is there an easy way to get the currently active dialog on the stack?

My bot is based on core-bot sample and has an interrupt function which can be invoked by certain intents during dialogs. If I'm in a dialog, and then the interrupt starts a dialog, they are both invoked via dc.beginDialog and there are on a single level in the dialog stack. For example, it would look like this
[ { id: 'viewOrderDialog', state: { dialogs: [Object] } },
{ id: 'interruptDialog', state: { dialogs: [Object] } } ]
So I can somewhat easily get the active dialog by getting the ID of the last element in the array. However, in my process I can start additional dialogs from, in this case, interruptDialog. Those are started from within a waterfall via step.beginDialog. In that case, they are no longer at the same level as the other dialogs (started from dc instead of step). I have to get into state.dialogs.dialogStack to find the id, which then can become nested again if that dialog calls another. Here is an example of what dc.activeDialog can end up looking like:
{"id":"interruptDialog","state":{"dialogs":{"dialogStack":[{"id":"waterfallDialog","state":{"options":"expediteOrder","values":{"instanceId":"d61d748e-af45-cea0-9188-63904de21dfc"},"stepIndex":0}},{"id":"escalationDialog","state":{"dialogs":{"dialogStack":[{"id":"waterfallDialog","state":{"options":{},"values":{"instanceId":"6e755278-d636-dd76-3b47-eb43e3eda1c7"},"stepIndex":2}},{"id":"emailDialog","state":{"dialogs":{"dialogStack":[{"id":"waterfallDialog","state":{"options":{},"values":{"instanceId":"87f08019-ff59-ce03-ccab-7914fb0b553b"},"stepIndex":1}},{"id":"emailPrompt","state":{"options":{"prompt":"Which email address do you want us to reply to?"},"state":{}}}]}}}]}}}]}}}
I could get down to the lowest level, which in this case is emailPrompt, but it seems it would take an inordinate amount of overhead to check and see if each level of dialogs/dialogStack was an array. (And yes, I should probably name my waterfall dialogs something other than waterfallDialog). I was hoping there would be an easy way to just get the most recent dialog off the stack, but I couldn't find anything to give me that information.
In a less general sense, I'm specifically trying to add a condition to the interrupt to prevent it from being invoked within certain dialogs. I have a step where user can write an email body, and if they write something about expediting an order, the interrupt is activating. In this specific case I decided to solve it by converting dc.activeDialog to a string and then checking to see if it includes 'emailDialog'. Then I add a condition for !activeDialog.includes('emailDialog'). Works fine for this case, but I asked the more general question because this may not be a good solution in other cases where I need to know which dialog I am in.
I can provide code snippets if needed, but the code itself isn't really important. I'm just trying to determine the best way to get the id of the currently active dialog from the dialog context.
The reason you're seeing nested dialog stacks is because you're using component dialogs.
If your interruptions are always performed on the root dialog context and that's where your interrupt dialogs get added, then there should be no need to dig into the nested dialog stacks. Because the interrupt dialog will always be in the root dialog stack you can just check your root dialog context to see if the active dialog is an interrupt dialog.
I don't know of any builtin way to determine the innermost active dialog, but if that's really what you want to do then it shouldn't be hard to create a recursive function to do it:
getInnermostActiveDialog(dc) {
var child = dc.child;
return child ? this.getInnermostActiveDialog(child) : dc.activeDialog;
}
It should be noted that the Core Bot sample makes only specific dialogs interruptible by having them extend a common base dialog class and then handling interruptions from within the dialog instead of from the bot class. You might want to follow that example by having dialogs "opt in" to interruptibility rather than having the interrupt dialog "opt out."

Bot Framework BeginDialog or ReplaceDialog during conversation, which should I use?

I'm currently working on a bot using Microsoft's Bot Framework. This bot has multiple Component dialogs build up from WaterfallDialogs. When my users go through the conversations I split up pieces of this conversation in separate waterfall dialogs, but I've noticed that there are two ways to make this work.
BeginDialog() Creates a new instance of the dialog and pushes it onto the stack.
ReplaceDialog() Ends the active dialog and starts a new dialog in its place.
Currently I've not noticed any difference in using these two ways of switching waterfallDialogs. What are the main differences between the two and which should I be using to switch between waterfallDialogs within a single Component Dialog?
beginDialog does not end the current dialog. So if that dialog is not complete, it will continue running after the new dialog or dialogs are popped off the stack. If you are running this as the last step of a waterfall dialog, I think it will technically work but is not considered a best practice. If you have no intention of returning to the currently running dialog, you should replaceDialog since it combines ending of the current dialog with the beginning of the new one.

Test quickly changing scenario using selenium web driver in nodejs

I have a button which triggers a rest call and upon click of that button until the rest call triggers I disable the button.
I am writing a test case using selenium web driver and nodejs
button = driver.findElement(By.class("btn"));
await button.click();
console.log(await button.isEnabled()) //outputs true
But I can see that the button is being disabled and I am sure Iam selectingthe correct button the findElement statement.
The documentation for .isEnabled() says:
Is the element currently enabled or not? This will generally return true for everything but disabled input elements.
So what you are seeing is expected behaviour.
To test your scenario, you will need the following approach:
click your button
click the same button again
the second click you are expecting to fail, so you will have to wrap it in whatever is the node.js equivalent of try..catch (sorry, I'm a Java guy)
inside of the catch, set a variable to true
afterwards test the variable has been set
The scenario you have described is to click a button, verify it becomes disabled, and then verify it becomes enabled. There are probably a few ways to do this. I'm looking at the documentation and here is one way:
button = driver.findElement(By.class("btn"));
button.click();
driver.wait(until.elementIsDisabled(button));
driver.wait(until.elementIsEnabled(button));
If the button never becomes disabled, an exception will be thrown. If the button never becomes reenabled, an exception will be thrown. So, the fail condition is either one throwing an exception. The pass condition is no exceptions.
NOTE: disabled and enabled, in Selenium terms, is generally referring to an INPUT tag. If your button is not an INPUT tag, then this won't work. You will need to detect some CSS style being applied/removed to determine disabled/enabled.

How to stop QnAMaker dialog from returning to parent dialog?

Trying to understand MS Bot Framework and build my first bot.
The default dialog is a Prompts.choice. First choice passes to new dialog that asks for Prompts.text.
User enters text which then passes that to my QnAMaker, which looks for the answer and returns it. This works as expected.
After answer is returned, my bot closes the QnAMaker dialog and then returns to the default dialog where the bot starts over from the beginning. I don't want this to happen.
How do I keep the user in the QnAMaker dialog so that they can continually ask QNAMaker questions until they are done and want to do something else in the bot?
Screenshot of terminal output. Code below. Thanks!
bot.dialog('rentalHelp', [
function(session) {
builder.Prompts.text(session, "In which state do you live? (please spell out)");
},
function(session, results) {
// start the QnA bot dialog
session.beginDialog('QnAMaker');
}
]);
I think I figured out the reason it was doing this from Bot SDK chat reference library
Excerpt:
note: Waterfalls have a hidden last step which will automatically end the current dialog if if you call a prompt or dialog from the last step. This is useful where you have a deep stack of dialogs and want a call to session.endDialog() from the last child on the stack to end the entire stack. The close of the last child will trigger all of its parents to move to this hidden step which will cascade the close all the way up the stack. This is typically a desired behavior but if you want to avoid it or stop it somewhere in the middle you'll need to add a step to the end of your waterfall that either does nothing or calls something like session.send() which isn't going to advance the waterfall forward.
It would be great if someone could confirm this is the problem or help me to improve my code.

How to handle LWUIT dialogs shown on background threads

I have written an application in LWUIT targeted for a J2ME phone (Sprint DuraXT). The application is for pickup and delivery van drivers. It receives dispatches from a back-end dispatching system that describe pickups and delivers the driver must make. As the drivers, execute the pickups and deliveries, the driver enters status information that is sent back to the dispatching system.
Now, during the processing of a pickup or delivery, the driver may be presented with error dialogs (incorrect field entry), yes/no confirmation dialogs (confirming some action) and information dialogs (indicating some status the driver should be aware of).
In addition, there is a background thread listening for dispatches coming from the back-end server. In the current implementation, this background thread can also create yes/no confirmation dialogs and information dialogs. These dialogs are more like an alert as they have an associated sound, but they are simply dialogs.
As long as these two dialogs do not occur “simultaneously” every thing works as expected. You can dismiss the dialogs and the app proceeds as expected.
However, when you are on a screen and there is a dialog already showing and a second one from the background thread occurs, you sometime wind up with the wrong screen showing and it is “frozen”. E.g. the soft keys have no effect.
My hypothesis is that there is a race condition between the threads that are dismissing the dialogs. It goes like this. The EDT is blocked showing the dialog that arises as part of the form’s logic. The background thread is also blocked showing a dialog. Now when the dialog showing on the EDT is dismissed, the form is restored, but the EDT may go off and display another form (via show()). When the dialog displayed by the background thread is dismissed, the form which was showing when the dialog was initially displayed is sometimes restored. Now, the display shows a different form than the one the EDT might have shown.
It is pretty clear that this problem is caused by the dialogs resulting from the activities of the background thread. So the basic question is: “How to handle the dialogs arising from the background thread?” I have some thoughts but none yield a particularly clean implementation. I am hoping somebody has had to deal with this same problem and has a suggestion.
I have tried synchronizing the dialog construction and display so that only one dialog can get displayed at a time. This certainly improves the UI, but does not fully resolve the problem. The race begins when the first dialog is dismissed. Here are some other ideas,
If a dialog is shown by a thread other than the EDT, call show on the form at the top of the display stack when the dialog is dismissed. This is a bit of a hack, but may be a workaround.
Run dialogs to be shown by the background thread on the EDT. There are several ways to do this, but the question is will it resolve the problem? Will using an EventDispatcher help? I have experimented using an EventDispatcher to fire an ActionEvent containing a subclass of a Dialog as a source. The subclass contains a show() method which invokes the correct form of the Dialog show method. The class holding the EventDispatcher (global to the application) listens for these events. When the event arrives, the show method is invoked. For information dialogs that simply continue execution from wherever they are dismissed, this should work. For yes/no dialogs, you may have to create something like yes/no callbacks to handle the bifurcation in the logic. And what is not obvious is if this will actually serialize the processing of the dialogs on the EDT thread. This seems complicated.
Any ideas?
I actually hit upon the solution after a bit of experimentation. Because the Dialogs are part of a more compilcated action involving yes/no Dialogs and database queries, I found I had to wrap the whole action in a class which implements the Runnable interface. Then I run the action via Display.getInstance().callSeriallyAndWait(runnable).
So others may benefit from this discussion, here is a example of one of these classes with the action embedded in the run method.
private class CancelOrder implements Runnable {
private KWMap order;
public CancelOrder(KWMap order) {
this.order = order;
}
public void run() {
String orderNum = getString(order, OrderTable.ORDER_NUM);
if (legStatusTable.isOrderStarted(orderNum)
&& !orderTable.isOrderComplete(order)) {
String msg = "You received a cancellation message for Order "
+ orderNum
+ " which has been started but is not finished."
+ "\nDo you want to keep it?";
if (app.yesNoDialog(msg, "Yes", "no")) {
sendCancelResponse(order, "Yes", "");
} else {
deleteOrder(orderNum);
sendCancelResponse(order, "No", "");
}
} else {
// order has neither been started nor completed.
deleteOrder(orderNum);
sendCancelResponse(order, "Yes", "");
app.alertDialog("Dispatcher cancelled Order " + orderNum);
}
}
}
The key thing here is that the action contains logic depending on how a user responds to a yes/no Dialog and there are operations on an underlying database and messaging subsystem as well. Except for the Dialogs, nothing in this action blocks the EDT for more than a few 100s of milliseconds, so the application runs very smoothly. The app coorectly handles dislogs stacking on top of each other which was a problem with the simple apporach of letting these actions run on the background (non EDT) thread.

Resources