Attached is a patch that I believe will close sr #2208 when applied to
trunk, which I hope to do tomorrow morning (US/Eastern).
There's more I want to do in pokerservice.py. I've talked to Loic about
storing the payouts as they went down in the database, since we can't be
sure that a change in the algorithm/table hasn't occured since the
tourney ran.
However, that should be a separate patch. If there are no objections
tomorrow morning when I get online, I'll merge this from r5187 on
/branches/poker-prizes into trunk.
This patch is copyrighted by me and licensed GPLv3-or-later.
diff --git a/poker-engine/ChangeLog b/poker-engine/ChangeLog
index 5a149ea..d327add 100644
--- a/poker-engine/ChangeLog
+++ b/poker-engine/ChangeLog
@@ -1,3 +1,61 @@
+2008-12-07 Bradley M. Kuhn <[EMAIL PROTECTED]>
+
+ * pokerengine/Makefile.am (pokerengine_PYTHON): Added
+ pokerprizes.py
+
+ * tests/tournament.py.in (TestPrizes.test1): Adapted test.
+
+ * tests/Makefile.am (EXTRA_DIST): added testmessages.py
+
+ * tests/test-pokertournament.py.in
+ (PokerTournamentTestCase.testPrizes): Adjusted test.
+ (PokerTournamentTestCase.testPrizesAlgorithm): Adjusted test.
+ (PokerTournamentTestCase.testPrizesTable): Adjusted test.
+
+ * tests/test-pokerprizes.py.in
+ (PokerPrizesTestCase.test01_algorithmPrizeInterface): Added test
+ to cover removePlayer().
+ (PokerPrizesTestCase.test02_tablePrizeInterface): Added test to
+ cover removePlayer().
+
+ * pokerengine/pokerprizes.py (PokerPrizes.removePlayer): Wrote method.
+
+ * pokerengine/pokertournament.py (PokerTournament.prizes): Adapted
+ to use self.perize_object.prizes()
+ (PokerTournament.register): Added called to prizes_object.addPlayer()
+ (PokerTournament.unregister): Added called to prizes_object.removePlayer()
+
+ * pokerengine/pokerprizes.py (PokerPrizes.__init__): Added
+ dummy configDirs argument to simplify code in pokertournament.loadPayouts()
+
+ * pokerengine/pokertournament.py
+ (PokerTournament.prizesAlgorithm, PokerTournament.prizesTable):
+ Removed methods.
+ (PokerTournament.loadPayouts): Switched to use PokerPrizesFactory()
+
+ * tests/test-pokerprizes.py.in (PokerPrizesTestCase.tearDown):
+ Added method.
+ (PokerPrizesTestCase.setUp): Added method.
+ (PokerPrizesTestCase.test00_factory): Wrote test.
+
+ * configure.ac (AC_CONFIG_FILES): Added tests/test-pokerprizes.py.
+
+2008-12-06 Bradley M. Kuhn <[EMAIL PROTECTED]>
+
+ * pokerengine/pokerprizes.py (PokerPrizesFactory): Created class.
+ (PokerPrizes): Created class.
+ (PokerPrizesAlgorithm): Created class, using
+ pokertournament.prizesAlgorithm() as getPrizes()
+ (PokerPrizesTable): Created class, using
+ pokertournament.prizesTable() as getPrizes()
+
+ * tests/test-pokerprizes.py.in (PokerPrizesTestCase): Created
+ class.
+ (PokerPrizesTestCase.test01_algorithmPrizeInterface): Adapted from
+ PokerTournamentTestCase.testPrizesAlgorithm
+ (PokerPrizesTestCase.test02_tablePrizeInterface): Adapted from
+ PokerTournamentTestCase.testPrizesTable
+
2008-11-28 Loic Dachary <[EMAIL PROTECTED]>
* Release 1.3.1
diff --git a/poker-engine/configure.ac b/poker-engine/configure.ac
index 8e7e8d3..d12ff81 100644
--- a/poker-engine/configure.ac
+++ b/poker-engine/configure.ac
@@ -96,6 +96,7 @@ AC_CONFIG_FILES([Makefile
tests/test-pokercards.py
tests/test-pokerengineconfig.py
tests/test-pokertournament.py
+ tests/test-pokerprizes.py
tests/test-game.py
tests/test-pokerchips.py
tests/test-pokerrake.py
diff --git a/poker-engine/pokerengine/Makefile.am b/poker-engine/pokerengine/Makefile.am
index 666cf95..7f3f8de 100644
--- a/poker-engine/pokerengine/Makefile.am
+++ b/poker-engine/pokerengine/Makefile.am
@@ -34,5 +34,6 @@ pokerengine_PYTHON = \
pokerengineconfig.py \
pokergame.py \
pokerrake.py \
+ pokerprizes.py \
pokertournament.py \
version.py
diff --git a/poker-engine/pokerengine/pokerprizes.py b/poker-engine/pokerengine/pokerprizes.py
new file mode 100644
index 0000000..9e849dd
--- /dev/null
+++ b/poker-engine/pokerengine/pokerprizes.py
@@ -0,0 +1,147 @@
+#
+# Copyright (C) 2008 Bradley M. Kuhn <[EMAIL PROTECTED]>
+# Copyright (C) 2006, 2007, 2008 Loic Dachary <[EMAIL PROTECTED]>
+# Copyright (C) 2004, 2005, 2006 Mekensleep <[EMAIL PROTECTED]>
+# 24 rue vieille du temple, 75004 Paris
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Authors:
+# Bradley M. Kuhn <[EMAIL PROTECTED]>
+# Loic Dachary <[EMAIL PROTECTED]>
+#
+from pokerengine.pokerengineconfig import Config
+############################################################################
+class PokerPrizesFactory:
+ """PokerPrizes is designed to handle payout strcutres for poker
+ tournaments. The Factory is used to generate different types of
+ payout structure builds.
+
+ The public interface usage looks something like this:
+
+ prizes = pokerprizes.PokerPrizeFactory("Type")(buyInAmount = 100, playerCount = 5)
+ prizes.addPlayer()
+ prizeArray = prizes.getPrizes()
+ # returns an list where index+1 st place gets the price, prizeArray[index]"""
+
+ def __init__(self, moduleStr = 'pokerprizes', classPrefix = "PokerPrizes", defaultClass = "PokerPrizesAlgorithm"):
+ self.moduleStr = moduleStr
+ self.classPrefix = classPrefix
+ self.defaultClass = defaultClass
+ # ----------------------------------------------------------------------
+ def error(self, string):
+ self.message("ERROR " + string)
+ # ----------------------------------------------------------------------
+ def message(self, string):
+ print string
+ # ----------------------------------------------------------------------
+ def getClass(self, classname):
+ classname = self.classPrefix + classname
+ try:
+ return getattr(__import__(self.moduleStr, globals(), locals(), [classname]), classname)
+ except AttributeError, ae:
+ self.error(ae.__str__())
+ classname = self.defaultClass
+ return getattr(__import__(self.moduleStr, globals(), locals(), [classname]), classname)
+############################################################################
+class PokerPrizes:
+ """PokerPrizesVirtual base class for PokerPrizes"""
+ def __init__(self, buyInAmount, playerCount = 0, guaranteeAmount = 0, configDirs = None):
+ self.buy_in = buyInAmount
+ self.player_count = playerCount
+ self.guarantee_amount = guaranteeAmount
+ # ----------------------------------------------------------------------
+ def error(self, string):
+ self.message("ERROR " + string)
+ # ----------------------------------------------------------------------
+ def message(self, string):
+ print "[PokerPrizes] " + string
+ # ----------------------------------------------------------------------
+ def addPlayer(self):
+ self.player_count += 1
+ # ----------------------------------------------------------------------
+ def removePlayer(self):
+ self.player_count -= 1
+ # ----------------------------------------------------------------------
+ def getPrizes(self):
+ errStr = "getPrizes NOT IMPLEMENTED IN ABSTRACT BASE CLASS"
+ self.error(errStr)
+ raise NotImplementedError(errStr)
+############################################################################
+class PokerPrizesAlgorithm(PokerPrizes):
+ def getPrizes(self):
+ buy_in = self.buy_in
+ candidates_count = self.player_count
+ if candidates_count < 5:
+ winners = 1
+ elif candidates_count < 10:
+ winners = 2
+ elif candidates_count < 20:
+ winners = 3
+ elif candidates_count < 30:
+ winners = 4
+ elif candidates_count < 40:
+ winners = 6
+ elif candidates_count < 50:
+ winners = int(candidates_count * 0.2)
+ elif candidates_count < 200:
+ winners = int(candidates_count * 0.15)
+ else:
+ winners = int(candidates_count * 0.1)
+
+ prizes = []
+ prize_pool = max(self.guarantee_amount, buy_in * candidates_count)
+ money_left = prize_pool
+ while winners > 0:
+ if money_left / winners < max(1, prize_pool / 100, int(buy_in * 2.5)):
+ prizes.extend([ money_left / winners ] * winners)
+ winners = 0
+ else:
+ money_left /= 2
+ winners -= 1
+ prizes.append(money_left)
+ rest = prize_pool - sum(prizes)
+ prizes[0] += rest
+ return prizes
+############################################################################
+class PokerPrizesTable(PokerPrizes):
+ def __init__(self, buyInAmount, playerCount = 0, guaranteeAmount = 0, configDirs = ['.'],
+ configFileName = "poker.payouts.xml"):
+ self._loadPayouts(configDirs)
+
+ PokerPrizes.__init__(self, buyInAmount = buyInAmount, playerCount = playerCount,
+ guaranteeAmount = guaranteeAmount)
+ # ----------------------------------------------------------------------
+ def _loadPayouts(self, dirs):
+ config = Config(dirs)
+ config.load("poker.payouts.xml")
+ self.payouts = []
+ for node in config.header.xpathEval("/payouts/payout"):
+ properties = config.headerNodeProperties(node)
+ self.payouts.append(( int(properties['max']), map(lambda percent: float(percent) / 100, node.content.split())))
+ # ----------------------------------------------------------------------
+ def getPrizes(self):
+ buy_in = self.buy_in
+ for ( maximum, payouts ) in self.payouts:
+ if self.player_count <= maximum:
+ break
+
+ total = max(self.guarantee_amount, self.player_count * buy_in)
+ prizes = map(lambda percent: int(total * percent), payouts)
+ #
+ # What's left because of rounding errors goes to the tournament winner
+ #
+ prizes[0] += total - sum(prizes)
+ return prizes
diff --git a/poker-engine/pokerengine/pokertournament.py b/poker-engine/pokerengine/pokertournament.py
index 2e00640..de2fef9 100644
--- a/poker-engine/pokerengine/pokertournament.py
+++ b/poker-engine/pokerengine/pokertournament.py
@@ -1,11 +1,8 @@
#
# Copyright (C) 2006, 2007, 2008 Loic Dachary <[EMAIL PROTECTED]>
-# Copyright (C) 2004, 2005, 2006 Mekensleep
-#
-# Mekensleep
-# 24 rue vieille du temple
-# 75004 Paris
-# [EMAIL PROTECTED]
+# Copyright (C) 2008 Bradley M. Kuhn <[EMAIL PROTECTED]>
+# Copyright (C) 2004, 2005, 2006 Mekensleep <[EMAIL PROTECTED]>
+# 24 rue vieille du temple, 75004 Paris
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -35,7 +32,7 @@ def tournament_seconds():
shuffler = random
from pokerengine.pokergame import PokerGameServer
-from pokerengine.pokerengineconfig import Config
+from pokerengine.pokerprizes import PokerPrizesFactory
TOURNAMENT_STATE_ANNOUNCED = "announced"
TOURNAMENT_STATE_REGISTERING = "registering"
@@ -226,12 +223,7 @@ class PokerTournament:
self.updateRegistering()
def loadPayouts(self):
- config = Config(self.dirs)
- config.load("poker.payouts.xml")
- self.payouts = []
- for node in config.header.xpathEval("/payouts/payout"):
- properties = config.headerNodeProperties(node)
- self.payouts.append(( int(properties['max']), map(lambda percent: float(percent) / 100, node.content.split())))
+ self.prizes_object = PokerPrizesFactory().getClass(self.prizes_specs.capitalize())(buyInAmount = self.buy_in, playerCount = self.registered, configDirs = self.dirs)
def message(self, message):
print self.prefix + "[PokerTournament %s] " % self.name + message
@@ -366,6 +358,7 @@ class PokerTournament:
if self.can_register:
self.players.append(serial)
self.registered += 1
+ self.prizes_object.addPlayer()
if self.state == TOURNAMENT_STATE_REGISTERING:
self.updateRunning()
elif self.state == TOURNAMENT_STATE_RUNNING:
@@ -378,6 +371,7 @@ class PokerTournament:
if self.state == TOURNAMENT_STATE_REGISTERING:
self.players.remove(serial)
self.registered -= 1
+ self.prizes_object.removePlayer()
return True
else:
return False
@@ -511,60 +505,12 @@ class PokerTournament:
return len(to_equalize) > 0
def prizes(self):
+ # FIXME?: I left this test for self.can_register because it was
+ # here before PokerPrizes() class existed, but it is not clear to
+ # me that it should still be here. I have made the tests cover it
+ # though. -- bkuhn, 2008-12-07
if self.can_register:
return None
if not self.rank2prize:
- if self.prizes_specs == "algorithm":
- self.rank2prize = self.prizesAlgorithm()
- elif self.prizes_specs == "table":
- self.rank2prize = self.prizesTable()
+ self.rank2prize = self.prizes_object.getPrizes()
return self.rank2prize
-
- def prizesAlgorithm(self):
- buy_in = self.buy_in
- candidates_count = self.registered
- if candidates_count < 5:
- winners = 1
- elif candidates_count < 10:
- winners = 2
- elif candidates_count < 20:
- winners = 3
- elif candidates_count < 30:
- winners = 4
- elif candidates_count < 40:
- winners = 6
- elif candidates_count < 50:
- winners = int(candidates_count * 0.2)
- elif candidates_count < 200:
- winners = int(candidates_count * 0.15)
- else:
- winners = int(candidates_count * 0.1)
-
- prizes = []
- prize_pool = max(self.prize_min, buy_in * candidates_count)
- money_left = prize_pool
- while winners > 0:
- if money_left / winners < max(1, prize_pool / 100, int(buy_in * 2.5)):
- prizes.extend([ money_left / winners ] * winners)
- winners = 0
- else:
- money_left /= 2
- winners -= 1
- prizes.append(money_left)
- rest = prize_pool - sum(prizes)
- prizes[0] += rest
- return prizes
-
- def prizesTable(self):
- buy_in = self.buy_in
- for ( maximum, payouts ) in self.payouts:
- if self.registered <= maximum:
- break
-
- total = max(self.prize_min, self.registered * buy_in)
- prizes = map(lambda percent: int(total * percent), payouts)
- #
- # What's left because of rounding errors goes to the tournament winner
- #
- prizes[0] += total - sum(prizes)
- return prizes
diff --git a/poker-engine/tests/Makefile.am b/poker-engine/tests/Makefile.am
index 3dd412b..fc5af18 100644
--- a/poker-engine/tests/Makefile.am
+++ b/poker-engine/tests/Makefile.am
@@ -30,6 +30,7 @@ export PYTHON
EXTRA_DIST = \
coverage.py \
+ testmessages.py \
test-data/pokerrake.py \
bugs.py \
$(wildcard conf/*.xml) \
diff --git a/poker-engine/tests/test-pokerprizes.py.in b/poker-engine/tests/test-pokerprizes.py.in
new file mode 100644
index 0000000..9f6902d
--- /dev/null
+++ b/poker-engine/tests/test-pokerprizes.py.in
@@ -0,0 +1,203 @@
+# -*- mode: python -*-
+# Copyright (C) 2008 Bradley M. Kuhn <[EMAIL PROTECTED]>
+# Copyright (C) 2006, 2007, 2008 Loic Dachary <[EMAIL PROTECTED]>
+# Copyright (C) 2006 Mekensleep <[EMAIL PROTECTED]>
+# 24 rue vieille du temple, 75004 Paris
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Authors:
+# Bradley M. Kuhn <[EMAIL PROTECTED]>
+# Pierre-Andre (05/2006)
+# Loic Dachary <[EMAIL PROTECTED]>
+#
+
+import sys, os
+sys.path.insert(0, "@top_srcdir@")
+
+import unittest
+import os.path
+import types
+import time
+
+from testmessages import restore_all_messages, silence_all_messages, search_output, clear_all_messages, get_messages
+from pokerengine import pokerprizes
+
+class PokerPrizesTestCase(unittest.TestCase):
+ TestConfDirectory = '@top_srcdir@/conf'
+
+ # ---------------------------------------------------------
+ def setUp(self):
+ silence_all_messages()
+ self.dirs = ['.', PokerPrizesTestCase.TestConfDirectory, '~/conf']
+
+ # -------------------------------------------------------
+ def tearDown(self):
+ pass
+ # -------------------------------------------------------------------------
+ def test00_factory(self):
+ """test00_factory
+ basic factory interface tests."""
+ f = pokerprizes.PokerPrizesFactory()
+ clear_all_messages()
+ f.error("test")
+ self.assertEquals(get_messages(), ['ERROR test'])
+
+ self.failUnless(f.getClass(""), pokerprizes.PokerPrizesAlgorithm)
+
+ clear_all_messages()
+ self.assertEquals(f.getClass("DOESNOTEXIST"), pokerprizes.PokerPrizesAlgorithm)
+ self.assertEquals(get_messages(), ["ERROR 'module' object has no attribute 'PokerPrizesDOESNOTEXIST'"])
+ # -------------------------------------------------------
+ def test01_algorithmPrizeInterface(self):
+ """test01_algorithmPrizeInterface
+ Test the payout structure of the Algorithm prize interface"""
+ pa = pokerprizes.PokerPrizesFactory().getClass("Algorithm")(buyInAmount = 100, playerCount = 4)
+ self.assertEquals(pa.buy_in, 100)
+ self.assertEquals(pa.player_count, 4)
+
+ self.failUnlessEqual(pa.getPrizes(), [400])
+
+ for cnt in range(5, 9):
+ pa.addPlayer()
+ self.failUnlessEqual(pa.player_count, cnt)
+ if cnt == 5:
+ pa.removePlayer()
+ self.assertEquals(pa.player_count, 4)
+ self.failUnlessEqual(pa.getPrizes(), [400])
+ pa.addPlayer()
+ self.assertEquals(pa.player_count, cnt)
+ self.failUnlessEqual(pa.getPrizes(), [375, 125])
+
+ self.failUnlessEqual(pa.getPrizes(), [600, 200])
+
+ for cnt in range(9, 19):
+ pa.addPlayer()
+ self.failUnlessEqual(pa.player_count, cnt)
+ self.failUnlessEqual(pa.getPrizes(), [1125, 450, 225])
+
+ for cnt in range(19, 29):
+ pa.addPlayer()
+ self.failUnlessEqual(pa.player_count, cnt)
+
+ self.failUnlessEqual(pa.getPrizes(), [1575, 700, 350, 175])
+
+ for cnt in range(29, 39):
+ pa.addPlayer()
+ self.failUnlessEqual(pa.player_count, cnt)
+
+ self.failUnlessEqual(pa.getPrizes(), [1902, 950, 237, 237, 237, 237])
+
+ for cnt in range(39, 49):
+ pa.addPlayer()
+ self.failUnlessEqual(pa.player_count, cnt)
+
+ self.failUnlessEqual(len(pa.getPrizes()), int(48 * 0.20))
+
+ for cnt in range(49, 199):
+ pa.addPlayer()
+ self.failUnlessEqual(pa.player_count, cnt)
+
+ self.failUnlessEqual(len(pa.getPrizes()), int(198 * 0.15))
+
+ for cnt in range(199, 299):
+ pa.addPlayer()
+ self.failUnlessEqual(pa.player_count, cnt)
+
+ self.failUnlessEqual(len(pa.getPrizes()), int(298 * 0.10))
+ # -------------------------------------------------------
+ def test02_tablePrizeInterface(self):
+ """test02_tablePrizeInterface
+ Test the payout structure of the table prize interface"""
+ pt = pokerprizes.PokerPrizesFactory().getClass("Table")(buyInAmount = 100, playerCount = 2, configDirs = self.dirs)
+ self.assertEquals(pt.buy_in, 100)
+ self.assertEquals(pt.player_count, 2)
+
+ self.failUnlessEqual(pt.getPrizes(), [200])
+
+ for player in range(4, 7):
+ pt.addPlayer()
+ if player == 4:
+ pt.removePlayer()
+ self.assertEquals(pt.player_count, 2)
+ self.failUnlessEqual(pt.getPrizes(), [200])
+ pt.addPlayer()
+ self.assertEquals(pt.player_count, 3)
+ self.failUnlessEqual(pt.getPrizes(), [300])
+
+ self.failUnlessEqual(pt.getPrizes(), [350, 150])
+
+ for player in range(7, 28):
+ pt.addPlayer()
+ self.failUnlessEqual(pt.getPrizes(), [1300, 780, 520])
+
+ for player in range(28, 48):
+ pt.addPlayer()
+ self.failUnlessEqual(pt.getPrizes(), [1840, 1104, 736, 552, 368])
+
+ for player in range(48, 198):
+ pt.addPlayer()
+ self.failUnlessEqual(pt.getPrizes(), [5880, 3920, 2450, 1764, 1568, 1274, 980, 784, 588, 392])
+
+ for player in range(198, 298):
+ pt.addPlayer()
+ self.failUnlessEqual(len(pt.getPrizes()), 20)
+ # -------------------------------------------------------
+ def test03_virtualBaseClass(self):
+ """test03_virtualBaseClass
+ Test minor things not elsewhere covered for the base class"""
+ v = pokerprizes.PokerPrizes(5, playerCount = 3, guaranteeAmount = 100)
+ self.assertEquals(v.buy_in, 5)
+ self.assertEquals(v.player_count, 3)
+ self.assertEquals(v.guarantee_amount, 100)
+
+ clear_all_messages()
+ v.error("test")
+ self.assertEquals(get_messages(), ['ERROR test'])
+
+ clear_all_messages()
+ exceptCaught = False
+ try:
+ v.getPrizes()
+ self.failIf(True) # should not reach here
+ except NotImplementedError, nie:
+ exceptCaught = True
+ self.assertEquals(nie.__str__(), 'getPrizes NOT IMPLEMENTED IN ABSTRACT BASE CLASS')
+ self.failUnless(exceptCaught)
+ self.assertEquals(get_messages(), ['ERROR getPrizes NOT IMPLEMENTED IN ABSTRACT BASE CLASS'])
+# ---------------------------------------------------------
+def GetTestSuite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(PokerPrizesTestCase))
+ # Comment out above and use line below this when you wish to run just
+ # one test by itself (changing prefix as needed).
+# suite.addTest(unittest.makeSuite(Breaks, prefix = "test2"))
+ return suite
+
+# ---------------------------------------------------------
+def Run(verbose):
+ return unittest.TextTestRunner(verbosity=verbose).run(GetTestSuite())
+
+# ---------------------------------------------------------
+if __name__ == '__main__':
+ if Run(int(os.environ.get('VERBOSE_T', 2))).wasSuccessful():
+ sys.exit(0)
+ else:
+ sys.exit(1)
+
+# Interpreted by emacs
+# Local Variables:
+# compile-command: "( cd .. ; ./config.status tests/test-pokerprizes.py ) ; ( cd ../tests ; make COVERAGE_FILES='../pokerengine/pokerprizes.py' TESTS='coverage-reset test-pokerprizes.py coverage-report' check )"
+# End:
diff --git a/poker-engine/tests/test-pokertournament.py.in b/poker-engine/tests/test-pokertournament.py.in
index e9703fc..caed381 100644
--- a/poker-engine/tests/test-pokertournament.py.in
+++ b/poker-engine/tests/test-pokertournament.py.in
@@ -38,7 +38,10 @@ class ConstantPlayerShuffler:
def shuffle(self, what):
what.sort()
+from testmessages import restore_all_messages, silence_all_messages, search_output, clear_all_messages, get_messages
+
from pokerengine import pokertournament
+from pokerengine.pokerprizes import PokerPrizesTable, PokerPrizesAlgorithm
pokertournament.shuffler = ConstantPlayerShuffler()
class PokerTournamentTestCase(unittest.TestCase):
@@ -113,7 +116,7 @@ class PokerTournamentTestCase(unittest.TestCase):
'rebuy_delay' : 30, \
'add_on' : 10, \
'add_on_delay' : 120, \
- 'prizes_specs' : 'prizes', \
+ 'prizes_specs' : 'table', \
}
tournament = pokertournament.PokerTournament(**arguments)
@@ -354,43 +357,77 @@ class PokerTournamentTestCase(unittest.TestCase):
'buy_in' : 100, \
'players_quota' : 300, \
'seats_per_game' : 2, \
- 'verbose' : int(os.environ.get('VERBOSE_T', 3))
+ 'verbose' : int(os.environ.get('VERBOSE_T', 3)), \
+ 'prizes_specs' : 'algorithm'
}
-
tournament = pokertournament.PokerTournament(**arguments)
+
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = True
for player in range(4):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesAlgorithm(), [400])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [400])
+ tournament.can_register = True
for player in range(4, 8):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesAlgorithm(), [600, 200])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [600, 200])
+ tournament.can_register = True
for player in range(8, 18):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesAlgorithm(), [1125, 450, 225])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [1125, 450, 225])
+ tournament.can_register = True
for player in range(18, 28):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesAlgorithm(), [1575, 700, 350, 175])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [1575, 700, 350, 175])
+ tournament.can_register = True
for player in range(28, 38):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesAlgorithm(), [1902, 950, 237, 237, 237, 237])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [1902, 950, 237, 237, 237, 237])
+ tournament.can_register = True
for player in range(38, 48):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(len(tournament.prizesAlgorithm()), int(48 * 0.20))
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(len(tournament.prizes()), int(48 * 0.20))
+ tournament.can_register = True
for player in range(48, 198):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(len(tournament.prizesAlgorithm()), int(198 * 0.15))
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(len(tournament.prizes()), int(198 * 0.15))
+ tournament.can_register = True
for player in range(198, 298):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(len(tournament.prizesAlgorithm()), int(298 * 0.10))
-
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(len(tournament.prizes()), int(298 * 0.10))
+ tournament.can_register = True
# -------------------------------------------------------
def testPrizesTable(self):
"""Test Poker Tournament : Prizes table"""
@@ -400,35 +437,58 @@ class PokerTournamentTestCase(unittest.TestCase):
'buy_in' : 100, \
'players_quota' : 300, \
'seats_per_game' : 2, \
+ 'prizes_specs' : 'table', \
'verbose' : int(os.environ.get('VERBOSE_T', 3))
}
-
tournament = pokertournament.PokerTournament(**arguments)
-
+
for player in range(2):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesTable(), [200])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [200])
+ tournament.can_register = True
for player in range(4, 7):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesTable(), [350, 150])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [350, 150])
+ tournament.can_register = True
for player in range(7, 28):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesTable(), [1300, 780, 520])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [1300, 780, 520])
+ tournament.can_register = True
for player in range(28, 48):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesTable(), [1840, 1104, 736, 552, 368])
-
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(tournament.prizes(), [1840, 1104, 736, 552, 368])
+ tournament.can_register = True
+
for player in range(48, 198):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(tournament.prizesTable(), [5880, 3920, 2450, 1764, 1568, 1274, 980, 784, 588, 392])
+ self.assertEquals(tournament.prizes(), None)
+ tournament.rank2prize = None
+ tournament.can_register = False
+ self.failUnlessEqual(tournament.prizes(), [5880, 3920, 2450, 1764, 1568, 1274, 980, 784, 588, 392])
+ tournament.can_register = True
for player in range(198, 298):
self.failUnless(tournament.register(player))
- self.failUnlessEqual(len(tournament.prizesTable()), 20)
-
+ self.assertEquals(tournament.prizes(), None)
+ tournament.can_register = False
+ tournament.rank2prize = None
+ self.failUnlessEqual(len(tournament.prizes()), 20)
+ tournament.can_register = True
# -------------------------------------------------------
def testPrizes(self):
"""Test Poker Tournament : Prizes"""
@@ -444,24 +504,55 @@ class PokerTournamentTestCase(unittest.TestCase):
}
tournament = pokertournament.PokerTournament(**arguments)
-
self.failUnlessEqual(tournament.prizes(), None)
-
for player in range(20):
self.failUnless(tournament.register(player))
tournament.prizes_specs = 'table'
tournament.rank2prize = None
- self.failUnlessEqual(tournament.prizesTable(), tournament.prizes())
-
- tournament.prizes_specs = 'algorithm'
+ p = PokerPrizesTable(buyInAmount = 100, playerCount = 20, configDirs = self.dirs)
+ self.failUnlessEqual(tournament.prizes_object.player_count, p.player_count)
+ self.failUnlessEqual(tournament.prizes_object.buy_in, p.buy_in)
+ self.failUnlessEqual(tournament.prizes(), p.getPrizes())
+
+ arguments['prizes_specs'] = 'algorithm'
+ tournament = pokertournament.PokerTournament(**arguments)
+ self.failUnlessEqual(tournament.prizes(), None)
+ for player in range(20):
+ self.failUnless(tournament.register(player))
tournament.rank2prize = None
- self.failUnlessEqual(tournament.prizesAlgorithm(), tournament.prizes())
+ p = PokerPrizesAlgorithm(buyInAmount = 100, playerCount = 20)
+ self.failUnlessEqual(tournament.prizes_object.player_count, p.player_count)
+ self.failUnlessEqual(tournament.prizes_object.buy_in, p.buy_in)
+ self.failUnlessEqual(tournament.prizes(), p.getPrizes())
- tournament.prizes_specs = 'invalid'
- tournament.rank2prize = None
+
+ silence_all_messages()
+
+ arguments['prizes_specs'] = 'invalid'
+ tournament = pokertournament.PokerTournament(**arguments)
self.failUnlessEqual(tournament.prizes(), None)
-
+ for player in range(20):
+ self.failUnless(tournament.register(player))
+ tournament.rank2prize = None
+
+ # Behavior before pokerprizes existed when prizes_specs was
+ # invalid in some way, it simply had nothing returned from
+ # tournament.prizes(). The test case, therefore, was as below:
+
+# self.failUnlessEqual(tournament.prizes(), None) However, it makes
+
+ # However, it more sense to simply default to something if a prize
+ # spec is invalid, and print an error message. That is what now
+ # happens, and that's what this test code does:
+
+ msgs = get_messages()
+ self.assertEquals(msgs[0], "ERROR 'module' object has no attribute 'PokerPrizesInvalid'")
+ p = PokerPrizesAlgorithm(buyInAmount = 100, playerCount = 20)
+ self.failUnlessEqual(tournament.prizes_object.player_count, p.player_count)
+ self.failUnlessEqual(tournament.prizes_object.buy_in, p.buy_in)
+ self.failUnlessEqual(tournament.prizes(), p.getPrizes())
+ restore_all_messages()
# -------------------------------------------------------
def testMovePlayer(self):
"""Test Poker Tournament : Move player"""
diff --git a/poker-engine/tests/testmessages.py b/poker-engine/tests/testmessages.py
new file mode 100644
index 0000000..dd9b65c
--- /dev/null
+++ b/poker-engine/tests/testmessages.py
@@ -0,0 +1,115 @@
+#
+# Copyright (C) 2006, 2007, 2008 Loic Dachary <[EMAIL PROTECTED]>
+# Copyright (C) 2006 Mekensleep <[EMAIL PROTECTED]>
+# 24 rue vieille du temple, 75004 Paris
+#
+# This software's license gives you freedom; you can copy, convey,
+# propagate, redistribute and/or modify this program under the terms of
+# the GNU General Public License (GPL) as published by the Free Software
+# Foundation (FSF), either version 3 of the License, or (at your option)
+# any later version of the GPL published by the FSF.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file in the toplevel directory called
+# "GPLv3". If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors:
+# Loic Dachary <[EMAIL PROTECTED]>
+#
+import sys, os
+
+classes = []
+
+from pokerengine import pokergame
+classes.append(pokergame.PokerGame)
+
+from pokerengine import pokerprizes
+classes.append(pokerprizes.PokerPrizesFactory)
+classes.append(pokerprizes.PokerPrizes)
+
+from twisted.internet import defer
+
+verbose = int(os.environ.get('VERBOSE_T', '-1'))
+
+#
+# for coverage purpose, make sure all message functions
+# are called at least once
+#
+def call_messages():
+ import StringIO
+ for a_class in classes:
+ stdout = sys.stdout
+ sys.stdout = StringIO.StringIO()
+ class F(a_class):
+ def __init__(self, *args, **kwargs):
+ self._prefix = 'P'
+ self.prefix = 'P'
+ self.id = 1
+ self.name = 'name'
+ F().message('')
+ sys.stdout = stdout
+call_messages()
+
+messages_needle = ''
+messages_grep_hit = None
+def grep_output(needle):
+ messages_grep_hit = defer.Deferred()
+ messages_needle = needle
+ return messages_grep_hit
+
+def messages_grep(haystack):
+ if haystack.find(messages_needle):
+ hit = messages_grep_hit
+ messages_grep_hit = None
+ hit.callback(haystack)
+
+def messages_append(string):
+ if verbose > 3:
+ print "OUTPUT: " + string
+ if not hasattr(string, '__str__'):
+ raise Exception, "Message comes in as non-stringifiable object"
+ string = string.__str__()
+ messages_out.append(string)
+ messages_grep(string)
+
+class2message = {
+ pokergame.PokerGame: lambda self, string: messages_append(self.prefix + "[PokerGame " + str(self.id) + "] " + string)
+ }
+messages_out = []
+
+def redirect_messages(a_class):
+ if not hasattr(a_class, 'orig_message'):
+ a_class.orig_message = [ ]
+ a_class.orig_message.append(a_class.message)
+ a_class.message = class2message.get(a_class, lambda self, string: messages_append(string))
+
+def silence_all_messages():
+ messages_out = []
+ for a_class in classes:
+ redirect_messages(a_class)
+
+def restore_all_messages():
+ for a_class in classes:
+ a_class.message = a_class.orig_message.pop()
+
+def search_output(what):
+ if verbose > 1:
+ print "search_output: " + what
+ for message in messages_out:
+ if message.find(what) >= 0:
+ return True
+ if verbose > 1:
+ print "\tnot in " + message
+ return False
+
+def clear_all_messages():
+ global messages_out
+ messages_out = []
+
+def get_messages():
+ return messages_out
diff --git a/poker-engine/tests/tournament.py.in b/poker-engine/tests/tournament.py.in
index b2d6ac6..0fd6587 100644
--- a/poker-engine/tests/tournament.py.in
+++ b/poker-engine/tests/tournament.py.in
@@ -439,68 +439,102 @@ class TestCreate(unittest.TestCase):
class TestPrizes(unittest.TestCase):
def test1(self):
- tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ])
- tourney.can_register = False
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'algorithm', buy_in = 5, players_quota = 100)
+ for ii in range(1, 11): tourney.register(ii)
- tourney.prizes_specs = "algorithm"
- tourney.buy_in = 5
-
- tourney.registered = 10
- tourney.rank2prize = None
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [32, 12, 6])
- tourney.registered = 20
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'algorithm', buy_in = 5, players_quota = 100)
+ for ii in range(1, 21): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [57, 25, 12, 6])
- tourney.registered = 50
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'algorithm', buy_in = 5, players_quota = 1000)
+ for ii in range(1, 51): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [129, 62, 31, 7, 7, 7, 7])
- tourney.registered = 200
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'algorithm', buy_in = 5, players_quota = 1000)
+ for ii in range(200): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [506, 250, 125, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7])
- tourney.prizes_specs = "table"
-
- tourney.registered = 3
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(3): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [15])
- tourney.registered = 6
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(6): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [21, 9])
- tourney.registered = 30
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(30): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [75, 45, 30])
- tourney.registered = 50
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(50): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [100, 60, 40, 30, 20])
- tourney.registered = 200
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(200): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [300, 200, 125, 90, 80, 65, 50, 40, 30, 20])
- tourney.registered = 300
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(300): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [453, 292, 180, 120, 97, 75, 52, 37, 26, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15])
- tourney.registered = 500
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(500): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [641, 375, 250, 200, 125, 100, 75, 50, 43, 31, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18])
- tourney.registered = 700
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 1000)
+ for ii in range(700): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [717, 437, 315, 245, 175, 140, 105, 61, 52, 43, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17])
- tourney.registered = 1000
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 5000)
+ for ii in range(1000): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [1026, 600, 450, 350, 250, 200, 150, 87, 75, 62, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10])
- tourney.registered = 5000
- tourney.rank2prize = None
+ tourney = PokerTournament(dirs = [ '../conf', '@top_srcdir@/conf' ],
+ prizes_specs = 'table', buy_in = 5, players_quota = 5000)
+ for ii in range(5000): tourney.register(ii)
+
+ tourney.can_register = False
self.assertEqual(tourney.prizes(), [5036, 3000, 2000, 1500, 1250, 1000, 625, 437, 312, 250, 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37])
--
-- bkuhn
_______________________________________________
Pokersource-users mailing list
[email protected]
https://mail.gna.org/listinfo/pokersource-users