alexa-samples / skill-sample-nodejs-buttons-trivia

This is a sample trivia skill that will allow developers to get a head start on their trivia games using Echo Buttons. It allows for roll-call of the players, asking trivia questions, and determining whether the voice inputs matched the answers.
Other
32 stars 35 forks source link

Multiple Correct Answers #10

Closed CraigHDev closed 5 years ago

CraigHDev commented 5 years ago

Hi,

I am quite new to doing this and still learning so hopefully you can help me.

I have found your code quite useful and have got everything working perfectly as outlined in your guide

I was wondering how would i be able to expand this to allow muliple correct answers for each question e.g Full answer = Castlevania Symphony of the night so i would also like short versions like Castlevania or symphony to also be allowed.

Basically I want to be able to allow users to say partial answers but still register that its correct.

Any help with this would be brilliant.

mdinescu commented 5 years ago

Great question!

The way the skill is coded, only one of the answers is considered correct but you could modify the logic to accept a list of correct answers instead of just one.

The question/answers structure looks like this:

{
   index: 2,
   question: 'What is the only type of bear native to South America?',
   answers: ['brown bear', 'kodiac', 'giant panda', 'spectacled bear'],
   correct_answer: 'spectacled bear'
}

You could change the correct_answer to be an array instead, like so:

{
   index: 2,
   question: 'What is the only type of bear native to South America?',
   answers: ['brown bear', 'kodiac', 'giant panda', 'spectacled bear'],
   correct_answer: ['spectacled bear', 'spectacled']
}

And then, update the logic in the answerQuestion function (https://github.com/alexa/skill-sample-nodejs-buttons-trivia/blob/master/lambda/custom/utils/game.js#L474-L498) to check each of the values in the correct_answer instead of just one. If any of them is a match then you consider the question answered correctly.

P.S. Make sure any valid answers you provide are represented in the interaction model too!

I hope this helps

CraigHDev commented 5 years ago

Thanks for getting back to me so quickly its really appreciated.

Going by the above it looks like i just missed out editing the answerQuestion function in the game.js file as i already edited the questions into an array and edited the interaction model but didnt even consider editing other files yet.

Now i just need to work out how to edit the answerQuestion section correctly and i will hopefully get it working.

CraigHDev commented 5 years ago

@mdinescu Sorry to bother you again.

I have been looking at this over the past couple of days and have been unable to figure out a way of getting the project to accept multiple correct answers.

I have altered the Array and Interaction models as discussed and I have tried various ways of editing the section you stated but nothing has worked so far :(

Any further help would be greatly appreciated

mdinescu commented 5 years ago

Not sure what you've tried but basically, I suggest making a loop through the values in the correct_answer array:

let answered = false;
for (var aIndex = 0; aIndex < currentQuestion.correct_answer.length; aIndex++) {
    let correct_answer = gameHelper.normalizeAnswer(currentQuestion.correct_answer[aIndex]);

    /***  what follows here is the same logic as was there before for a single correct answer ***/ 
    // Check to see if we have the correct answer
    if (settings.GAME.MULTIPLE_CHOICE === true){
        let matches = stringSimilarity.findBestMatch(answer, answers);
        logger.debug('Looking for correct answer \'' + correct_answer + '\' exceeding settings threshold of ' +
        settings.GAME.ANSWER_SIMILARITY + ' in \n' + JSON.stringify(matches, null, 2));
        // loop through all the matches, in case there is more than one that is good enough to consider
        for (var i = 0; i < matches.ratings.length; ++i) {
           let match = matches.ratings[i];
           if (match.rating >= settings.GAME.ANSWER_SIMILARITY && match.target === correct_answer) {
               answered = true;
               break;
           }
        }
    } else {
        let answerSimilarity = stringSimilarity.compareTwoStrings(correct_answer, answer);
        logger.debug('Comparing answer \'' + answer + '\' to correct answer \'' +
            correct_answer + '\' yields similarity of ' + answerSimilarity +
            ' vs settings threshold of ' + settings.GAME.ANSWER_SIMILARITY);
        if (answerSimilarity >= settings.GAME.ANSWER_SIMILARITY) {
           answered = true;
        }
    }
    /*** if this answer was correct, stop the loop ***/
    if (answered === true) {
        break;
    }
}

/*** here you continue the rest of the implementation of the answerQuestion function ***/
CraigHDev commented 5 years ago

Hi @mdinescu , Thanks for getting back to me so quickly its really appreciated.

So I have tried adding the above code by replacing lines 474 - 501 with what you provided. I think added the questions into an array and also updated the interaction model.

Upon running the skill in Developer console i now receive the following error: There was a problem with the requested skill's response. This previously worked for single answers so i am unsure what has gone wrong.

mdinescu commented 5 years ago

Can you post a pull request with the changes?

Also - what is the error you get in the Lambda console? That will tell you where the problem is

CraigHDev commented 5 years ago

game.zip

I have attached the Game.js file with the change i have currently made. The only change is i have added the code you provided instead of the original single answer code.

In Lambda it appears to be breaking further down for a parsing error for an else statement on line 547. Any attempt i have made to edit this line has broke breaks something else further down.

mdinescu commented 5 years ago

It looks like when you edited the code you removed one of the lines that was checking if the answer is correct. You also had a duplicate call to gameHelper.normalizeAnswer(..) which would potentially cause some issues.

Try this: https://gist.github.com/mdinescu/3d958b5d47754acabb71d707c16ad0ed#file-game-js-L472-L509

CraigHDev commented 5 years ago

@mdinescu This is brilliant thanks :)

So I have just replaced the game file with the new version that you created and its still outputting an error in Lambda.

Its stating on lines 558, 612 that correct_answer isn't defined. Any ideas?

mdinescu commented 5 years ago

I see - that's the code path that handles the incorrect answers. In the original game, where you had only one possible correct answer, Alexa would communicate that to the player(s).

In your case you have to make a decision about how to handle that in a multiple-correct-answers type of game.

You could have it not give the correct answer at all, or you could have it say something like: "one of the possible answers was: " and pick either the first, or one at random from the list of correct answers.

This correct_answer: correct_answer would have to become: correct_answer: currentQuestion.correct_answer[0] (or instead of 0 you can make it pick an index at random)

CraigHDev commented 5 years ago

@mdinescu So adding in the currentQuestion.correct_answer[0] fixed all of the errors lambda was displaying however when running the skill in amazon dev now it is only recognizing the first correct answer out of the multiple choices. Any of the alternative answer are incorrect.

I have the correct answers in an array as previously shown above and also within the interaction model.

Adding this feature in is really stumping me :(

You have been a great help and any further assistance would be greatly appreciated.

mdinescu commented 5 years ago

I'm not sure what it is but I would look into adding further debug statements to see what path the code follows.

Also, you should see in the logs one of these lines: https://github.com/alexa/skill-sample-nodejs-buttons-trivia/issues/10#issuecomment-453782381 or https://gist.github.com/mdinescu/3d958b5d47754acabb71d707c16ad0ed#file-game-js-L495-L497

Things to inspect would be the length of the array, the normalized answer etc.

CraigHDev commented 5 years ago

Hi @mdinescu

I have been working on this and still cant get this working :(

Do you have a working example available? I think seeing it working would allow me to work out how this works and whats gone wrong with the previous attempts.

Any help would be amazing.

justinpecott commented 5 years ago

Hi @CraigHDev I whipped up a quick working example. Just swap this game.js into your project. Make sure you have the answers in array form as note earlier in the thread. Also make sure each correct answer exists in the possible answers - else it won't work.

https://gist.github.com/justinpecott/a273ec66b8dab122d567a84a20b67049

CraigHDev commented 5 years ago

@justinpecott

Thank you so much i have now got this working with multiple correct answers being allowed. I still have to tidy up how alexa reads it out as she keeps pausing but that shouldn't be too hard to work out :)

i do have a further question if you could assist. If a user now gets a question incorrect it will read out all of the possible correct answers and since these are just variants of the larger full answer e.g for 'Castlevania Symphony of the night' i would also have "castlevania' and 'symphony' and the current code reads all three however i would like it to just read the full correct answer so in this example just 'Castlevania Symphony of the night'

Any ideas on how to get this to only read out a single answer?

justinpecott commented 5 years ago

Look for the lines (560, 614) containing

correct_answers.join(' or ')

and change them to something like this which will only read the first in the array

correct_answers[0]
CraigHDev commented 5 years ago

Hi @mdinescu and @justinpecott

I have now got the skill to accept multiple correct answers and only state one of the correct answers. Now i just need to continue adding content and tidy up alexas responses :)

I would like to thank you both for all your help getting this working. Its been really appreciated.