bots: Improve response at 3 wrong answers in trivia bot.

This commit is contained in:
Rhea Parekh 2018-06-10 22:29:43 +05:30 committed by showell
parent f25772d1dc
commit b28cfcac3d
2 changed files with 103 additions and 11 deletions

View file

@ -2,12 +2,13 @@ import json
import html import html
from unittest.mock import patch from unittest.mock import patch
from typing import Optional from typing import Optional, Tuple, Any, Dict
from zulip_bots.test_lib import ( from zulip_bots.test_lib import (
BotTestCase, BotTestCase,
DefaultTests, DefaultTests,
read_bot_fixture_data, read_bot_fixture_data,
StubBotHandler,
) )
from zulip_bots.request_test_lib import ( from zulip_bots.request_test_lib import (
@ -17,6 +18,9 @@ from zulip_bots.request_test_lib import (
from zulip_bots.bots.trivia_quiz.trivia_quiz import ( from zulip_bots.bots.trivia_quiz.trivia_quiz import (
get_quiz_from_payload, get_quiz_from_payload,
fix_quotes, fix_quotes,
get_quiz_from_id,
update_quiz,
handle_answer,
) )
class TestTriviaQuizBot(BotTestCase, DefaultTests): class TestTriviaQuizBot(BotTestCase, DefaultTests):
@ -29,6 +33,13 @@ class TestTriviaQuizBot(BotTestCase, DefaultTests):
'* **D** Mammals\n' + \ '* **D** Mammals\n' + \
'**reply**: answer Q001 <letter>' '**reply**: answer Q001 <letter>'
def get_test_quiz(self) -> Tuple[Dict[str, Any], Any]:
bot_handler = StubBotHandler()
quiz_payload = read_bot_fixture_data('trivia_quiz', 'test_new_question')['response']
with patch('random.shuffle'):
quiz = get_quiz_from_payload(quiz_payload)
return quiz, bot_handler
def _test(self, message: str, response: str, fixture: Optional[str]=None) -> None: def _test(self, message: str, response: str, fixture: Optional[str]=None) -> None:
if fixture: if fixture:
with self.mock_http_conversation(fixture): with self.mock_http_conversation(fixture):
@ -74,9 +85,12 @@ class TestTriviaQuizBot(BotTestCase, DefaultTests):
with patch('random.shuffle'): with patch('random.shuffle'):
quiz = get_quiz_from_payload(quiz_payload) quiz = get_quiz_from_payload(quiz_payload)
# Test initial storage
self.assertEqual(quiz['question'], 'Which class of animals are newts members of?') self.assertEqual(quiz['question'], 'Which class of animals are newts members of?')
self.assertEqual(quiz['correct_letter'], 'A') self.assertEqual(quiz['correct_letter'], 'A')
self.assertEqual(quiz['answers']['D'], 'Mammals') self.assertEqual(quiz['answers']['D'], 'Mammals')
self.assertEqual(quiz['answered_options'], [])
self.assertEqual(quiz['pending'], True)
# test incorrect answer # test incorrect answer
with patch('zulip_bots.bots.trivia_quiz.trivia_quiz.get_quiz_from_id', with patch('zulip_bots.bots.trivia_quiz.trivia_quiz.get_quiz_from_id',
@ -88,3 +102,56 @@ class TestTriviaQuizBot(BotTestCase, DefaultTests):
return_value=json.dumps(quiz)): return_value=json.dumps(quiz)):
with patch('zulip_bots.bots.trivia_quiz.trivia_quiz.start_new_quiz') as mock_new_quiz: with patch('zulip_bots.bots.trivia_quiz.trivia_quiz.start_new_quiz') as mock_new_quiz:
self._test('answer Q001 A', '**CORRECT!** Amphibian :tada:') self._test('answer Q001 A', '**CORRECT!** Amphibian :tada:')
def test_update_quiz(self) -> None:
quiz, bot_handler = self.get_test_quiz()
update_quiz(quiz, 'Q001', bot_handler)
test_quiz = json.loads(bot_handler.storage.get('Q001'))
self.assertEqual(test_quiz, quiz)
def test_get_quiz_from_id(self) -> None:
quiz, bot_handler = self.get_test_quiz()
bot_handler.storage.put('Q001', quiz)
self.assertEqual(get_quiz_from_id('Q001', bot_handler), quiz)
def test_handle_answer(self) -> None:
quiz, bot_handler = self.get_test_quiz()
# create test initial storage
update_quiz(quiz, 'Q001', bot_handler)
# test for a correct answer
start_new_question, response = handle_answer(quiz, 'A', 'Q001', bot_handler)
self.assertTrue(start_new_question)
self.assertEqual(response, '**CORRECT!** Amphibian :tada:')
# test for an incorrect answer
start_new_question, response = handle_answer(quiz, 'D', 'Q001', bot_handler)
self.assertFalse(start_new_question)
self.assertEqual(response, '**WRONG!** D is not correct :disappointed:')
def test_handle_answer_three_failed_attempts(self) -> None:
quiz, bot_handler = self.get_test_quiz()
# create test storage for a question which has been incorrectly answered twice
quiz['answered_options'] = ['C', 'B']
update_quiz(quiz, 'Q001', bot_handler)
# test response and storage after three failed attempts
start_new_question, response = handle_answer(quiz, 'D', 'Q001', bot_handler)
self.assertEqual(response, '**WRONG!** :disappointed: The correct answer is Amphibian.')
self.assertTrue(start_new_question)
quiz_reset = json.loads(bot_handler.storage.get('Q001'))
self.assertEqual(quiz_reset['pending'], False)
# test response after question has ended
incorrect_answers = ['B', 'C', 'D']
for ans in incorrect_answers:
start_new_question, response = handle_answer(quiz, ans, 'Q001', bot_handler)
self.assertEqual(response, '**WRONG!** :disappointed: The correct answer is Amphibian.')
self.assertFalse(start_new_question)
start_new_question, response = handle_answer(quiz, 'A', 'Q001', bot_handler)
self.assertEqual(response, '**CORRECT!** Amphibian :tada:')
self.assertFalse(start_new_question)
# test storage after question has ended
quiz_reset = json.loads(bot_handler.storage.get('Q001'))
self.assertEqual(quiz_reset['pending'], False)

View file

@ -43,9 +43,9 @@ class TriviaQuizHandler:
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
return return
quiz = json.loads(quiz_payload) quiz = json.loads(quiz_payload)
correct, bot_response = grade_question(quiz, answer) start_new_question, bot_response = handle_answer(quiz, answer, quiz_id, bot_handler)
bot_handler.send_reply(message, bot_response) bot_handler.send_reply(message, bot_response)
if correct: if start_new_question:
start_new_quiz(message, bot_handler) start_new_quiz(message, bot_handler)
return return
else: else:
@ -125,6 +125,8 @@ def get_quiz_from_payload(payload: Dict[str, Any]) -> Dict[str, Any]:
quiz = dict( quiz = dict(
question=fix_quotes(question), question=fix_quotes(question),
answers=answers, answers=answers,
answered_options=[],
pending=True,
correct_letter=correct_letter, correct_letter=correct_letter,
) )
return quiz return quiz
@ -196,16 +198,39 @@ Q: {question}
) )
return content return content
def grade_question(quiz: Dict[str, Any], answer: str) -> Tuple[bool, str]: def update_quiz(quiz: Dict[str, Any], quiz_id: str, bot_handler: Any) -> None:
correct = (answer == quiz['correct_letter']) bot_handler.storage.put(quiz_id, json.dumps(quiz))
if correct: def build_response(is_correct: bool, num_answers: int) -> str:
long_answer = quiz['answers'][answer] if is_correct:
response = '**CORRECT!** {long_answer} :tada:'.format(long_answer=long_answer) response = '**CORRECT!** {answer} :tada:'
return correct, response else:
if num_answers >= 3:
response = '**WRONG!** :disappointed: The correct answer is {answer}.'
else:
response = '**WRONG!** {option} is not correct :disappointed:'
return response
response = '**WRONG!** {answer} is not correct :disappointed:'.format(answer=answer) def handle_answer(quiz: Dict[str, Any], option: str, quiz_id: str,
return correct, response bot_handler: Any) -> Tuple[bool, str]:
answer = quiz['answers'][quiz['correct_letter']]
is_new_answer = (option not in quiz['answered_options'])
if is_new_answer:
quiz['answered_options'].append(option)
num_answers = len(quiz['answered_options'])
is_correct = (option == quiz['correct_letter'])
start_new_question = quiz['pending'] and (is_correct or num_answers >= 3)
if start_new_question or is_correct:
quiz['pending'] = False
if is_new_answer or start_new_question:
update_quiz(quiz, quiz_id, bot_handler)
response = build_response(is_correct, num_answers).format(
option=option, answer=answer, id=quiz_id)
return start_new_question, response
handler_class = TriviaQuizHandler handler_class = TriviaQuizHandler