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 NotAvailableException (Exception ):
12
+ def __init__ (self , message : str ) -> None :
13
+ self .message = message
14
+
15
+ def __str__ (self ) -> str :
16
+ return self .message
17
+
18
+ class TriviaQuizModel (object ):
19
+ def __init__ (self ):
20
+ # This could throw an exception. It will be picked up by
21
+ # game_handler and the game will end
22
+ self .current_board = self .get_trivia_quiz ()
23
+ self .scores = {} # type: Dict[int, int]
24
+
25
+ def update_board (self , board ):
26
+ self .current_board = deepcopy (board )
27
+
28
+ def validate_move (self , answer ):
29
+ return answer in "ABCD"
30
+
31
+ def make_move (self , move , player_number , is_computer = False ):
32
+ if player_number not in self .scores :
33
+ self .scores [player_number ] = 0
34
+ if not self .validate_move (move ):
35
+ raise BadMoveException ("Move not valid" )
36
+ self .current_board = self .get_trivia_quiz ()
37
+ if move == self .current_board ['correct_letter' ]:
38
+ self .scores [player_number ] += 1
39
+ else :
40
+ self .scores [player_number ] -= 1
41
+ if self .scores [player_number ] < 0 :
42
+ self .scores [player_number ] = 0
43
+ return {
44
+ 'correct' : move == self .current_board ['correct_letter' ],
45
+ 'correct_letter' : self .current_board ['correct_letter' ],
46
+ 'score' : self .scores [player_number ]
47
+ }
48
+
49
+ def determine_game_over (self , players ):
50
+ for player_number , score in self .scores .items ():
51
+ if score > 5 :
52
+ # Game over
53
+ return players [player_number ]
54
+ return
55
+
56
+ def get_trivia_quiz (self ) -> Dict [str , Any ]:
57
+ payload = self .get_trivia_payload ()
58
+ quiz = self .get_quiz_from_payload (payload )
59
+ return quiz
60
+
61
+ def get_trivia_payload (self ) -> Dict [str , Any ]:
62
+
63
+ url = 'https://opentdb.com/api.php?amount=1&type=multiple'
64
+
65
+ try :
66
+ data = requests .get (url )
67
+
68
+ except requests .exceptions .RequestException :
69
+ raise NotAvailableException ("Uh-Oh! Trivia service is down." )
70
+
71
+ if data .status_code != 200 :
72
+ raise NotAvailableException ("Uh-Oh! Trivia service is down." )
73
+
74
+ payload = data .json ()
75
+ return payload
76
+
77
+ def get_quiz_from_payload (self , payload : Dict [str , Any ]) -> Dict [str , Any ]:
78
+ result = payload ['results' ][0 ]
79
+ question = result ['question' ]
80
+ letters = ['A' , 'B' , 'C' , 'D' ]
81
+ random .shuffle (letters )
82
+ correct_letter = letters [0 ]
83
+ answers = dict ()
84
+ answers [correct_letter ] = result ['correct_answer' ]
85
+ for i in range (3 ):
86
+ answers [letters [i + 1 ]] = result ['incorrect_answers' ][i ]
87
+
88
+ def fix_quotes (s : str ) -> Optional [str ]:
89
+ # opentdb is nice enough to escape HTML for us, but
90
+ # we are sending this to code that does that already :)
91
+ #
92
+ # Meanwhile Python took until version 3.4 to have a
93
+ # simple html.unescape function.
94
+ try :
95
+ return html .unescape (s )
96
+ except Exception :
97
+ raise Exception ('Please use python3.4 or later for this bot.' )
98
+ answers = {
99
+ letter : fix_quotes (answer )
100
+ for letter , answer
101
+ in answers .items ()
102
+ }
103
+ quiz = dict (
104
+ question = fix_quotes (question ),
105
+ answers = answers ,
106
+ answered_options = [],
107
+ pending = True ,
108
+ correct_letter = correct_letter ,
109
+ )
110
+ return quiz
0 commit comments