Skip to content
This repository has been archived by the owner on Aug 30, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/demo-report-outage' into addingT…
Browse files Browse the repository at this point in the history
…ests
  • Loading branch information
lucasbarth committed Apr 27, 2022
2 parents 1059146 + a2456bb commit 13e1676
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 25 deletions.
128 changes: 106 additions & 22 deletions lambda/conversation/reportOutage.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,73 @@ const {
const { utils } = require('@ocelot-consulting/ocelot-voice-framework')
const { fakePhoneNumber, fakeWebsite } = require('../constants')

const callOutageApi = async () => {
console.log('outage reported')
const callOutageApi = async ({houseNumber, phoneNumber}) => {
console.log('outage reported', houseNumber, phoneNumber)

return [{
result: 'noOutage'
}, {
result: 'yesOutage',
impact: '300',
areaDescription: 'The pines neighborhood north of Park Street',
workDescription: 'Crews are on the scenen and expect repairs to complete in about an hour.'
}, {
result: 'badCombination'
}][houseNumber % 3]
}

const stateMap = {
fresh: state(
transition('processIntent', 'confirmAddress',
guard(({ conversationAttributes }) => !conversationAttributes.confirmAddress?.confirmedAddress),
transition('processIntent', 'askForHouseNumber')
),
askForHouseNumber: state(
transition('processIntent', 'askForTelephoneNumber',
guard((ctx, { intent }) => intent.name === 'ANumber'),
reduce((ctx, { intent } ) => ({ ...ctx, houseNumber: intent.slots.number.value, misunderstandingCount: 0 }))
),
transition('processIntent', 'incorrectAddress',
guard(({ conversationAttributes }) => !conversationAttributes.confirmAddress?.correctAddress),
transition('processIntent', 'goBack',
guard(({ misunderstandingCount }, { intent }) => intent.name === 'GoBackIntent' || misunderstandingCount > 3)
),
transition('processIntent', 'letYouKnow',
guard(({ conversationAttributes }) => conversationAttributes.confirmAddress?.correctAddress),
transition('processIntent', 'askForHouseNumber',
reduce(ctx => ({ ...ctx, misunderstandingCount: ctx.misunderstandingCount + 1 })),
),
),
confirmAddress: state(
immediate('incorrectAddress',
guard(({ resuming, conversationAttributes }) => resuming && !conversationAttributes.confirmAddress?.correctAddress),
askForTelephoneNumber: state(
transition('processIntent', 'gotAllData',
guard((ctx, { intent }) => intent.name === 'APhoneNumber'),
reduce((ctx, { intent } ) => ({ ...ctx, phoneNumber: intent.slots.phoneNumber.value, misunderstandingCount: 0 }))
),
transition('processIntent', 'goBack',
guard(({ misunderstandingCount }, { intent }) => intent.name === 'GoBackIntent' || misunderstandingCount > 3)
),
immediate('letYouKnow',
guard(({ resuming, conversationAttributes }) => resuming && conversationAttributes.confirmAddress?.correctAddress),
transition('processIntent', 'askForTelephoneNumber',
reduce(ctx => ({ ...ctx, misunderstandingCount: ctx.misunderstandingCount + 1 })),
),
),
letYouKnow: state(
transition('processIntent', 'gotAllData',
transition('processIntent', 'thanksForReporting',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'yes'),
reduce(ctx => ({ ...ctx, letThemKnow: true }))
reduce(ctx => ({ ...ctx, letThemKnow: true, misunderstandingCount: 0 }))
),
transition('processIntent', 'gotAllData',
transition('processIntent', 'thanksForReporting',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'no'),
reduce(ctx => ({ ...ctx, letThemKnow: false, misunderstandingCount: 0 }))
),
transition('processIntent', 'goBack',
guard(({ misunderstandingCount }, { intent }) => intent.name === 'GoBackIntent' || misunderstandingCount > 3)
),
transition('processIntent', 'letYouKnow',
reduce(ctx => ({ ...ctx, misunderstandingCount: ctx.misunderstandingCount + 1 })),
),
),
letYouKnowWOutageReport: state(
transition('processIntent', 'thanksForReporting',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'yes'),
reduce(ctx => ({ ...ctx, letThemKnow: true, misunderstandingCount: 0 }))
),
transition('processIntent', 'thanksForReporting',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'no'),
reduce(ctx => ({ ...ctx, letThemKnow: false }))
reduce(ctx => ({ ...ctx, letThemKnow: false, misunderstandingCount: 0 }))
),
transition('processIntent', 'goBack',
guard(({ misunderstandingCount }, { intent }) => intent.name === 'GoBackIntent' || misunderstandingCount > 3)
Expand All @@ -49,34 +84,83 @@ const stateMap = {
reduce(ctx => ({ ...ctx, misunderstandingCount: ctx.misunderstandingCount + 1 })),
),
),
reportAnOutage: state(
transition('processIntent', 'letYouKnow',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'yes'),
reduce(ctx => ({ ...ctx, reportingOutage: true, misunderstandingCount: 0 }))
),
transition('processIntent', 'haveANiceDay',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'no'),
reduce(ctx => ({ ...ctx, reportingOutage: false, misunderstandingCount: 0 }))
),
transition('processIntent', 'goBack',
guard(({ misunderstandingCount }, { intent }) => intent.name === 'GoBackIntent' || misunderstandingCount > 3)
),
transition('processIntent', 'reportAnOutage',
reduce(ctx => ({ ...ctx, misunderstandingCount: ctx.misunderstandingCount + 1 })),
),
),
tryAgain: state(
transition('processIntent', 'askForHouseNumber',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'yes'),
reduce(ctx => ({ ...ctx, houseNumber: 0, phoneNumber: '', misunderstandingCount: 0 }))
),
transition('processIntent', 'goBack',
guard((ctx, { intent }) => intent.name === 'YesNoIntent' && utils.getSlotValueId(intent.slots.yesNo) === 'no'),
reduce(ctx => ({ ...ctx, misunderstandingCount: 0 }))
),
transition('processIntent', 'goBack',
guard(({ misunderstandingCount }, { intent }) => intent.name === 'GoBackIntent' || misunderstandingCount > 3)
),
transition('processIntent', 'tryAgain',
reduce(ctx => ({ ...ctx, misunderstandingCount: ctx.misunderstandingCount + 1 })),
),
),
gotAllData: invoke(callOutageApi,
transition('done', 'thanksForReporting'),
transition('done', 'reportAnOutage',
guard((ctx, {data: { result }}) => result === 'noOutage'),
reduce((ctx, { data }) => ({ ...ctx, attemptCount: ctx.attemptCount + 1 })),),
transition('done', 'letYouKnowWOutageReport',
guard((ctx, {data: { result }}) => result === 'yesOutage'),
reduce((ctx, { data }) => ({ ...ctx, attemptCount: ctx.attemptCount + 1, outageDetails: {...data} })),),
transition('done', 'tryAgain',
guard((ctx, {data: { result }}) => result === 'badCombination'),
reduce((ctx, { data }) => ({ ...ctx, attemptCount: ctx.attemptCount + 1 })),),
transition('error', 'error',
reduce((ctx, { error }) => ({ ...ctx, error })),
)
),
thanksForReporting: state(),
incorrectAddress: state(),
haveANiceDay: state(),
error: state(),
goBack: state(),
};

const reportOutage = {
handle: ({ dialog, sessionAttributes }) => ({
initialState: {
outageDetails: {},
attemptCount: 0,
houseNumber: 0,
phoneNumber: '',
reportAnOutage: '',
letThemKnow: '',
reportingOutage: '',
misunderstandingCount: 0,
error: '',
},
stateMap,
transitionStates: 'confirmAddress',
dialogMap: {
askForHouseNumber: ({ misunderstandingCount }) => dialog(`reportOutage.askForHouseNumber.${misunderstandingCount > 0 ? 'misheard' : 'confirm'}`),
askForTelephoneNumber: ({ misunderstandingCount }) => dialog(`reportOutage.askForTelephoneNumber.${misunderstandingCount > 0 ? 'misheard' : 'confirm'}`),
letYouKnow: ({ misunderstandingCount }) => dialog(`reportOutage.letYouKnow.${misunderstandingCount > 0 ? 'misheard' : 'confirm'}`),
letYouKnowWOutageReport: ({ misunderstandingCount, outageDetails }) => dialog(`reportOutage.letYouKnowWOutageReport.${misunderstandingCount > 0 ? 'misheard' : 'confirm'}`, {...outageDetails}),
reportAnOutage: ({ misunderstandingCount }) => dialog(`reportOutage.reportAnOutage.${misunderstandingCount > 0 ? 'misheard' : 'confirm'}`),
tryAgain: ({ misunderstandingCount, houseNumber, phoneNumber }) => dialog(`reportOutage.tryAgain.${misunderstandingCount > 0 ? 'misheard' : 'confirm'}`, {houseNumber, phoneNumber}),
thanksForReporting: ({ letThemKnow }) => dialog(`reportOutage.reply.${letThemKnow ? 'withContact' : 'noContact'}`),
incorrectAddress: () => dialog('reportOutage.wrongAddress', { website: fakeWebsite, phoneNumber: fakePhoneNumber }),
haveANiceDay: () => dialog(`reportOutage.reply.haveANiceDay`),
error: () => dialog('home.error'),
},
overrideResume: sessionAttributes.previousPoppedConversation === 'confirmAddress',
}),
intent: 'ReportOutage',
canInterrupt: true,
Expand Down
52 changes: 49 additions & 3 deletions lambda/dialog/ReportOutageDialog.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,40 @@
const reportOutage = {
wrongAddress: [
`Sorry, we can't report an outage for you because we don't have the right address for your account. Please call <say-as interpret-as="telephone">{{phoneNumber}}</say-as> or visit {{website}} to report the outage`,
],
askForHouseNumber: {
confirm:[
`What is the house number for the house that you would like to report an outage at?`
],
misheard: [
`Please just say a number for the address you're trying to report an outage at.`
]
},
askForTelephoneNumber: {
confirm:[
`What is the telephone number for service at this address?`
],
misheard: [
`Please say the telephone number for this address as a ten digit number.`
]
},
tryAgain: {
confirm: [
`I'm sorry but house number {{houseNumber}} and phone number {{phoneNumber}} don't match our records. Would you like to try saying the numbers again?`
],
misheard: [
`Was that a yes or a no.`,
`I didn't catch that. You can respond yes or no.`,
`I didn't catch that. Would you like to try saying the numbers again?`
]
},
reportAnOutage: {
confirm: [
`There are no reported outages in your area. Would you like to report an outage at your address?`
],
misheard: [
`Was that a yes or a no.`,
`I didn't catch that. You can respond yes or no.`,
`I didn't catch that. Would you like to report an outage at your address?`
]
},
letYouKnow: {
confirm: [
`Would you like a notification when the power is restored?`,
Expand All @@ -14,12 +47,25 @@ const reportOutage = {
`I didn't catch that. Would you like us to notify you when the power is restored?`
]
},
letYouKnowWOutageReport: {
confirm: [
`There is currently an outage in your area affecting {{impact}} customers in {{areaDescription}}. {{workDescription}} Would you like a notification when the power is restored?`
],
misheard: [
`Was that a yes or a no.`,
`I didn't catch that. You can respond yes or no.`,
`I didn't catch that. Would you like us to notify you when the power is restored?`
]
},
reply: {
withContact: [
`Great! We received your outage report, and we'll let you know when power is restored. Thank you.`
],
noContact: [
`Great! We received your outage report. Thank you.`
],
haveANiceDay: [
`Thank you. Come back if there is a problem.`
]
}
}
Expand Down
68 changes: 68 additions & 0 deletions skill-package/interactionModels/custom/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,46 @@
"estimated restoration time"
]
},
{
"name": "ANumber",
"slots": [
{
"name": "number",
"type": "AMAZON.NUMBER",
"samples": [
"{number}"
]
}
],
"samples": [
"{number}",
"house number {number}",
"the house number is {number}",
"the number is {number}"
]
},
{
"name": "APhoneNumber",
"slots": [
{
"name": "phoneNumber",
"type": "AMAZON.PhoneNumber",
"samples": [
"{phoneNumber}"
]
}
],
"samples": [
"{phoneNumber}",
"phone number is {phoneNumber}",
"area code {phoneNumber}",
"my number is {phoneNumber}",
"my phone number is {phoneNumber}",
"my telephone number is {phoneNumber}",
"the phone number is {phoneNumber}",
"the telephone number is {phoneNumber}"
]
},
{
"name": "ReportOutage",
"slots": [
Expand Down Expand Up @@ -302,6 +342,34 @@
"confirmationRequired": false,
"prompts": {}
},
{
"name": "ANumber",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "number",
"type": "AMAZON.NUMBER",
"elicitationRequired": false,
"confirmationRequired": false,
"prompts": {}
}
]
},
{
"name": "APhoneNumber",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "phoneNumber",
"type": "AMAZON.PhoneNumber",
"elicitationRequired": false,
"confirmationRequired": false,
"prompts": {}
}
]
},
{
"name": "OtherIntent",
"slots": [],
Expand Down

0 comments on commit 13e1676

Please sign in to comment.