View difference between Paste ID: f7b3e99d6 and
SHOW: | | - or go back to the newest paste.
1-
1+
Index: debian/python-poker-network.links
2
===================================================================
3
--- debian/python-poker-network.links	(r�vision 6257)
4
+++ debian/python-poker-network.links	(copie de travail)
5
 -1,4 +1,5 @@
6
 usr/share/poker-network/schema.sql usr/share/dbconfig-common/data/python-poker-network/install/mysql
7
+usr/share/poker-network/1.7.5-2.0.0.sql usr/share/dbconfig-common/data/python-poker-network/upgrade/mysql/2.0.0
8
 usr/share/poker-network/1.7.4-1.7.5.sql usr/share/dbconfig-common/data/python-poker-network/upgrade/mysql/1.7.5
9
 usr/share/poker-network/1.7.3-1.7.4.sql usr/share/dbconfig-common/data/python-poker-network/upgrade/mysql/1.7.4
10
 usr/share/poker-network/1.6.0-1.7.0.sql usr/share/dbconfig-common/data/python-poker-network/upgrade/mysql/1.7.0
11
Index: pokernetwork/pokerpackets.py
12
===================================================================
13
--- pokernetwork/pokerpackets.py	(r�vision 6257)
14
+++ pokernetwork/pokerpackets.py	(copie de travail)
15
 -1732,6 +1732,7 @@
16
 
17
     format = "!I"
18
     format_size = calcsize(format)
19
+    TIME_BEFORE_YOU_CAN_REBUY_CODE = "1"
20
 
21
     def __init__(self, *args, **kwargs):
22
         self.amount = kwargs.get("amount",0)
23
 -1849,6 +1850,7 @@
24
    info = PacketPokerId.info + ( ('name', 'noname', 's'),
25
                                  ('outfit', 'random', 's'),
26
                                  ('url', 'random', 's'),
27
+                                  ('tables_max', -1, 'I'),
28
                                  # FIXME_PokerPlayerInfoLocale: 
29
                                  # (see also sr #2262 )
30
                                  # should "locale" be here?  It's
31
 -1863,20 +1865,22 @@
32
        self.name = kwargs.get('name', "noname")
33
        self.url = kwargs.get('url', "random")
34
        self.outfit = kwargs.get('outfit',"random")
35
+       self.tables_max = kwargs.get('tables_max',-1)
36
        PacketPokerId.__init__(self, *args, **kwargs)
37
 
38
    def pack(self):
39
-       return PacketPokerId.pack(self) + self.packstring(self.name) + self.packstring(self.outfit) + self.packstring(self.url)
40
+       return PacketPokerId.pack(self) + self.packstring(self.name) + self.packstring(self.outfit) + self.packstring(self.url) + pack(PacketPokerPlayerInfo.format, self.tables_max)
41
 
42
    def unpack(self, block):
43
        block = PacketPokerId.unpack(self, block)
44
        (block, self.name) = self.unpackstring(block)
45
        (block, self.outfit) = self.unpackstring(block)
46
        (block, self.url) = self.unpackstring(block)
47
-       return block
48
+       (self.tables_max,) = unpack(PacketPokerPlayerInfo.format, block[:PacketPokerPlayerInfo.format_size]) 
49
+       return block[PacketPokerPlayerInfo.format_size:]
50
 
51
    def calcsize(self):
52
-       return PacketPokerId.calcsize(self) + self.calcsizestring(self.name) + self.calcsizestring(self.outfit) + self.calcsizestring(self.url)
53
+       return PacketPokerId.calcsize(self) + self.calcsizestring(self.name) + self.calcsizestring(self.outfit) + self.calcsizestring(self.url) + PacketPokerPlayerInfo.format_size
54
 
55
    def __str__(self):
56
        return PacketPokerId.__str__(self) + " name = %s, url = %s, outfit = %s " % ( self.name , self.url, self.outfit )
57
Index: pokernetwork/pokerservice.py
58
===================================================================
59
--- pokernetwork/pokerservice.py	(r�vision 6257)
60
+++ pokernetwork/pokerservice.py	(copie de travail)
61
 -102,6 +102,7 @@
62
 UPDATE_TOURNEYS_SCHEDULE_DELAY = 10 * 60
63
 CHECK_TOURNEYS_SCHEDULE_DELAY = 60
64
 DELETE_OLD_TOURNEYS_DELAY = 1 * 60 * 60
65
+CLEANUP_SERIAL2LEAVETIME_DELAY = 1 * 60 * 60
66
 
67
 class IPokerService(Interface):
68
 
69
 -295,6 +296,7 @@
70
             self.createTable(0, description)
71
         self.cleanupTourneys()
72
         self.updateTourneysSchedule()
73
+        self.cleanupSerial2leavetimeTimer()
74
         self.messageCheck()
75
         self.poker_auth.SetLevel(PACKET_POKER_SEAT, User.REGULAR)
76
         self.poker_auth.SetLevel(PACKET_POKER_GET_USER_INFO, User.REGULAR)
77
 -304,6 +306,19 @@
78
         self.poker_auth.SetLevel(PACKET_POKER_HAND_SELECT_ALL, User.ADMIN)
79
         service.Service.startService(self)
80
         self.down = False
81
+        
82
+    
83
+    def cleanupSerial2leavetimeTimer(self):
84
+        for table in self.tables.values():
85
+                serialsToDelete = {}
86
+                for (player_serial , leavetime ) in table.serial2leavetime.iteritems():
87
+                    if (time.time() - leavetime[0]) > table.timeBeforeYouCanRebuyMin :
88
+                        serialsToDelete[player_serial] = player_serial;                               
89
+                for serial in serialsToDelete:
90
+                    del table.serial2leavetime[serial]
91
+                                                               
92
+        self.timer['cleanupSerial2leavetimeTimer'] = reactor.callLater(CLEANUP_SERIAL2LEAVETIME_DELAY, self.cleanupSerial2leavetimeTimer)
93
+                                
94
 
95
     def message(self, string):
96
         print "PokerService: " + str(string)
97
 -449,6 +464,7 @@
98
 
99
     def shutdown(self):
100
         self.shutting_down = True
101
+        self.cancelTimer('cleanupSerial2leavetimeTimer')
102
         self.cancelTimer('checkTourney')
103
         self.cancelTimer('updateTourney')
104
         self.cancelTimer('messages')
105
 -1905,6 +1921,7 @@
106
                                             name = "anonymous",
107
                                             url= "random",
108
                                             outfit = "random",
109
+                                            tables_max = -1,
110
                                             # FIXME_PokerPlayerInfoLocale:
111
                                             # (see also sr #2262 )
112
                                             # this sets locale but
113
 -1920,19 +1937,20 @@
114
             return placeholder
115
 
116
         cursor = self.db.cursor()
117
-        sql = ( "select locale,name,skin_url,skin_outfit from users where serial = " + str(serial) )
118
+        sql = ( "select locale,name,skin_url,skin_outfit,tables_max from users where serial = " + str(serial) )
119
         cursor.execute(sql)
120
         if cursor.rowcount != 1:
121
             self.error("getPlayerInfo(%d) expected one row got %d" % ( serial, cursor.rowcount ))
122
             return placeholder
123
-        (locale,name,skin_url,skin_outfit) = cursor.fetchone()
124
+        (locale,name,skin_url,skin_outfit,tables_max) = cursor.fetchone()
125
         if skin_outfit == None:
126
             skin_outfit = "random"
127
         cursor.close()
128
         packet = PacketPokerPlayerInfo(serial = serial,
129
                                        name = name,
130
                                        url = skin_url,
131
-                                       outfit = skin_outfit)
132
+                                       outfit = skin_outfit,
133
+                                       tables_max = tables_max)
134
         # pokerservice generally provides playerInfo() internally to
135
         # methods like pokeravatar.(re)?login.  Since this is the central
136
         # internal location where the query occurs, we hack in the locale
137
Index: pokernetwork/pokeravatar.py
138
===================================================================
139
--- pokernetwork/pokeravatar.py	(r�vision 6257)
140
+++ pokernetwork/pokeravatar.py	(copie de travail)
141
 -131,6 +131,7 @@
142
         self.user.privilege = User.REGULAR
143
         self.user.url = player_info.url
144
         self.user.outfit = player_info.outfit
145
+        self.user.tablesMax = player_info.tables_max
146
         self._setDefaultLocale(player_info.locale)
147
 
148
         if self.explain:
149
 -140,10 +141,11 @@
150
         self.loginTableUpdates(serial)
151
     
152
     def login(self, info):
153
-        (serial, name, privilege) = info
154
+        (serial, name, privilege, tables_max) = info
155
         self.user.serial = serial
156
         self.user.name = name
157
         self.user.privilege = privilege
158
+        self.user.tablesMax = tables_max
159
 
160
         player_info = self.service.getPlayerInfo(serial)
161
         self.user.url = player_info.url
162
 -224,6 +226,9 @@
163
     def getName(self):
164
         return self.user.name
165
 
166
+    def getTablesMax(self):
167
+        return self.user.tablesMax
168
+
169
     def getUrl(self):
170
         return self.user.url
171
 
172
 -1061,7 +1066,8 @@
173
             return PacketPokerPlayerInfo(serial = self.getSerial(),
174
                                          name = self.getName(),
175
                                          url = self.user.url,
176
-                                         outfit = self.user.outfit)
177
+                                         outfit = self.user.outfit,
178
+                                         tables_max = self.user.tablesMax)
179
         else:
180
             return PacketError(code = PacketPokerGetPlayerInfo.NOT_LOGGED,
181
                                message = "Not logged in",
182
Index: pokernetwork/pokertable.py
183
===================================================================
184
--- pokernetwork/pokertable.py	(r�vision 6257)
185
+++ pokernetwork/pokertable.py	(copie de travail)
186
 -35,6 +35,7 @@
187
 from types import *
188
 from string import split, join
189
 import time
190
+import datetime
191
 import traceback
192
 
193
 from pokerengine.pokergame import PokerGameServer, history2messages
194
 -132,6 +133,14 @@
195
         self.cache = self.createCache()
196
         self.owner = 0
197
         self.avatar_collection = PokerAvatarCollection("Table%d" % id, factory.verbose)
198
+        self.timeBeforeYouCanRebuyMinProps = settings.headerGetProperties("/server/time-before-you-can-rebuy-min")
199
+        self.isTimeBeforeYouCanRebuyMin= False                 
200
+        if len(self.timeBeforeYouCanRebuyMinProps) != 0:
201
+            if self.timeBeforeYouCanRebuyMinProps[0].get("activate") == "yes":
202
+                self.isTimeBeforeYouCanRebuyMin= True
203
+                self.timeBeforeYouCanRebuyMin = int (self.timeBeforeYouCanRebuyMinProps[0].get("period", 1800))
204
+            
205
+        self.serial2leavetime = {} # key : serial ; value : [ time , money ]
206
         self.timer_info = {
207
             "playerTimeout": None,
208
             "playerTimeoutSerial": 0,
209
 -973,6 +982,9 @@
210
             #
211
             # If not on a closed table, stand up
212
             #
213
+            if(not self.game.isTournament() and self.isTimeBeforeYouCanRebuyMin and (self.game.minMoney() < self.game.serial2player[serial].money)):
214
+                self.serial2leavetime[serial] = [ time.time() , self.game.serial2player[serial].money ]       
215
+                      
216
             if self.isOpen():
217
                 if avatar.removePlayer(self, serial):
218
                     self.seated2observer(avatar)
219
 -1193,12 +1205,25 @@
220
             return False
221
 
222
         # Next, test to see if joining this table will cause the avatar to
223
-        # exceed the maximum permitted by the server.
224
-        if len(avatar.tables) >= self.factory.simultaneous:
225
+        # exceed the maximum permitted by the server 
226
+        clientTablesLen = len(avatar.tables)
227
+        if clientTablesLen >= self.factory.simultaneous:        
228
             if self.factory.verbose:
229
                 self.error("joinPlayer: %d seated at %d tables (max %d)" % ( serial, len(avatar.tables), self.factory.simultaneous ))
230
+            avatar.sendPacketVerbose(PacketPokerError(message = "You have reached the maximum number of tables available by the server (%d)" % (self.factory.simultaneous ),
231
+                                                      code=100 ))                                
232
             return False
233
+         
234
+        # Next, test to see if joining this table will cause the avatar to
235
+        # exceed the maximum permitted by the maximum specified for him
236
+        if avatar.getTablesMax() != -1 and clientTablesLen >= avatar.getTablesMax():       
237
+            if self.factory.verbose:
238
+                self.error("joinPlayer: %d seated at %d tables (specific user max %d)" % ( serial, len(avatar.tables), avatar.getTablesMax()))                                         
239
+            avatar.sendPacketVerbose(PacketPokerError(message = "You have reached the maximum number of tables available with your access (%d)" % (avatar.getTablesMax() ),
240
+                                                      code=101 ))                                                                        
241
+            return False
242
 
243
+
244
         #
245
         # Player is now an observer, unless he is seated
246
         # at the table.
247
 -1335,6 +1360,17 @@
248
             self.error("player %d already payed the buy-in" % avatar.getSerial())
249
             return False
250
 
251
+        if self.isTimeBeforeYouCanRebuyMin and self.serial2leavetime.has_key(avatar.getSerial()):     
252
+            diff = int (time.time() - self.serial2leavetime[avatar.getSerial()][0])
253
+            if (  diff  < self.timeBeforeYouCanRebuyMin  ) and self.serial2leavetime[avatar.getSerial()][1] > amount :
254
+                rest = self.timeBeforeYouCanRebuyMin - diff
255
+                self.error("player %d can't for the next %d secondes buyin less than %d " % (avatar.getSerial(), rest, self.serial2leavetime[avatar.getSerial()][1] ) )
256
+                avatar.sendPacketVerbose(PacketPokerError(message = "You can't for the next %d secondes buyin less than %d " % (rest, self.serial2leavetime[avatar.getSerial()][1] ),
257
+                                                          code=102 ))              
258
+                return False
259
+            else:
260
+                del self.serial2leavetime[avatar.getSerial()]
261
+                 
262
         amount = self.factory.buyInPlayer(avatar.getSerial(), game.id, self.currency_serial, max(amount, game.buyIn()))
263
         return avatar.setMoney(self, amount)
264
         
265
Index: pokernetwork/pokerauth.py
266
===================================================================
267
--- pokernetwork/pokerauth.py	(r�vision 6257)
268
+++ pokernetwork/pokerauth.py	(copie de travail)
269
 -52,11 +52,12 @@
270
 
271
     def auth(self, name, password):
272
         cursor = self.db.cursor()
273
-        cursor.execute("SELECT serial, password, privilege FROM users "
274
+        cursor.execute("SELECT serial, password, privilege, tables_max FROM users "
275
                        "WHERE name = '%s'" % name)
276
         numrows = int(cursor.rowcount)
277
         serial = 0
278
         privilege = User.REGULAR
279
+        tables_max = -1
280
         if numrows <= 0:
281
             if self.auto_create_account:
282
                 if self.verbose > 1:
283
 -73,13 +74,13 @@
284
             cursor.close()
285
             return ( False, "Invalid login or password" )
286
         else:
287
-            (serial, password_sql, privilege) = cursor.fetchone()
288
+            (serial, password_sql, privilege, tables_max) = cursor.fetchone()
289
             cursor.close()
290
             if password_sql != password:
291
                 self.message("password mismatch for %s" % name)
292
                 return ( False, "Invalid login or password" )
293
 
294
-        return ( (serial, name, privilege), None )
295
+        return ( (serial, name, privilege, tables_max), None )
296
 
297
     def userCreate(self, name, password):
298
         if self.verbose:
299
Index: pokernetwork/user.py
300
===================================================================
301
--- pokernetwork/user.py	(r�vision 6257)
302
+++ pokernetwork/user.py	(copie de travail)
303
 -73,6 +73,7 @@
304
         self.url = "random"
305
         self.outfit = "random"
306
         self.privilege = None
307
+        self.tablesMax = -1
308
 
309
     def logout(self):
310
         self.serial = 0
311
 -80,6 +81,7 @@
312
         self.url = "random"
313
         self.outfit = "random"
314
         self.privilege = None
315
+        self.tablesMax = -1
316
         
317
     def isLogged(self):
318
         return not self.serial == 0
319
Index: tests/test-pokeravatar.py.in
320
===================================================================
321
--- tests/test-pokeravatar.py.in	(r�vision 6257)
322
+++ tests/test-pokeravatar.py.in	(copie de travail)
323
 -1170,7 +1170,7 @@
324
     def playerInfoUnpriv(self, (client, packet)):
325
         return self.pingThenExpectPrivilegeFailure((client, packet), 
326
             PacketPokerPlayerInfo(serial= client.getSerial(), name = "The Naked Guy",
327
-                                  outfit = "Naked", url = "http://example.org"))
328
+                                  outfit = "Naked", url = "http://example.org", tables_max = -1))
329
     # -------------------------------------------------------------------------
330
     def test17_4_tourneyTourneyRegisterUnpriv(self):
331
         self.createClients(1)
332
 -1206,7 +1206,7 @@
333
                               'packet': 
334
                               PacketPokerPlayerInfo(serial = someoneElseSerial,
335
                                       name = "YOU_BEEN_CRACKED",
336
-                                      url = "http://example.com/myhack", outfit = "Naked") },
337
+                                      url = "http://example.com/myhack", outfit = "Naked", tables_max = -1) },
338
             'player_image' : { 'output' :
339
                                "%sattempt to set player image%s" \
340
                                    % (messageStart, forPlayerByPlayer),
341
 -1789,7 +1789,8 @@
342
         avatar.handlePacketLogic(PacketPokerPlayerInfo(serial= client.getSerial(),
343
                                                        name = "The Naked Guy",
344
                                                        outfit = "Naked",
345
-                                                       url = "http://example.org"))
346
+                                                       url = "http://example.org",
347
+                                                       tables_max = -1))
348
         found = False
349
         for packet in avatar.resetPacketsQueue():
350
             if packet.type == PACKET_POKER_PLAYER_INFO:
351
 -1821,7 +1822,8 @@
352
         avatar.handlePacketLogic(PacketPokerPlayerInfo(serial= client.getSerial(),
353
                                                        name = "The Naked Guy",
354
                                                        outfit = "Naked",
355
-                                                       url = "http://example.org"))
356
+                                                       url = "http://example.org",
357
+                                                       tables_max = -1))
358
         found = False
359
         for packet in avatar.resetPacketsQueue():
360
             if packet.type == PACKET_ERROR:
361
 -2240,7 +2242,7 @@
362
         avatar0 = self.service.avatars[0]
363
         avatar0.logout()
364
         table.observers.append(avatar0)
365
-        avatar0.login((4, "user0", 32767))
366
+        avatar0.login((4, "user0", 32767, -1))
367
         avatar0.queuePackets()
368
         count = 0
369
         for packet in avatar0.resetPacketsQueue():
370
 -2295,7 +2297,7 @@
371
         avatar0 = self.service.avatars[0]
372
         avatar0.logout()
373
         table.observers.append(avatar0)
374
-        avatar0.login((4, "user0", 32767))
375
+        avatar0.login((4, "user0", 32767,-1))
376
         avatar0.queuePackets()
377
         count = 0
378
         for packet in avatar0.resetPacketsQueue():
379
 -4036,6 +4038,7 @@
380
             mpiSelf.outfit = "naked"
381
             mpiSelf.locale = 'mylocale'
382
             mpiSelf.name = 'Doyle Brunson'
383
+            mpiSelf.tables_max = -1
384
     class MockService:
385
         def __init__(msSelf):
386
             msSelf.verbose = 6
387
Index: tests/test-pokerclient.py.in
388
===================================================================
389
--- tests/test-pokerclient.py.in	(r�vision 6257)
390
+++ tests/test-pokerclient.py.in	(copie de travail)
391
 -1097,7 +1097,8 @@
392
         client.handlePlayerInfo(PacketPokerPlayerInfo(name = "test",
393
                                                   url = "http://thatisone/",
394
                                                   outfit = "Stablize",
395
-                                                  serial = client.getSerial()))
396
+                                                  serial = client.getSerial(),
397
+                                                  tables_max = -1))
398
         if forceCrash:
399
             self.assertEquals(get_messages(), 
400
                               ['ERROR *CRITICAL*: PACKET_POKER_PLAYER_INFO: may enter loop packet.url = http://thatisone/\n url = http://thatistwo\n url_check = http://thatisthree\npacket.outfit = Stablize\n outfit = Stablize\n outfit_check = Stablize'])
401
 -1141,7 +1142,8 @@
402
         client.handlePlayerInfo(PacketPokerPlayerInfo(name = "test",
403
                                                   url = "http://stable/",
404
                                                   outfit = "OutfitOne",
405
-                                                  serial = client.getSerial()))
406
+                                                  serial = client.getSerial(),
407
+                                                  tables_max = -1))
408
         if forceCrash:
409
             self.assertEquals(get_messages(), 
410
                               ['ERROR *CRITICAL*: PACKET_POKER_PLAYER_INFO: may enter loop packet.url = http://stable/\n url = http://stable/\n url_check = http://stable/\npacket.outfit = OutfitOne\n outfit = OutfitTwo\n outfit_check = OutfitThree'])
411
Index: tests/conf/poker.server.xml.in
412
===================================================================
413
--- tests/conf/poker.server.xml.in	(r�vision 6257)
414
+++ tests/conf/poker.server.xml.in	(copie de travail)
415
 -8,6 +8,8 @@
416
 	chat="yes" >
417
 
418
   <delays autodeal="3" round="2" position="1" showdown="5" finish="3" />
419
+    <!-- remaining buy-in -->
420
+  <remaining-buy-in activate="yes" period="1800" />
421
   
422
   <table name="One"	variant="holdem" betting_structure="2-4-limit" seats="10" timeout="60" custom_money="0" />
423
   <table name="Two"	variant="holdem" betting_structure="10-15-limit" seats="10" timeout="60" custom_money="0" />
424
Index: tests/test-pokertable.py.in
425
===================================================================
426
--- tests/test-pokertable.py.in	(r�vision 6257)
427
+++ tests/test-pokertable.py.in	(copie de travail)
428
 -62,6 +62,8 @@
429
 <server verbose="4" autodeal="yes" max_missed_round="5">
430
   <delays autodeal_tournament_min="2" autodeal="2" autodeal_max="2" autodeal_check="0" round="0" position="0" showdown="0" finish="0" />
431
 
432
+  <time-before-you-can-rebuy-min activate="yes" period="1" /> 
433
+  
434
   <path>@POKER_ENGINE_PKGSYSCONFDIR@ @POKER_NETWORK_PKGSYSCONFDIR@</path>
435
   <users temporary="BOT"/>
436
 </server>
437
 -70,6 +72,8 @@
438
 <server verbose="4" autodeal="no" >
439
   <delays autodeal_tournament_min="2" autodeal="2" autodeal_max="2" autodeal_check="0" round="0" position="0" showdown="0" finish="0" />
440
 
441
+  <time-before-you-can-rebuy-min activate="yes" period="1" /> 
442
+  
443
   <decks>
444
     <deck>9c 9d 9h Ts Tc Td Th Ts Jc Jd Jh Js Qc Qd Qh Qs Kc Kd Kh Ks Ac Ad Ah As</deck>
445
   </decks>
446
 -152,6 +156,9 @@
447
         self.joined_max = 1000
448
         self.chat_messages = []
449
 
450
+    def setSimultaneous(self, tables_max):
451
+        self.simultaneous = tables_max
452
+        
453
     def getMissedRoundMax(self):
454
         return 5  # if you change this, change it in settings_xml above
455
 
456
 -330,6 +337,7 @@
457
         self.user = MockClient.User()
458
         self.testObject = testObject
459
         self.reasonExpected = expectedReason
460
+        self.tables_max = -1
461
 
462
     def __str__(self):
463
         return "MockClient of Player%d" % self.serial
464
 -414,7 +422,15 @@
465
                 self.name = self.player.getName()
466
                 self.url = "http://fake"
467
                 self.outfit = None
468
+                self.tables_max = -1
469
         return MockPlayerInfo(self)
470
+                
471
+    def getTablesMax(self):
472
+        return self.tables_max   
473
+        
474
+    def setTablesMax(self, table_max):
475
+        self.tables_max = table_max        
476
+             
477
 
478
 if verbose < 0: redirect_messages(MockClient)
479
 
480
 -654,9 +670,18 @@
481
 
482
         self.assertEqual(True, self.table.rebuyPlayerRequest(player[5], \
483
                                               self.table.game.maxBuyIn()))
484
-        # finally, player5 tries to join table 2, which isn't permitted since
485
+        # now, player5 tries to join table 2, which isn't permitted since
486
         # we've set MockService.simultaneous to 1
487
         self.assertEqual(False, self.table2.joinPlayer(player[5], 5))
488
+        
489
+        # finally, apply simultaneous = 2, player5 tries to join table 2, which isn't permitted since
490
+        # we've set tablesMax for specific user to 1       
491
+        self.service.setSimultaneous(2) 
492
+        player[5].setTablesMax(1)
493
+        self.assertEqual(False, self.table2.joinPlayer(player[5], 5))  
494
+        player[5].setTablesMax(2)   
495
+        self.assertEqual(True, self.table2.joinPlayer(player[5], 5))    
496
+        
497
     # -------------------------------------------------------------------
498
     def test08_2_brokenSeatFactory(self):
499
         player = self.createPlayer(1, False)
500
 -1427,6 +1452,18 @@
501
         self.tableSave = self.table
502
 
503
         return deferredMustBeCalledBackForSuccess
504
+    # -------------------------------------------------------------------    
505
+    def test47_timeBeforeYouCanRebuyMin(self):
506
+        # note : createPlayer apply maxBuyIn
507
+        p = self.createPlayer(1)
508
+        self.table.quitPlayer(p, 1)
509
+        self.table.joinPlayer(p, p.serial)
510
+        self.table.seatPlayer(p, p.serial, -1)
511
+        if self.table.game.isTournament() == False:
512
+            self.assertEqual(False,self.table.buyInPlayer(p, self.table.game.minMoney()))
513
+            time.sleep(2)
514
+            self.assertEqual(True,self.table.buyInPlayer(p, self.table.game.minMoney()))
515
+                    
516
 # -------------------------------------------------------------------
517
 
518
 # I seriously considered not having *all* the same tests run with
519
 -1846,6 +1883,11 @@
520
         """SKIP THIS TEST IN THIS SUBCLASS
521
         """
522
         return True
523
+    # -------------------------------------------------------------------    
524
+    def test47_timeBeforeYouCanRebuyMin(self):
525
+        """SKIP THIS TEST IN THIS SUBCLASS
526
+        """
527
+        return True          
528
 # --------------------------------------------------------------------------------
529
 class MockServiceWithUserStats(MockService):
530
     def __init__(self, settings):
531
Index: tests/test-pokerservice.py.in
532
===================================================================
533
--- tests/test-pokerservice.py.in	(r�vision 6257)
534
+++ tests/test-pokerservice.py.in	(copie de travail)
535
 -221,9 +221,9 @@
536
             cursor.execute("INSERT INTO users (name, password, created) VALUES ('user%d', 'password%d', 0)" % ( user_number, user_number ))
537
             self.assertEqual(1, cursor.rowcount)
538
 
539
-        ( (self.user1_serial, name, privilege), message ) = self.service.auth("user1", "password1", "role1")
540
-        ( (self.user2_serial, name, privilege), message ) = self.service.auth("user2", "password2", "role1")
541
-        ( (self.user3_serial, name, privilege), message ) = self.service.auth("user3", "password3", "role1")
542
+        ( (self.user1_serial, name, privilege, tables_max), message ) = self.service.auth("user1", "password1", "role1")
543
+        ( (self.user2_serial, name, privilege, tables_max), message ) = self.service.auth("user2", "password2", "role1")
544
+        ( (self.user3_serial, name, privilege, tables_max), message ) = self.service.auth("user3", "password3", "role1")
545
 
546
         for user_number in (self.user1_serial, self.user2_serial, self.user3_serial):
547
             if self.default_money > 0 and user_number == self.user3_serial:
548
 -1321,7 +1321,7 @@
549
     # ----------------------------------------------------------------
550
     def test01_auth(self):
551
         self.service.startService()
552
-        ( (serial, name, privilege), message ) = self.service.auth("user1", "password1", "role1")
553
+        ( (serial, name, privilege, tables_max), message ) = self.service.auth("user1", "password1", "role1")
554
         self.assertEquals(None, message)
555
         self.assertEquals(4, serial)
556
         self.assertEquals("user1", name)
557
 -1344,9 +1344,9 @@
558
                 return "user1"
559
 
560
         self.service.startService()
561
-        ( (serial, name, privilege), message ) = self.service.auth("user1", "password1", sets.Set('role1'))
562
+        ( (serial, name, privilege, tables_max), message ) = self.service.auth("user1", "password1", sets.Set('role1'))
563
         self.service.avatar_collection.add(serial, Client())
564
-        ( (serial, name, privilege), message ) = self.service.auth("user1", "password1", sets.Set('role1'))
565
+        ( (serial, name, privilege, tables_max), message ) = self.service.auth("user1", "password1", sets.Set('role1'))
566
         self.assertEquals(None, message)
567
         self.assertEquals("user1", name)
568
 
569
 -1984,7 +1984,7 @@
570
     def test_refill(self):
571
         self.service.startService()
572
         refill = 10000
573
-        ( (serial, name, privilege), message ) = self.service.auth("user1", "password1", "role1")
574
+        ( (serial, name, privilege, tables_max), message ) = self.service.auth("user1", "password1", "role1")
575
         self.assertEquals(0, self.service.autorefill(serial))
576
         table_money = 1000
577
         table_serial = 200
578
 -4497,7 +4497,7 @@
579
                         found = True
580
                         break
581
                 cursorSelf.rowcount = 1
582
-                cursorSelf.row = ('ourlocal','ourname','ourskinurl',None)
583
+                cursorSelf.row = ('ourlocal','ourname','ourskinurl',None,-1)
584
                 self.failUnless(found)
585
                 return cursorSelf.rowcount
586
             def fetchone(cursorSelf): return cursorSelf.row
587
 -4519,6 +4519,7 @@
588
         self.assertEquals(pack.name, 'ourname')
589
         self.assertEquals(pack.url, 'ourskinurl')
590
         self.assertEquals(pack.outfit, 'random')
591
+        self.assertEquals(pack.tables_max, -1)
592
 
593
         self.service.db = oldDb
594
     # ----------------------------------------------------------------
595
 -5324,6 +5325,7 @@
596
         self.assertEquals(packet.name, "anonymous")
597
         self.assertEquals(packet.url, "random")
598
         self.assertEquals(packet.outfit, "random")
599
+        self.assertEquals(packet.tables_max, -1)
600
         # FIXME_PokerPlayerInfoLocale: (see also sr #2262 )
601
         # PokerService.getPlayerInfo() sends locale argument when creating
602
         # the PokerPlayerInfo() packet, but that argument is not used.
603
 -5339,7 +5341,7 @@
604
                 self.failUnless(sql.find("serial = 235") > 0, "serial wrong")
605
             def __init__(cursorSelf):
606
                 MockCursorBase.__init__(cursorSelf, self, 
607
-                                      ["select locale,name,skin_url,skin_outfit from users"])
608
+                                      ["select locale,name,skin_url,skin_outfit,tables_max from users"])
609
         self.service = pokerservice.PokerService(self.settings)
610
 
611
         oldDb = self.service.db
612
 -5354,6 +5356,7 @@
613
         self.assertEquals(packet.name, "anonymous")
614
         self.assertEquals(packet.url, "random")
615
         self.assertEquals(packet.outfit, "random")
616
+        self.assertEquals(packet.tables_max, -1)
617
         # FIXME_PokerPlayerInfoLocale: (see also sr #2262 )
618
         # PokerService.getPlayerInfo() sends locale argument when creating
619
         # the PokerPlayerInfo() packet, but that argument is not used.
620
Index: tests/poker.server.xml
621
===================================================================
622
--- tests/poker.server.xml	(r�vision 6257)
623
+++ tests/poker.server.xml	(copie de travail)
624
 -6,6 +6,8 @@
625
     verbose="3"
626
     chat="yes" >
627
 
628
+  <time-before-you-can-rebuy-min activate="yes" period="1800" />
629
+
630
   <delays autodeal="3" round="2" position="1" showdown="7" finish="3" />
631
   
632
   <table name="Fourty"	variant="7stud" betting_structure="ante-5-10-limit" seats="8" player_timeout="60" custom_money="0" />
633
Index: tests/test-tourneytablebalance.py.in
634
===================================================================
635
--- tests/test-tourneytablebalance.py.in	(r�vision 6257)
636
+++ tests/test-tourneytablebalance.py.in	(copie de travail)
637
 -121,6 +121,7 @@
638
                 miSelf.name =  "PLAYER INFO: %d" % self.serial
639
                 miSelf.url  = "http://example.org"
640
                 miSelf.outfit  = "naked"
641
+                miSelf.tables_max = -1
642
         return MockInfo()
643
 
644
     def sendPacket(self, packet):
645
Index: tests/test-pokerauth.py.in
646
===================================================================
647
--- tests/test-pokerauth.py.in	(r�vision 6257)
648
+++ tests/test-pokerauth.py.in	(copie de travail)
649
 -149,7 +149,7 @@
650
         auth = pokerauth.get_auth_instance(db, settings)
651
 
652
         clear_all_messages()
653
-        self.assertEquals(auth.auth('joe_schmoe', 'foo'), ((4, 'joe_schmoe', 1), None))
654
+        self.assertEquals(auth.auth('joe_schmoe', 'foo'), ((4, 'joe_schmoe', 1, -1), None))
655
         self.assertEquals(get_messages(), ['user joe_schmoe does not exist, create it',
656
                                        'creating user joe_schmoe', 'create user with serial 4'])
657
         self.failUnless(len(self.checkIfUserExistsInDB('joe_schmoe')) == 1)
658
 -174,6 +174,7 @@
659
         cursor.execute("""CREATE TABLE users (
660
  	    serial int unsigned not null auto_increment,
661
 	    name varchar(32), password varchar(32), privilege int default 1,
662
+	    tables_max int default -1,	    
663
             primary key (serial))""")
664
         for ii in [ 1 , 2 ]:
665
             cursor.execute("INSERT INTO users (name, password) values ('%s', '%s')" %
666
 -198,7 +199,7 @@
667
         auth = pokerauth.get_auth_instance(self.db, self.settings)
668
 
669
         clear_all_messages()
670
-        self.assertEquals(auth.auth('dan_harrington', 'bar'), ((4L, 'dan_harrington', 1L), None))
671
+        self.assertEquals(auth.auth('dan_harrington', 'bar'), ((4L, 'dan_harrington', 1L, -1), None))
672
         self.assertEquals(get_messages(), [])
673
 
674
         clear_all_messages()
675
Index: database/1.7.5-2.0.0.sql
676
===================================================================
677
--- database/1.7.5-2.0.0.sql	(r�vision 6257)
678
+++ database/1.7.5-2.0.0.sql	(copie de travail)
679
 -1,3 +1,6 @@
680
--- resthost must persist
681
-ALTER table resthost ENGINE=MyIsam;
682
-ALTER table route ENGINE=MyIsam;
683
+UPDATE server SET version = '2.0.0';
684
+
685
+-- max tables allowed , no check if -1
686
+ALTER TABLE `users` ADD `tables_max` INT UNSIGNED DEFAULT -1;
687
+
688
+
689
Index: database/schema.sql.in
690
===================================================================
691
--- database/schema.sql.in	(r�vision 6257)
692
+++ database/schema.sql.in	(copie de travail)
693
 -60,13 +60,15 @@
694
   password VARCHAR(32),
695
   -- 1 is a regular player, 0 is an observer and cannot play, 2 is admin
696
   privilege INT DEFAULT 1,
697
+  -- max tables allowed , no check if -1
698
+  tables_max INT DEFAULT -1,    
699
   -- locale
700
   locale VARCHAR(32) DEFAULT "en_US",
701
 
702
   rating INT DEFAULT 1000,
703
   future_rating FLOAT DEFAULT 1000,
704
   games_count INT DEFAULT 0,
705
-  
706
+    
707
   PRIMARY KEY (serial),
708
   KEY name_idx (name),
709
   UNIQUE KEY email_idx (email)