Mercurial > libervia-backend
comparison src/plugins/plugin_misc_quiz.py @ 683:75e4f5e2cc65
plugins radiocol, card_game, quiz: code factorization
author | souliane <souliane@mailoo.org> |
---|---|
date | Wed, 23 Oct 2013 12:45:13 +0200 |
parents | 2805fa3f4bdf |
children | f610864eb7a5 |
comparison
equal
deleted
inserted
replaced
682:2805fa3f4bdf | 683:75e4f5e2cc65 |
---|---|
28 from zope.interface import implements | 28 from zope.interface import implements |
29 | 29 |
30 from wokkel import disco, iwokkel, data_form | 30 from wokkel import disco, iwokkel, data_form |
31 from sat.tools.xml_tools import dataForm2XML | 31 from sat.tools.xml_tools import dataForm2XML |
32 from sat.tools.frontends.games import TarotCard | 32 from sat.tools.frontends.games import TarotCard |
33 | 33 from sat.tools.plugins.games import RoomGame |
34 from time import time | 34 from time import time |
35 | 35 |
36 try: | 36 try: |
37 from twisted.words.protocols.xmlstream import XMPPHandler | 37 from twisted.words.protocols.xmlstream import XMPPHandler |
38 except ImportError: | 38 except ImportError: |
53 "handler": "yes", | 53 "handler": "yes", |
54 "description": _("""Implementation of Quiz game""") | 54 "description": _("""Implementation of Quiz game""") |
55 } | 55 } |
56 | 56 |
57 | 57 |
58 class Quiz(object): | 58 class Quiz(RoomGame): |
59 | 59 |
60 def __init__(self, host): | 60 def __init__(self, host): |
61 info(_("Plugin Quiz initialization")) | 61 info(_("Plugin Quiz initialization")) |
62 self.host = host | 62 RoomGame.__init__(self, host, PLUGIN_INFO, (NS_QG, QG_TAG), player_init_data={'score': 0}, |
63 self.games = {} | 63 options={'stage': None}) |
64 self.waiting_inv = {} # Invitation waiting for people to join to launch a game | 64 host.bridge.addMethod("quizGameLaunch", ".plugin", in_sign='ass', out_sign='', method=self.prepareRoom) # args: players, profile |
65 host.bridge.addMethod("quizGameLaunch", ".plugin", in_sign='ass', out_sign='', method=self.quizGameLaunch) # args: players, profile | 65 host.bridge.addMethod("quizGameCreate", ".plugin", in_sign='sass', out_sign='', method=self.createGame) # args: room_jid, players, profile |
66 host.bridge.addMethod("quizGameCreate", ".plugin", in_sign='sass', out_sign='', method=self.quizGameCreate) # args: room_jid, players, profile | 66 host.bridge.addMethod("quizGameReady", ".plugin", in_sign='sss', out_sign='', method=self.playerReady) # args: player, referee, profile |
67 host.bridge.addMethod("quizGameReady", ".plugin", in_sign='sss', out_sign='', method=self.newPlayerReady) # args: player, referee, profile | |
68 host.bridge.addMethod("quizGameAnswer", ".plugin", in_sign='ssss', out_sign='', method=self.playerAnswer) | 67 host.bridge.addMethod("quizGameAnswer", ".plugin", in_sign='ssss', out_sign='', method=self.playerAnswer) |
69 host.bridge.addSignal("quizGameStarted", ".plugin", signature='ssass') # args: room_jid, referee, players, profile | 68 host.bridge.addSignal("quizGameStarted", ".plugin", signature='ssass') # args: room_jid, referee, players, profile |
70 host.bridge.addSignal("quizGameNew", ".plugin", | 69 host.bridge.addSignal("quizGameNew", ".plugin", |
71 signature='sa{ss}s', | 70 signature='sa{ss}s', |
72 doc={'summary': 'Start a new game', | 71 doc={'summary': 'Start a new game', |
114 doc={'summary': "Nobody answered the question in time", | 113 doc={'summary': "Nobody answered the question in time", |
115 'param_0': "room_jid: jid of game's room", | 114 'param_0': "room_jid: jid of game's room", |
116 'param_1': "time_left: time left before timer expiration", | 115 'param_1': "time_left: time left before timer expiration", |
117 'param_2': '%(doc_profile)s'}) | 116 'param_2': '%(doc_profile)s'}) |
118 host.trigger.add("MUC user joined", self.userJoinedTrigger) | 117 host.trigger.add("MUC user joined", self.userJoinedTrigger) |
119 | |
120 def createGameElt(self, to_jid, type="normal"): | |
121 type = "normal" if to_jid.resource else "groupchat" | |
122 elt = domish.Element((None, 'message')) | |
123 elt["to"] = to_jid.full() | |
124 elt["type"] = type | |
125 elt.addElement((NS_QG, QG_TAG)) | |
126 return elt | |
127 | 118 |
128 def __game_data_to_xml(self, game_data): | 119 def __game_data_to_xml(self, game_data): |
129 """Convert a game data dict to domish element""" | 120 """Convert a game data dict to domish element""" |
130 game_data_elt = domish.Element((None, 'game_data')) | 121 game_data_elt = domish.Element((None, 'game_data')) |
131 for data in game_data: | 122 for data in game_data: |
170 score_elt['score'] = str(score[player]) | 161 score_elt['score'] = str(score[player]) |
171 answer_result_elt.addChild(score_elt) | 162 answer_result_elt.addChild(score_elt) |
172 | 163 |
173 return answer_result_elt | 164 return answer_result_elt |
174 | 165 |
175 def __create_started_elt(self, players): | |
176 """Create a game_started domish element""" | |
177 started_elt = domish.Element((None, 'started')) | |
178 idx = 0 | |
179 for player in players: | |
180 player_elt = domish.Element((None, 'player')) | |
181 player_elt.addContent(player) | |
182 player_elt['index'] = str(idx) | |
183 idx += 1 | |
184 started_elt.addChild(player_elt) | |
185 return started_elt | |
186 | |
187 def __ask_question(self, question_id, question, timer): | 166 def __ask_question(self, question_id, question, timer): |
188 """Create a element for asking a question""" | 167 """Create a element for asking a question""" |
189 question_elt = domish.Element((None, 'question')) | 168 question_elt = domish.Element((None, 'question')) |
190 question_elt['id'] = question_id | 169 question_elt['id'] = question_id |
191 question_elt['timer'] = str(timer) | 170 question_elt['timer'] = str(timer) |
198 next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) # the player after the dealer start | 177 next_player_idx = game_data['current_player'] = (game_data['init_player'] + 1) % len(game_data['players']) # the player after the dealer start |
199 game_data['first_player'] = next_player = game_data['players'][next_player_idx] | 178 game_data['first_player'] = next_player = game_data['players'][next_player_idx] |
200 to_jid = jid.JID(room_jid.userhost() + "/" + next_player) | 179 to_jid = jid.JID(room_jid.userhost() + "/" + next_player) |
201 mess = self.createGameElt(to_jid) | 180 mess = self.createGameElt(to_jid) |
202 yourturn_elt = mess.firstChildElement().addElement('your_turn') | 181 yourturn_elt = mess.firstChildElement().addElement('your_turn') |
203 self.host.profiles[profile].xmlstream.send(mess) | |
204 | |
205 def userJoinedTrigger(self, room, user, profile): | |
206 """This trigger is used to check if we are waiting people in this room, | |
207 and to create a game if everybody is here""" | |
208 _room_jid = room.occupantJID.userhostJID() | |
209 if _room_jid in self.waiting_inv and len(room.roster) == 4: | |
210 #When we have 4 people in the room, we create the game | |
211 #TODO: check people identity | |
212 players = room.roster.keys() | |
213 del self.waiting_inv[_room_jid] | |
214 self.quizGameCreate(_room_jid.userhost(), players, profile_key=profile) | |
215 return True | |
216 | |
217 def quizGameLaunch(self, players, profile_key='@DEFAULT@'): | |
218 """Launch a game: helper method to create a room, invite players, and create the quiz game | |
219 @param players: list for players jid""" | |
220 debug(_('Launching quiz game')) | |
221 profile = self.host.memory.getProfileName(profile_key) | |
222 if not profile: | |
223 error(_("Unknown profile")) | |
224 return | |
225 | |
226 def quizRoomJoined(room): | |
227 _room = room.occupantJID.userhostJID() | |
228 for player in players: | |
229 self.host.plugins["XEP-0249"].invite(jid.JID(player), room.occupantJID.userhostJID(), {"game": "Quiz"}, profile) | |
230 self.waiting_inv[_room] = (time(), players) # TODO: remove invitation waiting for too long, using the time data | |
231 | |
232 def after_init(ignore): | |
233 room_name = "sat_quiz_%s" % self.host.plugins["XEP-0045"].getUniqueName(profile_key) | |
234 print "\n\n===> room_name:", room_name | |
235 muc_service = None | |
236 for service in self.host.memory.getServerServiceEntities("conference", "text", profile): | |
237 if not ".irc." in service.userhost(): | |
238 #FIXME: | |
239 #This awfull ugly hack is here to avoid an issue with openfire: the irc gateway | |
240 #use "conference/text" identity (instead of "conference/irc"), there is certainly a better way | |
241 #to manage this, but this hack fill do it for test purpose | |
242 muc_service = service | |
243 break | |
244 if not muc_service: | |
245 error(_("Can't find a MUC service")) | |
246 return | |
247 | |
248 _jid, xmlstream = self.host.getJidNStream(profile) | |
249 d = self.host.plugins["XEP-0045"].join(jid.JID("%s@%s" % (room_name, muc_service.userhost())), _jid.user, {}, profile).addCallback(quizRoomJoined) | |
250 | |
251 client = self.host.getClient(profile) | |
252 if not client: | |
253 error(_('No client for this profile key: %s') % profile_key) | |
254 return | |
255 client.client_initialized.addCallback(after_init) | |
256 | |
257 def quizGameCreate(self, room_jid_param, players, profile_key='@DEFAULT@'): | |
258 """Create a new game | |
259 @param room_jid_param: jid of the room | |
260 @param players: list of players nick (nick must exist in the room) | |
261 @param profile_key: %(doc_profile_key)s""" | |
262 debug(_("Creating Quiz game")) | |
263 room_jid = jid.JID(room_jid_param) | |
264 profile = self.host.memory.getProfileName(profile_key) | |
265 if not profile: | |
266 error(_("profile %s is unknown") % profile_key) | |
267 return | |
268 if room_jid in self.games: | |
269 warning(_("Quiz game already started in room %s") % room_jid.userhost()) | |
270 else: | |
271 room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile) | |
272 if not room_nick: | |
273 error('Internal error') | |
274 return | |
275 referee = room_jid.userhost() + '/' + room_nick | |
276 status = {} | |
277 players_data = {} | |
278 for player in players: | |
279 players_data[player] = {'score': 0} | |
280 status[player] = "init" | |
281 self.games[room_jid.userhost()] = {'referee': referee, 'players': players, 'status': status, 'players_data': players_data, 'stage': None} | |
282 for player in players: | |
283 mess = self.createGameElt(jid.JID(room_jid.userhost() + '/' + player)) | |
284 mess.firstChildElement().addChild(self.__create_started_elt(players)) | |
285 self.host.profiles[profile].xmlstream.send(mess) | |
286 | |
287 def newPlayerReady(self, player, referee, profile_key='@DEFAULT@'): | |
288 """Must be called when player is ready to start a new game""" | |
289 profile = self.host.memory.getProfileName(profile_key) | |
290 if not profile: | |
291 error(_("profile %s is unknown") % profile_key) | |
292 return | |
293 debug('new player ready: %s' % profile) | |
294 mess = self.createGameElt(jid.JID(referee)) | |
295 ready_elt = mess.firstChildElement().addElement('player_ready') | |
296 ready_elt['player'] = player | |
297 self.host.profiles[profile].xmlstream.send(mess) | 182 self.host.profiles[profile].xmlstream.send(mess) |
298 | 183 |
299 def playerAnswer(self, player, referee, answer, profile_key='@DEFAULT@'): | 184 def playerAnswer(self, player, referee, answer, profile_key='@DEFAULT@'): |
300 """Called when a player give an answer""" | 185 """Called when a player give an answer""" |
301 profile = self.host.memory.getProfileName(profile_key) | 186 profile = self.host.memory.getProfileName(profile_key) |
369 else: | 254 else: |
370 reactor.callLater(4, self.restartTimer, room_jid, profile) | 255 reactor.callLater(4, self.restartTimer, room_jid, profile) |
371 | 256 |
372 def newGame(self, room_jid, profile): | 257 def newGame(self, room_jid, profile): |
373 """Launch a new round""" | 258 """Launch a new round""" |
374 debug(_('new Quiz game')) | 259 common_data = {'game_score': 0} |
375 game_data = self.games[room_jid.userhost()] | |
376 players = game_data['players'] | |
377 players_data = game_data['players_data'] | |
378 game_data['stage'] = "init" | |
379 | |
380 for player in players: | |
381 players_data[player]['game_score'] = 0 | |
382 | |
383 new_game_data = {"instructions": _(u"""Bienvenue dans cette partie rapide de quizz, le premier à atteindre le score de 9 remporte le jeu | 260 new_game_data = {"instructions": _(u"""Bienvenue dans cette partie rapide de quizz, le premier à atteindre le score de 9 remporte le jeu |
384 | 261 |
385 Attention, tu es prêt ?""")} | 262 Attention, tu es prêt ?""")} |
386 | 263 msg_elts = self.__game_data_to_xml(new_game_data) |
387 mess = self.createGameElt(room_jid) | 264 RoomGame.newRound(self, room_jid, (common_data, msg_elts), profile) |
388 mess.firstChildElement().addChild(self.__game_data_to_xml(new_game_data)) | |
389 self.host.profiles[profile].xmlstream.send(mess) | |
390 reactor.callLater(10, self.askQuestion, room_jid, profile) | 265 reactor.callLater(10, self.askQuestion, room_jid, profile) |
391 | 266 |
392 def quiz_game_cmd(self, mess_elt, profile): | 267 def quiz_game_cmd(self, mess_elt, profile): |
393 from_jid = jid.JID(mess_elt['from']) | 268 from_jid = jid.JID(mess_elt['from']) |
394 room_jid = jid.JID(from_jid.userhost()) | 269 room_jid = jid.JID(from_jid.userhost()) |