~ubuntu-branches/ubuntu/precise/gnome-games/precise-proposed

« back to all changes in this revision

Viewing changes to glchess/src/lib/ggz/protocol.py

  • Committer: Package Import Robot
  • Author(s): Rodrigo Moya
  • Date: 2011-05-30 13:32:04 UTC
  • mfrom: (1.3.4)
  • mto: (163.1.3 precise)
  • mto: This revision was merged to the branch mainline in revision 143.
  • Revision ID: package-import@ubuntu.com-20110530133204-celaq1v1dsxc48q1
Tags: upstream-3.0.2
ImportĀ upstreamĀ versionĀ 3.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
import xml.sax.handler
3
 
 
4
 
"<UPDATE TYPE='player' ACTION='delete' ROOM='40' TOROOM='-1'>"
5
 
"<PLAYER ID='kostaya'/>"
6
 
"</UPDATE>"
7
 
 
8
 
"<UPDATE TYPE='table' ACTION='leave' ROOM='40'>"
9
 
"<TABLE ID='1' SEATS='2'>"
10
 
"<SEAT NUM='0' TYPE='player'>kostaya</SEAT>"
11
 
"</TABLE>"
12
 
"</UPDATE>"
13
 
 
14
 
"<UPDATE TYPE='table' ACTION='status' ROOM='40'>"
15
 
"<TABLE ID='1' STATUS='3' SEATS='2'/>"
16
 
"</UPDATE>"
17
 
 
18
 
"<UPDATE TYPE='table' ACTION='delete' ROOM='40'>"
19
 
"<TABLE ID='1' STATUS='-1' SEATS='2'/>"
20
 
"</UPDATE>"
21
 
 
22
 
class ParserFeedback:
23
 
 
24
 
    def onResult(self, action, code):
25
 
        pass
26
 
    
27
 
    def onMOTD(self, motd):
28
 
        pass
29
 
 
30
 
    def onChat(self, chatType, sender, text):
31
 
        pass
32
 
        
33
 
    def onJoin(self, tableId, isSpectator):
34
 
        pass
35
 
        
36
 
    def onLeave(self, reason):
37
 
        pass
38
 
        
39
 
    def gameAdded(self, gameId, name, version, author, url, numPlayers, protocol_engine, protocol_version):
40
 
        pass
41
 
 
42
 
    def roomAdded(self, roomId, gameId, name, description, nPlayers):
43
 
        pass
44
 
 
45
 
    def roomPlayersUpdate(self, roomId, nPlayers):
46
 
        pass
47
 
 
48
 
    def tableAdded(self, roomId, tableId, gameId, status, nSeats, description):
49
 
        pass
50
 
 
51
 
    def tableStatusChanged(self, tableId, status):
52
 
        pass
53
 
 
54
 
    def seatChanged(self, roomId, tableId, seatId, seatType, user):
55
 
        pass
56
 
 
57
 
    def tableRemoved(self, tableId):
58
 
        pass
59
 
 
60
 
    def onPlayerList(self, room, players):
61
 
        pass
62
 
 
63
 
    def playerAdded(self, name, playerType, tableId, perms, lag, room, fromRoom):
64
 
        pass
65
 
 
66
 
    def playerRemoved(self, name, room, toRoom):
67
 
        pass
68
 
 
69
 
class GGZParser:
70
 
    """
71
 
    """
72
 
    
73
 
    def __init__(self):
74
 
        self.parent = None
75
 
        self.parser = None
76
 
    
77
 
    def startElement(self, name, attributes):
78
 
        if self.parser is not None:
79
 
            self.parser.startElement(name, attributes)
80
 
            return
81
 
        try:
82
 
            method = getattr(self, 'start_%s' % name.lower())
83
 
        except AttributeError:
84
 
            print 'Unknown start element: %s' % name
85
 
        else:
86
 
            method(attributes)
87
 
 
88
 
    def characters(self, data):
89
 
        if self.parser is not None:
90
 
            self.parser.characters(data)
91
 
            return
92
 
        self.handle_data(data)
93
 
    
94
 
    def endElement(self, name):
95
 
        if self.parser is not None:
96
 
            self.parser.endElement(name)
97
 
            return
98
 
        try:
99
 
            method = getattr(self, 'end_%s' % name.lower())
100
 
        except AttributeError:
101
 
            print 'Unknown end element: %s' % name
102
 
        else:
103
 
            method()
104
 
            
105
 
    def push(self, parser, attributes):
106
 
        assert(self.parser is None)
107
 
        parser.attributes = attributes
108
 
        parser.decoder = self.decoder
109
 
        parser.parent = self
110
 
        self.parser = parser
111
 
        
112
 
    def pop(self):
113
 
        assert(self.parent is not None)
114
 
        parser = self.parent.parser
115
 
        self.parent.parser = None
116
 
        self.parent.childFinished(parser)
117
 
 
118
 
    def handle_data(self, data):
119
 
        pass
120
 
    
121
 
    def childFinished(self, parser):
122
 
        pass
123
 
    
124
 
class GameParser(GGZParser):
125
 
    """
126
 
    <GAME ID='24' NAME='TicTacToe' VERSION='0.0.9'>
127
 
    <PROTOCOL ENGINE='TicTacToe' VERSION='4'/>
128
 
    <ALLOW PLAYERS='2' BOTS='1' SPECTATORS='true' PEERS='false'/>
129
 
    <BOT NAME='Alfred' CLASS='easy'/>
130
 
    <BOT NAME='Tarantula' CLASS='hard'/>
131
 
    <ABOUT AUTHOR='Brent Hendricks' URL='http://www.ggzgamingzone.org/games/tictactoe/'/>
132
 
    <DESC>Simple GGZ game module for playing Tic-Tac-Toe</DESC>
133
 
    </GAME>
134
 
    """
135
 
    
136
 
    def __init__(self):
137
 
        GGZParser.__init__(self)
138
 
        self.bots = []
139
 
    
140
 
    def start_desc(self, attributes):
141
 
        self.push(DescriptionParser(), attributes)
142
 
        
143
 
    def start_protocol(self, attributes):
144
 
        self.push(GameProtocolParser(), attributes)
145
 
 
146
 
    def start_allow(self, attributes):
147
 
        self.push(GameAllowParser(), attributes)
148
 
        
149
 
    def start_bot(self, attributes):
150
 
        self.push(GameBotParser(), attributes)
151
 
    
152
 
    def start_about(self, attributes):
153
 
        self.push(GameAboutParser(), attributes)
154
 
 
155
 
    def end_game(self):
156
 
        self.gameId = self.attributes['ID']
157
 
        self.name = self.attributes['NAME']
158
 
        self.version = self.attributes['VERSION']
159
 
        self.pop()
160
 
 
161
 
    def __str__(self):
162
 
        return 'GGZ Game id=%s protocol=%s (%s) description=%s' % (self.gameId, repr(self.protocol.engine), self.protocol.version, repr(self.description))
163
 
    
164
 
class DescriptionParser(GGZParser):
165
 
    """   
166
 
    <DESC>Simple GGZ game module for playing Tic-Tac-Toe</DESC>
167
 
    """
168
 
 
169
 
    def handle_data(self, data):
170
 
        self.parent.description = data
171
 
        
172
 
    def end_desc(self):
173
 
        self.pop()
174
 
 
175
 
class GameProtocolParser(GGZParser):
176
 
    """
177
 
    <PROTOCOL ENGINE='TicTacToe' VERSION='4'/>
178
 
    """
179
 
    
180
 
    def end_protocol(self):
181
 
        self.parent.protocol = self
182
 
        self.engine = self.attributes['ENGINE']
183
 
        self.version = self.attributes['VERSION']
184
 
        self.pop()
185
 
 
186
 
class GameAllowParser(GGZParser):
187
 
    """
188
 
    <ALLOW PLAYERS='2' BOTS='1' SPECTATORS='true' PEERS='false'/>
189
 
    """
190
 
    
191
 
    def end_allow(self):
192
 
        self.parent.allow = self
193
 
        self.numPlayers = self.attributes['PLAYERS']
194
 
        self.pop()
195
 
 
196
 
class GameBotParser(GGZParser):
197
 
    """
198
 
    <BOT NAME='Alfred' CLASS='easy'/>
199
 
    <BOT NAME='Tarantula' CLASS='hard'/>
200
 
    """
201
 
    
202
 
    def end_bot(self):
203
 
        self.parent.bots.append(self)
204
 
        self.name = self.attributes['NAME']
205
 
        self.difficulty = self.attributes['CLASS']
206
 
        self.pop()
207
 
 
208
 
class GameAboutParser(GGZParser):
209
 
    """
210
 
    <ABOUT AUTHOR='Brent Hendricks' URL='http://www.ggzgamingzone.org/games/tictactoe/'/>
211
 
    """
212
 
 
213
 
    def end_about(self):
214
 
        self.parent.about = self
215
 
        self.author = self.attributes['AUTHOR']
216
 
        self.url = self.attributes['URL']
217
 
        self.pop()
218
 
 
219
 
class RoomParser(GGZParser):
220
 
    
221
 
    def start_desc(self, attributes):
222
 
        self.push(DescriptionParser(), attributes)
223
 
 
224
 
    def end_room(self):
225
 
        self.pop()
226
 
    
227
 
    def __str__(self):
228
 
        return 'GGZ Room id=%s game=%s description=%s' % (self.roomId, self.game, repr(self.description))
229
 
 
230
 
class PlayerParser(GGZParser):
231
 
 
232
 
    def end_player(self):
233
 
        self.pop()
234
 
        
235
 
    def __str__(self):
236
 
        return 'GGZ Player id=%s type=%s table=%s perms=%s lag=%s' % (self.id, self.type, self.table, self.perms, self.lag)
237
 
    
238
 
class TableSeatParser(GGZParser):
239
 
    
240
 
    def __init__(self):
241
 
        GGZParser.__init__(self)
242
 
        self.label = ''
243
 
 
244
 
    def handle_data(self, data):
245
 
        self.label += data
246
 
 
247
 
    def end_seat(self):
248
 
        self.pop()
249
 
 
250
 
class TableParser(GGZParser):
251
 
    
252
 
    def __init__(self):
253
 
        GGZParser.__init__(self)
254
 
        self.seats = []
255
 
        self.description = ''
256
 
 
257
 
    def start_desc(self, attributes):
258
 
        self.push(DescriptionParser(), attributes)
259
 
 
260
 
    def start_seat(self, attributes):
261
 
        self.push(TableSeatParser(), attributes)
262
 
 
263
 
    def childFinished(self, parser):
264
 
        if isinstance(parser, TableSeatParser):
265
 
            self.seats.append(parser)
266
 
 
267
 
    def end_table(self):
268
 
        self.pop()
269
 
 
270
 
class GameListParser(GGZParser):
271
 
    
272
 
    def __init__(self):
273
 
        GGZParser.__init__(self)
274
 
        self.games = []
275
 
    
276
 
    def start_game(self, attributes):
277
 
        self.push(GameParser(), attributes)
278
 
 
279
 
    def childFinished(self, parser):
280
 
        self.games.append(parser)
281
 
 
282
 
    def end_list(self):
283
 
        for g in self.games:
284
 
            self.decoder.feedback.gameAdded(g.gameId, g.name, g.version, g.about.author, g.about.url, g.allow.numPlayers,
285
 
                                              g.protocol.engine, g.protocol.version)
286
 
        self.pop()
287
 
      
288
 
class TableListParser(GGZParser):
289
 
    
290
 
    def __init__(self):
291
 
        GGZParser.__init__(self)
292
 
        self.tables = []
293
 
    
294
 
    def start_table(self, attributes):
295
 
        self.push(TableParser(), attributes)
296
 
 
297
 
    def childFinished(self, parser):
298
 
        self.tables.append(parser)
299
 
 
300
 
    def end_list(self):
301
 
        for t in self.tables:
302
 
            room = self.attributes['ROOM']
303
 
            tableId = t.attributes['ID']
304
 
            gameId = t.attributes['GAME']
305
 
            status = t.attributes['STATUS']
306
 
            nSeats = int(t.attributes['SEATS'])
307
 
            self.decoder.feedback.tableAdded(room, tableId, gameId, status, nSeats, t.description)
308
 
            for seat in t.seats:
309
 
                self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], seat.label)
310
 
        self.pop()
311
 
 
312
 
class PlayerListParser(GGZParser):
313
 
    
314
 
    def __init__(self):
315
 
        GGZParser.__init__(self)
316
 
        self.players = []
317
 
    
318
 
    def start_player(self, attributes):
319
 
        self.push(PlayerParser(), attributes)
320
 
 
321
 
    def childFinished(self, playerParser):
322
 
        playerParser.name = playerParser.attributes['ID']
323
 
        playerParser.type = playerParser.attributes['TYPE']
324
 
        playerParser.tableId = playerParser.attributes['TABLE']
325
 
        try:
326
 
            playerParser.perms = playerParser.attributes['PERMS']
327
 
        except KeyError:
328
 
            playerParser.perms = ''
329
 
        playerParser.lag = playerParser.attributes['LAG']
330
 
        self.players.append(playerParser)
331
 
 
332
 
    def end_list(self):
333
 
        self.decoder.feedback.onPlayerList(self.attributes['ROOM'], self.players)
334
 
        self.pop()
335
 
 
336
 
class RoomListParser(GGZParser):
337
 
    
338
 
    def __init__(self):
339
 
        GGZParser.__init__(self)
340
 
        self.rooms = []
341
 
        
342
 
    def start_room(self, attributes):
343
 
        self.push(RoomParser(), attributes)
344
 
 
345
 
    def childFinished(self, parser):
346
 
        parser.roomId = parser.attributes['ID']
347
 
        parser.name = parser.attributes['NAME']
348
 
        parser.game = parser.attributes['GAME']
349
 
        parser.nPlayers = int(parser.attributes['PLAYERS'])
350
 
        self.rooms.append(parser)
351
 
 
352
 
    def end_list(self):
353
 
        for r in self.rooms:
354
 
            self.decoder.feedback.roomAdded(r.roomId, r.game, r.name, r.description, r.nPlayers)
355
 
        self.pop()
356
 
        
357
 
class ServerOptionsParser(GGZParser):
358
 
 
359
 
    def end_options(self):
360
 
        self.pop()
361
 
        
362
 
class ServerParser(GGZParser):
363
 
    
364
 
    def start_options(self, attributes):
365
 
        self.push(ServerOptionsParser(), attributes)
366
 
    
367
 
    def end_server(self):
368
 
        self.decoder.feedback.onConnected()
369
 
        self.pop()
370
 
 
371
 
class MOTDParser(GGZParser):
372
 
    
373
 
    def __init__(self):
374
 
        GGZParser.__init__(self)
375
 
        self.motd = ''
376
 
    
377
 
    def handle_data(self, data):
378
 
        self.motd += data
379
 
    
380
 
    def end_motd(self):
381
 
        self.decoder.feedback.onMOTD(self.motd)
382
 
        self.pop()
383
 
 
384
 
class RoomUpdateParser(GGZParser):
385
 
    
386
 
    def start_room(self, attributes):
387
 
        self.push(RoomParser(), attributes)
388
 
        
389
 
    def childFinished(self, parser):
390
 
        action = self.attributes['ACTION'].lower()
391
 
        if action == 'players':
392
 
            roomId = parser.attributes['ID']
393
 
            nPlayers = int(parser.attributes['PLAYERS'])
394
 
            self.decoder.feedback.roomPlayersUpdate(roomId, nPlayers)
395
 
        else:
396
 
            print 'Unknown player update action %s' % action
397
 
    
398
 
    def end_update(self):
399
 
        self.pop()
400
 
 
401
 
class PlayerUpdateParser(GGZParser):
402
 
    
403
 
    def start_player(self, attributes):
404
 
        self.push(PlayerParser(), attributes)
405
 
 
406
 
    def childFinished(self, parser):
407
 
        action = self.attributes['ACTION'].lower()
408
 
        if action == 'add':
409
 
            name = parser.attributes['ID']
410
 
            playerType = parser.attributes['TYPE']
411
 
            table = parser.attributes['TABLE']
412
 
            try:
413
 
                perms = parser.attributes['PERMS']
414
 
            except KeyError:
415
 
                perms = ''
416
 
            lag = parser.attributes['LAG']
417
 
            roomId = self.attributes['ROOM']
418
 
            fromRoomId = self.attributes['FROMROOM']
419
 
            self.decoder.feedback.playerAdded(name, playerType, table, perms, lag, roomId, fromRoomId)
420
 
        elif action == 'lag':
421
 
            playerId = parser.attributes['ID']
422
 
            lag = parser.attributes['LAG']
423
 
            print 'Player %s lag changed to %s' % (playerId, lag)
424
 
        elif action == 'join':
425
 
            pass
426
 
        elif action == 'leave':
427
 
            pass
428
 
        elif action == 'desc':
429
 
            pass
430
 
        elif action == 'seat':
431
 
            pass
432
 
        elif action == 'delete':
433
 
            playerId = parser.attributes['ID']
434
 
            room = self.attributes['ROOM']
435
 
            toRoom = self.attributes['TOROOM']
436
 
            self.decoder.feedback.playerRemoved(playerId, room, toRoom)
437
 
        else:
438
 
            print 'Unknown player update action %s' % action
439
 
    
440
 
    def end_update(self):
441
 
        self.pop()
442
 
        
443
 
class TableUpdateParser(GGZParser):   
444
 
 
445
 
    def __init__(self):
446
 
        GGZParser.__init__(self)
447
 
        self.table = None
448
 
    
449
 
    def start_table(self, attributes):
450
 
        self.push(TableParser(), attributes)
451
 
        
452
 
    def childFinished(self, parser):
453
 
        self.table = parser
454
 
 
455
 
    def end_update(self):
456
 
        room = self.attributes['ROOM']        
457
 
        action = self.attributes['ACTION']
458
 
        if action == 'add':
459
 
             "<UPDATE TYPE='table' ACTION='add' ROOM='3'>"
460
 
             " <TABLE ID='1' GAME='30' STATUS='1' SEATS='2'>"
461
 
             "  <DESC></DESC>"
462
 
             "  <SEAT NUM='0' TYPE='reserved'>bob</SEAT>"
463
 
             "  <SEAT NUM='1' TYPE='bot'/>"
464
 
             " </TABLE>"
465
 
             "</UPDATE>"
466
 
             room = self.attributes['ROOM']
467
 
             tableId = self.table.attributes['ID']
468
 
             gameId = self.table.attributes['GAME']
469
 
             status = self.table.attributes['STATUS']
470
 
             nSeats = int(self.table.attributes['SEATS'])
471
 
             description = self.table.description
472
 
             # FIXME: Include the seats with the add event somehow (and other adds)
473
 
             self.decoder.feedback.tableAdded(room, tableId, gameId, status, nSeats, description)
474
 
             for seat in self.table.seats:
475
 
                 self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], seat.label)
476
 
 
477
 
        elif action == 'join':
478
 
            "<UPDATE TYPE='table' ACTION='join' ROOM='3'>"
479
 
            " <TABLE ID='1' SEATS='2'>"
480
 
            "  <SEAT NUM='0' TYPE='player'>bob</SEAT>"
481
 
            " </TABLE>"
482
 
            "</UPDATE>"
483
 
            room = self.attributes['ROOM']
484
 
            tableId = self.table.attributes['ID']
485
 
            for seat in self.table.seats:
486
 
                self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], seat.label)
487
 
 
488
 
        elif action == 'leave':
489
 
            "<UPDATE TYPE='table' ACTION='leave' ROOM='3'>"
490
 
            " <TABLE ID='1' SEATS='2'>"
491
 
            "  <SEAT NUM='0' TYPE='player'>bob</SEAT>"
492
 
            " </TABLE>"
493
 
            "</UPDATE>"
494
 
            room = self.attributes['ROOM']
495
 
            tableId = self.table.attributes['ID']
496
 
            for seat in self.table.seats:
497
 
                self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], '') # seat.label)???
498
 
 
499
 
        elif action == 'status':
500
 
            "<UPDATE TYPE='table' ACTION='status' ROOM='3'>"
501
 
            " <TABLE ID='1' STATUS='3' SEATS='2'/>"
502
 
            "</UPDATE>"
503
 
            self.decoder.feedback.tableStatusChanged(self.table.attributes['ID'], self.table.attributes['STATUS'])
504
 
 
505
 
        elif action == 'delete':
506
 
            "<UPDATE TYPE='table' ACTION='delete' ROOM='3'>"
507
 
            " <TABLE ID='1' STATUS='-1' SEATS='2'/>"
508
 
            "</UPDATE>"
509
 
            self.decoder.feedback.tableRemoved(self.table.attributes['ID'])
510
 
 
511
 
        else:
512
 
            print 'Unknown table update action: %s' % action
513
 
 
514
 
        self.pop()
515
 
    
516
 
    "<UPDATE TYPE='table' ACTION='add' ROOM='13'>"
517
 
    " <TABLE ID='1' GAME='24' STATUS='1' SEATS='4'>"
518
 
    "  <DESC>I play alone...</DESC>"
519
 
    "  <SEAT NUM='0' TYPE='reserved'>helg</SEAT>"
520
 
    "  <SEAT NUM='1' TYPE='bot'/>"
521
 
    "  <SEAT NUM='2' TYPE='bot'/>"
522
 
    "  <SEAT NUM='3' TYPE='bot'/>"
523
 
    " </TABLE>"
524
 
    "</UPDATE>"
525
 
    "<UPDATE TYPE='table' ACTION='join' ROOM='13'>"
526
 
    " <TABLE ID='1' SEATS='4'>"
527
 
    "  <SEAT NUM='0' TYPE='player'>helg</SEAT>"
528
 
    " </TABLE>"
529
 
    "</UPDATE>"
530
 
 
531
 
class ChatParser(GGZParser):
532
 
    
533
 
    def __init__(self):
534
 
        GGZParser.__init__(self)
535
 
        self.text = ''
536
 
    
537
 
    def handle_data(self, data):
538
 
        self.text += data
539
 
 
540
 
    def end_chat(self):
541
 
        chatType = self.attributes['TYPE']
542
 
        sender = self.attributes['FROM']
543
 
        self.decoder.feedback.onChat(chatType, sender, self.text)
544
 
        self.pop()
545
 
 
546
 
class ResultParser(GGZParser):
547
 
    
548
 
    def start_list(self, attributes):
549
 
        t = attributes['TYPE'].lower()
550
 
        if t == 'player':
551
 
            self.push(PlayerListParser(), attributes)
552
 
        elif t == 'room':
553
 
            self.push(RoomListParser(), attributes)
554
 
        elif t == 'game':
555
 
            self.push(GameListParser(), attributes)
556
 
        elif t == 'table':
557
 
            self.push(TableListParser(), attributes)
558
 
        else:
559
 
            print 'Unknown list: %s' % t
560
 
 
561
 
    def end_result(self):
562
 
        action = self.attributes['ACTION']
563
 
        code = self.attributes['CODE']
564
 
        self.decoder.feedback.onResult(action, code)
565
 
        self.pop()
566
 
        
567
 
class JoinParser(GGZParser):
568
 
    
569
 
    def end_join(self):
570
 
        tableId = self.attributes['TABLE']
571
 
        isSpectator = self.attributes['SPECTATOR'] == 'true'
572
 
        self.decoder.feedback.onJoin(tableId, isSpectator)
573
 
        self.pop()
574
 
 
575
 
class LeaveParser(GGZParser):
576
 
    "<LEAVE REASON='gameover'/>"
577
 
    
578
 
    def end_leave(self):
579
 
        reason = self.attributes['REASON']
580
 
        self.decoder.feedback.onLeave(reason)
581
 
        self.pop()
582
 
 
583
 
class SessionParser(GGZParser):
584
 
    
585
 
    def start_server(self, attributes):
586
 
        self.push(ServerParser(), attributes)
587
 
    
588
 
    def start_motd(self, attributes):
589
 
        self.push(MOTDParser(), attributes)
590
 
 
591
 
    def start_update(self, attributes):
592
 
        t = attributes['TYPE'].lower()
593
 
        if t == 'room':
594
 
            self.push(RoomUpdateParser(), attributes)
595
 
        elif t == 'player':
596
 
            self.push(PlayerUpdateParser(), attributes)
597
 
        elif t == 'table':
598
 
            self.push(TableUpdateParser(), attributes)
599
 
        else:
600
 
            print 'Unknown update type: %s' % t
601
 
            
602
 
    def start_join(self, attributes):
603
 
        self.push(JoinParser(), attributes)
604
 
        
605
 
    def start_leave(self, attributes):
606
 
        self.push(LeaveParser(), attributes)
607
 
 
608
 
    def start_result(self, attributes):
609
 
        self.push(ResultParser(), attributes)
610
 
        
611
 
    def start_chat(self, attributes):
612
 
        self.push(ChatParser(), attributes)
613
 
    
614
 
    def start_ping(self, attributes):
615
 
        self.decoder.feedback.send("<PONG/>\n")
616
 
        
617
 
    def end_ping(self):
618
 
        pass
619
 
 
620
 
    def end_session(self):
621
 
        self.decoder.feedback.onSessionEnded()
622
 
        pass
623
 
 
624
 
class BaseParser(GGZParser):
625
 
    
626
 
    def __init__(self, decoder):
627
 
        GGZParser.__init__(self)
628
 
        self.decoder = decoder
629
 
 
630
 
    def start_session(self, attributes):
631
 
        self.push(SessionParser(), attributes)
632
 
 
633
 
class Decoder(xml.sax.handler.ContentHandler):
634
 
 
635
 
    def __init__(self, feedback):
636
 
        xml.sax.handler.ContentHandler.__init__(self)
637
 
        self.feedback = feedback
638
 
        self.parser = None
639
 
        self.xparser = xml.sax.make_parser()
640
 
        self.handler = BaseParser(self)
641
 
        self.xparser.setContentHandler(self)
642
 
 
643
 
    def startElement(self, name, attributes):
644
 
        self.handler.startElement(name, attributes)
645
 
 
646
 
    def characters(self, data):
647
 
        self.handler.characters(data)
648
 
 
649
 
    def endElement(self, name):
650
 
        self.handler.endElement(name)
651
 
 
652
 
    def feed(self, data):
653
 
        """Feed data into the decoder.
654
 
        
655
 
        'data' is the raw data to feed.
656
 
        
657
 
        Returns the next block of data to process, keep feeding until '' is returned.
658
 
        """
659
 
        index = data.find('\n')
660
 
        if index < 0:
661
 
            index = len(data) - 1
662
 
 
663
 
        chunk = data[:index+1]
664
 
        try:
665
 
            self.xparser.feed(chunk)
666
 
        except xml.sax.SAXParseException:
667
 
            print 'Invalid XML: %s' % repr(chunk)
668
 
        return data[index+1:]
669
 
 
670
 
if __name__ == '__main__':
671
 
    import chess
672
 
    
673
 
    class F:
674
 
        
675
 
        def onSeat(self, seatNum, version):
676
 
            print ('onSeat', seatNum, version)
677
 
            
678
 
        def onPlayers(self, whiteType, whiteName, blackType, blackName):
679
 
            print ('onPlayers', whiteType, whiteName, blackType, blackName)
680
 
                
681
 
        def onTimeRequest(self):
682
 
            print ('onTimeRequest',)
683
 
    
684
 
        def onSetTime(self, time):
685
 
            print ('onSetTime', time)
686
 
 
687
 
        def onStart(self):
688
 
            print ('onStart',)
689
 
    
690
 
        def onMove(self, move):
691
 
            print ('onMove', move)    
692
 
 
693
 
    f = F()
694
 
    d = chess.Chess(f);
695
 
 
696
 
    data = '\x01\x01\x06' # Seat seat=1 version=6
697
 
    for c in data:
698
 
        d.decode(c)
699
 
        
700
 
    data = '\x02\x03\x00\x00\x00\x0eglchess-test2\x00\x03\x00\x00\x00\x0dglchess-test\x00' # players type1=03 name1=glchess-test2 type2=03 name2=glchess-test
701
 
    for c in data:
702
 
        d.decode(c)
703
 
 
704
 
    data = '\x04\x00\x00\x00\x00'  # rsp time time=0
705
 
    for c in data:
706
 
        d.decode(c)
707
 
 
708
 
    d.decode('\x05') # start
709
 
 
710
 
    data = '\x07\x00\x00\x00\x05F2F4\x00' # move move=F2F4
711
 
    for c in data:
712
 
        d.decode(c)
713
 
 
714
 
    data = '\x0a\x00\x00\x00\x00\x00\x00\x00\x00' # update
715
 
    for c in data:
716
 
        d.decode(c)