Chat with the bot - Edit the test script - View the recent chats.
/* class=gwtchat.server.JavascriptBotUserWizard */
var domain = new NegotiationDomain(wiki.get('JobCandidateDomain.xml'),
/*humanSideName = */ "candidate",
/*computerSideName =*/ "employer"
);
var negotiator = new GeniusNegotiator(domain,
/*humanUtility =*/ wiki.get('JobCandidateShortTermUtilitySpace.xml'),
/*computerUtility =*/ wiki.get('JobEmployerShortTermUtilitySpace.xml'),
/*computerAgentClassName = */ "agents.RandomIncreasingUtilAgent",
/*maxOffersByHuman = */ 10);
var slots = new DialogStateSlots(domain.getIssues());
var YesNoCategorizer = Transformer.recall(wiki, 'YesNo.txt');
/* Create the input patterns that the WOZ will select from: */
var cachedInputPatterns = domain.inputPatterns();
cachedInputPatterns.add("yes");
cachedInputPatterns.add("no");
cachedInputPatterns.add("I want ()");
cachedInputPatterns.add("I don't care");
cachedInputPatterns.add("I agree");
cachedInputPatterns.add("I disagree");
cachedInputPatterns.add("I quit");
cachedInputPatterns.add("I commit");
function inputPatterns() { return cachedInputPatterns; }
var cachedValuesWithoutInputPatterns = domain.valuesWithoutInputPatterns();
function valuesWithoutInputPatterns() { return cachedValuesWithoutInputPatterns; }
var humanIsFirst = true;
function understandWithoutContext(intention, certainty) {
var matches, issueAndValue;
if ((issueAndValue = domain.issueAndValue(intention, currentIssue)) !=null) {
var issueName = issueAndValue.getKey();
var value = issueAndValue.getValue();
if (issueName!=null) {
if (domain.valueIsValidForIssue(value, issueName)) {
understandThatUserWants(issueName, value, certainty);
} else {
chat.complain(misunderstandingValueForIssue(issueName, value),
questionAboutCurrentIssue(), certainty);
}
} else {
chat.complain(misunderstandingValue(value),
questionAboutCurrentIssue(), certainty);
}
} else if (matches = /i want (.*)/i.exec(intention)) { // wrong value
var value = matches[1];
if (currentIssue) {
if (domain.valueIsValidForIssue(value, currentIssue)) {
understandThatUserWants(currentIssue, value, certainty);
} else {
chat.complain(misunderstandingValueForIssue(currentIssue, value),
questionAboutCurrentIssue(), certainty);
}
} else {
chat.complain(misunderstandingValue(value),
questionAboutCurrentIssue(), certainty);
}
}
else if (matches = /i don.t care about (.*)/i.exec(intention)) {
var issueName = matches[1]; // I don't care about X => X
if (domain.hasIssue(issueName)) {
understandThatUserWants(issueName, null, certainty);
} else {
chat.complain(misunderstandingIssue(issueName),
questionAboutCurrentIssue(), certainty);
}
}
else if (/i agree/i.exec(intention)) {
if (negotiator.getLastBidByComputer()==null) {
chat.complain("What exactly do you agree to? I didn't offer you anything! ","",certainty);
} else {
if (certainty>=0.9) {
negotiator.humanAccepts();
endNegotiation(negotiator.getLastBidByComputer());
} else {
ask(null, explicitConfirmationAccept(negotiator.getLastBidByComputer()),
/*yes=*/ intention,
/*no=*/ slots.hasCurrentSlot()? domain.questionAbout(slots.getCurrentSlot()): "So, what do you want to change? ");
}
}
}
else if (/i disagree/i.exec(intention)) {
negotiator.humanRejects();
}
else if (/i quit/i.exec(intention)) {
if (certainty>=0.9) {
negotiator.humanQuits();
endNegotiation(null);
} else {
ask(null, confirmQuit(),
/*yes=*/ intention,
/*no=*/ slots.hasCurrentSlot()? domain.questionAbout(slots.getCurrentSlot()): "So, what do you want to change? ");
}
}
else if (/i commit/i.exec(intention)) {
if (negotiator.maxOffersByHuman()<=0) {
chat.say(noMoreOffers());
} else {
var bid = negotiator.bidFromFilledSlots(slots.getFilledSlots());
if (certainty>=0.9) {
chat.say(implicitConfirmationOffer(bid));
negotiator.humanOffers(bid);
chat.say("You have "+negotiator.maxOffersByHuman()+" offers left.");
} else {
ask(null, explicitConfirmationOffer(bid),
/*yes=*/ intention,
/*no=*/ "So, what do you want to change? ");
}
}
}
else if (/restart/i.exec(intention)) {
greethuman(/*name=*/"", /*chatterid (ignored)=*/0);
}
else if (/i don.t care/i.exec(intention)) {
if (slots.hasCurrentSlot()) {
understandThatUserWants(slots.getCurrentSlot(), null, certainty);
} else {
chat.complain("Don't care about what? ","",certainty);
}
}
else if (/^yes\b/i.exec(intention) || /^no\b/i.exec(intention)) {
chat.complain("Why do you say "+intention+"? I didn't ask you anything! ","",certainty);
} else { /* assume that the user said what he wants, with a lower certainty: */
if (domain.valueIsValidForIssue(intention, currentIssue)) {
understandThatUserWants(currentIssue, intention, certainty);
} else {
var issueName = domain.issueByValue(intention.toLowerCase());
if (issueName!=null) {
understandThatUserWants(issueName, intention, certainty-0.2);
} else {
chat.complain(misunderstanding(),
(lastQuestion==null? questionAboutCurrentIssue(): lastQuestion), certainty);
}
}
}
}
understandInContext = understandWithoutContext; // initially there is no context
function understandThatUserWants(slot, value, certainty) {
if (slot==undefined) {
java.lang.System.err.println("undefined slot: understandThatUserWants("+slot+","+ value+","+ certainty+")");
return;
}
if (negotiator.maxOffersByHuman()<=0) {
chat.say(noMoreOffers());
return;
}
if (certainty>=0.8) {
slots.fillSlot(slot, value);
newSlotFilled = true;
if (certainty>=0.9) {
chat.say(minimalConfirmation());
} else {
nextImplicitConfirmations.push(domain.confirmationAbout(slot, value));
}
} else {
slots.setCurrentSlot(slot);
currentIssue = slot;
var question = explicitConfirmation(slot, value);
nextQuestion = question;
understandInContext = function(intention, certainty) {
if (/^yes\b/.exec(intention)) {
understandThatUserWants(slot, value, 0.95);
} else if (/^no\b/.exec(intention)) {
chat.say("OK, so "+questionAboutCurrentIssue());
} else { // the human didn't answer the question, but said something else:
lastQuestion = question;
understandWithoutContext(intention, certainty);
}
}
}
//print ("currentslot="+slots.getCurrentSlot()+"\n");
}
/* Called once when a human enters the room */
function greethuman(chatter) {
negotiator.startNegotiationSession();
slots.clear();
chat.say(domain.greeting(chatter.name)+
"
\nWe will negotiate several issues, ordered from the most important to the least important
"+
"For each issue, there are several possible values, ordered from the best to the worst:
"+
- \n"+
negotiator.humanUtilitySpaceHTML()+
"
"
You can make at most "+negotiator.maxOffersByHuman()+" offers.\n"+
"
Try to get the best deal for the most important subjects!\n");
if (humanIsFirst) {
negotiator.setHumanTurn();
chat.say("You will be the first to say what you want. "+questionAboutCurrentIssue());
} else {
negotiator.setComputerTurn();
chat.say("I will make the first offer. ");
getComputerActionFromNegotiationAgent();
}
}
/* Called once when a WOZ enters the room */
function greetwizard(chatter) {
chat.sayToWizard('Hi, '+chatter.name+'! It is great you are here. You will help me understand the user!');
}
var newSlotFilled = false;
var nextImplicitConfirmations = [];
/* Called before the first meaningful utterance */
function understandBeforeFirst() {
newSlotFilled = false;
nextImplicitConfirmations = [];
nextQuestion = null;
}
/* Called for each meaningful utterance detected at the human's input */
function understand(intention, certainty) {
lastQuestion = null;
//intention = substituter.substitute(intention); // simple text substitutions
var yesNo = YesNoCategorizer.bestTag(intention);
if (yesNo=='yes' || yesNo=='no')
intention = yesNo;
if (!understandInContext)
print("ERROR: Null function understandInContext!\n");
else {
var understandInCurrentContext = understandInContext;
understandInContext = understandWithoutContext; // forget the context after using it
understandInCurrentContext(intention, certainty); // understand the intention in the current context
}
}
/* Called after the last meaningful utterance */
function understandAfterLast() {
if (newSlotFilled) {
if (slots.allSlotsFilled()) {
understand("I commit", 0.6);
// commit bid with a low certainty. to let the user confirm/change.
} else {
nextQuestion = questionAboutCurrentIssue();
}
}
var nextConfirmationText = ;
if (nextImplicitConfirmations.length>0) {
nextConfirmationText += 'I see, ';
for (i=0; i<nextImplicitConfirmations.length; i++) {
if (i>0)
nextConfirmationText += " and ";
nextConfirmationText += nextImplicitConfirmations[i];
}
nextConfirmationText += ". ";
}
if (nextQuestion)
nextConfirmationText += nextQuestion;
chat.say(nextConfirmationText);
if (negotiator.isComputerTurn())
getComputerActionFromNegotiationAgent();
}
function displayname() { return "Boss"; }
function color() { return "#480"; }
/*
* QUESTIONS AND CONFIRMATION TEXTS
*/
var currentIssue=null;
function questionAboutCurrentIssue() {
slots.setCurrentSlotIfEmpty();
currentIssue = slots.getCurrentSlot();
return domain.questionAbout(currentIssue);
}
function explicitConfirmation(issue, value) {
return "So, "+ domain.confirmationAbout(issue, value) + "? "; }
function minimalConfirmation() {
return "I see. "; }
function explicitConfirmationOffer(bid) {
return "So, your offer is "+bid+"? "; }
function implicitConfirmationOffer(bid) {
return "Well, Let me think about it. "; }
function explicitConfirmationAccept(bid) {
return "So, do you agree to my offer: "+bid+"? "; }
function confirmQuit() {
return "Do you really want to quit? "; }
function noMoreOffers() {
return "Sorry, you cannot make any more offers! Either agree to my offer or quit.";}
/*
* MISUNDERSTANDING TEXTS
*/
function misunderstanding() {
return "I didn't understand you. ";
}
function misunderstandingValue(value) {
return value+" is not a valid value. ";
}
function misunderstandingIssue(issue) {
return issue+" is not one of the issues we negotiate about. ";
}
function misunderstandingValueForIssue(issueName, value) {
return value+" is not a valid value for "+issueName+". Valid values are: "+domain.valuesByIssue(issueName);
}
function getComputerActionFromNegotiationAgent() {
var computerAction = negotiator.computerAgentAction();
if (computerAction!=null) {
if (negotiator.actionIsAccept(computerAction)) {
if (negotiator.getLastBidByHuman() == null) { // ERROR: accept without offer!
chat.complain("My braincells are probably sick. I accepted your offer but you didn't make any offer!","",0.5);
} else {
endNegotiation(negotiator.getLastBidByHuman());
}
} else if (negotiator.actionIsReject(computerAction)) {
chat.say("I disagree to your offer. ");
} else if (negotiator.actionIsEndNegotiation(computerAction)) {
chat.say("I had enough of this negotiation. I quit. ");
endNegotiation(null);
} else if (negotiator.actionIsOffer(computerAction)) {
chat.say("My offer is: " + computerAction.getBid().toString());
} else {
chat.say("I say: " + computerAction.toString());
}
}
negotiator.setHumanTurn();
}
function endNegotiation(finalBid) {
var utility = negotiator.humanUtility(finalBid);
var maxUtility = negotiator.getHumanMaxUtility();
if (finalBid==null) {
chat.say("Sorry, we couldn't reach an agreement. ");
} else {
chat.say("Great! We agreed on "+finalBid+". ");
}
relativeUtility = Math.round(utility/maxUtility*100);
if (utility > 1) {
chat.say("The value of your offer is "+utility+" out of "+maxUtility+", so your score is "+relativeUtility+"%. ");
} else {
chat.say("The value of your offer is "+relativeUtility+"% of the maximum possible value. ");
}
}
var lastQuestion = null;
var nextQuestion = null;
function ask(issue, question, humanIntentionToConfirm, questionIfHumanRejects) {
nextQuestion = question;
understandInContext = function(intention, certainty) {
if (/^yes\b/.exec(intention)) {
if (issue!=null) currentIssue = issue;
understandWithoutContext(humanIntentionToConfirm, 0.95);
} else if (/^no\b/.exec(intention)) {
if (issue!=null) currentIssue = issue;
chat.say(questionIfHumanRejects);
} else { // the human didn't answer the question, but said something else:
lastQuestion = question;
understandWithoutContext(intention, certainty);
}
}
}