Search code examples
javascriptnode.jsalexa-skills-kit

Trying to capture Loan Amount and Interest rate in Alexa and compute EMI


I am trying to build a very basic EMI Calculator. I want to capture the Loan amount and Interest rate in separate intents and then do the maths part. However, after capturing the Loan amount and confirming the same the program doesn't move to capture the interest rate.

I can reach only to the point where Alexa confirms the value of the loan amount.

Please help me understand why?

const Alexa = require('ask-sdk-core');


//Launch request and welcome message.
const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speakOutput = 'Hello! Welcome to your E.M.I. Calculator. Please tell me the loan amount you want to calculate the E.M.I. for';
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();
    }
};

//capture the loan amount, save it in local variable and confirm to user the amount.
const captureLoanAmountHandler = {
    canHandle(handlerInput){
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'captureloanamount';
    },
    async handle(handlerInput){
        const currencyName = handlerInput.requestEnvelope.request.intent.slots.currency.value;
        const loanAmount = handlerInput.requestEnvelope.request.intent.slots.loanamount.value;
        
        const speakOutput = `Ok, I have captured the loan amount as ${currencyName} ${loanAmount}.`;
 //       return handlerInput.responseBuilder.speak(speakOutput);
        
 //       return handlerInput.responseBuilder.speak(speakOutput).getResponse();
        
    }
    };
    
//Prompt user for interest rate and capture it
const captureInterestRateHandler = {
    canHandle(handlerInput){
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'captureinterestrate';
    },
    
    async handle(handlerInput){
        let interestRateCaptured = false;
        while (!interestRateCaptured){
            const speakOutput = 'Please tell me the interest rate';
               interestRateCaptured = true; 
        return handlerInput.responseBuilder
            .speak(speakOutput).getResponse();
        }    
            
        const iRate = handlerInput.requestEnvelope.request.intent.slots.roi.value;    
        const speakOutput1 = `Ok, I have captured the interest rate as ${iRate}`;
        return handlerInput.responseBuilder.speak(speakOutput1).getResponse();
    }
}```

Solution

  • welcome to stackoverflow!

    There are some mistakes in your code, I'll try to describe/fix them one by one.

    Your CaptureLoanAmountHandler ends with simple .speak command, which means that Alexa will close the session as soon as she finished sentence you asked her to speak. In order to keep the session open, add .reprompt to the response builder (you can also use .shouldEndSession with false parameter, but .reprompt is better from UX point of view) and add there some clues for User how to interact with your skill:

    //capture the loan amount, save it in local variable and confirm to user the amount.
    const CaptureLoanAmountHandler = {
        canHandle(handlerInput){
            return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
                && Alexa.getIntentName(handlerInput.requestEnvelope) === 'captureloanamount';
        },
        async handle(handlerInput){
            const currencyName = handlerInput.requestEnvelope.request.intent.slots.currency.value;
            const loanAmount = handlerInput.requestEnvelope.request.intent.slots.loanamount.value;
            
            const speakOutput = `Ok, I have captured the loan amount as ${currencyName} ${loanAmount}. Now tell me your interest rate`;
            
            return handlerInput
                     .responseBuilder
                     .speak(speakOutput)
                     .reprompt('Say: interest rate is...')
                     .getResponse();
            
        }
    };
    

    Your CaptureInterestRateHandler should not contain while loop. In your code it will run only once since you set the guard to true in the first run ;)

    //Prompt user for interest rate and capture it
    const CaptureInterestRateHandler = {
        canHandle(handlerInput){
            return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
                && Alexa.getIntentName(handlerInput.requestEnvelope) === 'captureinterestrate';
        },
        
        async handle(handlerInput){
            const iRate = handlerInput.requestEnvelope.request.intent.slots.roi.value;    
            const speakOutput1 = `Ok, I have captured the interest rate as ${iRate}`;
            return handlerInput.responseBuilder.speak(speakOutput1).getResponse();
        }
    }
    

    I guess there should be some calculations done when you collected all input data.

    According to your comment:

    //capture the loan amount, save it in local variable and confirm to user the amount.
    

    I assume you expect to see loan amount value later in other intent handlers - I am afraid you won't :(. All variables, even const is available in the single handler run. In order to access them in other intents, you need to store them in SessionAttributes.

    Apart from that look closer to the Dialog - spoiler alert - it just does all dialog-related magic behind the scenes and at the end you get values your request for ;)