Skip to content

Commit 4b92eea

Browse files
committed
bots: port trivia_quiz to game_handler
1 parent 4382138 commit 4b92eea

File tree

3 files changed

+202
-241
lines changed

3 files changed

+202
-241
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
from zulip_bots.game_handler import BadMoveException
2+
import html
3+
import json
4+
import requests
5+
import random
6+
from copy import deepcopy
7+
from zulip_bots.lib import Any
8+
9+
from typing import Optional, Any, Dict, Tuple
10+
11+
class TriviaQuizModel(object):
12+
def __init__(self):
13+
self.current_board = self.get_trivia_quiz()
14+
self.scores = {}
15+
16+
def update_board(self, board):
17+
self.current_board = deepcopy(board)
18+
19+
def validate_move(self, answer):
20+
return answer in "ABCD"
21+
22+
def make_move(self, move, player_number, is_computer=False):
23+
if player_number not in self.scores:
24+
self.scores[player_number] = 0
25+
if not self.validate_move(move):
26+
raise BadMoveException()
27+
self.current_board = self.get_trivia_quiz()
28+
if move == self.current_board['correct_letter']:
29+
self.scores[player_number] += 1
30+
else:
31+
self.scores[player_number] -= 1
32+
return {
33+
'correct': move == self.current_board['correct_letter'],
34+
'correct_letter': self.current_board['correct_letter'],
35+
'score': self.scores[player_number]
36+
}
37+
38+
def determine_game_over(self, players):
39+
for player_number, score in self.scores.items():
40+
if score > 5:
41+
# Game over
42+
return players[player_number]
43+
return
44+
45+
def get_trivia_quiz(self) -> Dict[str, Any]:
46+
payload = self.get_trivia_payload()
47+
quiz = self.get_quiz_from_payload(payload)
48+
return quiz
49+
50+
def get_trivia_payload(self) -> Dict[str, Any]:
51+
52+
url = 'https://opentdb.com/api.php?amount=1&type=multiple'
53+
54+
try:
55+
data = requests.get(url)
56+
57+
except requests.exceptions.RequestException:
58+
raise NotAvailableException()
59+
60+
if data.status_code != 200:
61+
raise NotAvailableException()
62+
63+
payload = data.json()
64+
return payload
65+
66+
def get_quiz_from_payload(self, payload: Dict[str, Any]) -> Dict[str, Any]:
67+
result = payload['results'][0]
68+
question = result['question']
69+
letters = ['A', 'B', 'C', 'D']
70+
random.shuffle(letters)
71+
correct_letter = letters[0]
72+
answers = dict()
73+
answers[correct_letter] = result['correct_answer']
74+
for i in range(3):
75+
answers[letters[i+1]] = result['incorrect_answers'][i]
76+
77+
def fix_quotes(s: str) -> Optional[str]:
78+
# opentdb is nice enough to escape HTML for us, but
79+
# we are sending this to code that does that already :)
80+
#
81+
# Meanwhile Python took until version 3.4 to have a
82+
# simple html.unescape function.
83+
try:
84+
return html.unescape(s)
85+
except Exception:
86+
raise Exception('Please use python3.4 or later for this bot.')
87+
answers = {
88+
letter: fix_quotes(answer)
89+
for letter, answer
90+
in answers.items()
91+
}
92+
quiz = dict(
93+
question=fix_quotes(question),
94+
answers=answers,
95+
answered_options=[],
96+
pending=True,
97+
correct_letter=correct_letter,
98+
)
99+
return quiz

zulip_bots/zulip_bots/bots/trivia_quiz/test_trivia_quiz.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@
1515
mock_request_exception,
1616
)
1717

18-
from zulip_bots.bots.trivia_quiz.trivia_quiz import (
19-
get_quiz_from_payload,
20-
fix_quotes,
21-
get_quiz_from_id,
22-
update_quiz,
23-
handle_answer,
24-
)
18+
from zulip_bots.bots.trivia_quiz.controller import TriviaQuizModel
2519

2620
class TestTriviaQuizBot(BotTestCase, DefaultTests):
2721
bot_name = "trivia_quiz" # type: str
@@ -31,7 +25,7 @@ class TestTriviaQuizBot(BotTestCase, DefaultTests):
3125
'* **B** Fish\n' + \
3226
'* **C** Reptiles\n' + \
3327
'* **D** Mammals\n' + \
34-
'**reply**: answer Q001 <letter>'
28+
'**reply**: <letter>'
3529

3630
def get_test_quiz(self) -> Tuple[Dict[str, Any], Any]:
3731
bot_handler = StubBotHandler()
@@ -47,13 +41,6 @@ def _test(self, message: str, response: str, fixture: Optional[str]=None) -> Non
4741
else:
4842
self.verify_reply(message, response)
4943

50-
def test_bot_responds_to_empty_message(self) -> None:
51-
self._test('', 'type "new" for a new question')
52-
53-
def test_bot_new_question(self) -> None:
54-
with patch('random.shuffle'):
55-
self._test('new', self.new_question_response, 'test_new_question')
56-
5744
def test_question_not_available(self) -> None:
5845
self._test('new', 'Uh-Oh! Trivia service is down.', 'test_status_code')
5946

0 commit comments

Comments
 (0)