diff --git a/docs/known-bugs-and-planned-features.txt b/docs/known-bugs-and-planned-features.txt index e21ec833..a8a3f988 100644 --- a/docs/known-bugs-and-planned-features.txt +++ b/docs/known-bugs-and-planned-features.txt @@ -1,97 +1,17 @@ Everything is subject to change and the order does not indicate priority. Patches for any of these or other features are very welcome, see readme-overview.txt for contacts. Please also see db-todo.txt -alpha5 (release 25Sep-2Oct) -====== -pgsql recreate doesnt work, and it may not store version field on creation if using sql file with pgadmin. -check we're reading mucked cards from PS -ebuild: support pgsql -fix HUD config location and update release script accordingly - -(michael) update website for windows installer -(steffen) update install-in-gentoo on website -(steffen) update ebuild and ubuntu guide for HUD_config.xml - -(steffen) store raw hand in db and write reimport function using the raw hand field -make sure totalProfit shows actual profit rather than winnings. -update abbreviations.txt -export settings[hud-defaultInterval] to conf -fill check-/call-raise cache fields - -printhand each and the 2/3 relevant printplayerflags respectively on ps-lhe-ring-successful-steal-by-cutoff.txt and ps-lhe-ring-call-3B-preflop-cb-no2b.txt -change to savannah? -implement steal and positions in stud -anonymiser script to generate testdata without making a dozen find&replace all... remember to replace hand no with running no -separate db table design version and last bugfix in importer -change tabledesign VALIGN and add link to webpage -finish updating filelist -finish todos in git instructions -debian/ubuntu package http://www.debian.org/doc/maint-guide/ch-start.en.html -howto remote DB -move all user docs to webpage -(steffen) contributor list on webpage -finish bringing back tourney -No river stats for stud games? -hole/board cards are not correctly stored in the db for stud games -HORSE (and presumably other mixed games) hand history files not handled correctly -Some MTTs won't import (rebuys??) -Many STTs won't import - before beta =========== -Import draw (maybe without HudCache for a start) -graphs for SD/F, W$wSF, W$@SD -validate webpage -make linux use /etc/fpdb for config first, then ~/.fpdb. -FTP file with only one partial hand causes error -No Full Tilt support in HUD -HUD stat windows are too big on Windows -HUD task bar entries on Windows won't go away -MTT/STT not tested in HUD -HUD stats not aggregated -Player names with non-Latin chars throw warnings in HUD -HUD doesn't start when fpdb is started from the Windows "Start Menu" -Exiting HUD on Windows doesn't properly clean up stat windows +change to savannah? + -ebuild: USE gtk, set permissions in it, copy docs to correct place, use games eclass or whatever to get games group notice, git-ebuild, get it into sunrise -make hud display W$SD etc as fraction. -add dedicated update page -update status or make a support matrix table for website -move version into seperate file for fpdb gui and db -SD/F, W$wsF, W$@SD too low as reported by daedal in 2+2 forum on 12/13aug -create little test script for people to run to verify successful installation of pydeps -split hud data generation into separate for loops and make it more efficient -fix bug that sawFlop/Turn/River/CBChance/etc gets miscalculated if someone is allin - might as well add all-in recognition for this -make 3 default HUD configs (easy (4-5 fields), advanced (10ish fields), crazy (20 or so)) -make it work with postgres -expand instructions for profile file -maybe remove siteId from gametypes -?change most cache fields to bigint to allow extremely big databases in excess of 2 or 4 million hands per stake and position? -rakeback/frequent player points -skins -separate all gui and all processing into files that are named accordingly -ensure that there is only one db handle flying around and that its state is handled properly, ie. by the GUI. i think that might be why we have to reconnect the DB in tableviewer. -why do we have to reconnect in tv.read_names_clicked? -implement error file in importer -catch index error, type error, file not found error -HUD: use different colours according to classification. -move prepare-git.sh and create-release.sh to utils -offer not storing db password -change definition of bet to exclude bring in -fix GUI's load profile -config wizard -file permission script, use games group -make bulk importer display a grand total in the GUI -change save_to_db into one method and probably move into parse_logic Any comment or print with "todo" in it in the sourcecode except what is marked todo in the menu make a quick benchmark of mysql and postgresql: import of my whole db, some tableviewer refreshes with and without updated file Make tab and enter work as sensible in GUIs and implement Ctrl+Q, Ctrl+X and Alt+F4 for close. use profile file for bulk import and table viewer settings and pathes -handle errors properly, in particular wrt to SQL rollback. check that we read sitout correctly in: Full Tilt Poker Game #6150325318: Table Bogside -setup database, database-user and permission from GUI. -update prepare-git to check for license header and copyright. verify at least 2 or 3 sng hands no rush but before 1.0RC @@ -115,7 +35,6 @@ can wait till 1.x ================= in all importer: stop doing if site=="ftp", make class constants for site_id instead It treats fold due to disconnect as voluntary fold which is not ideal -check for unnecessary db.commit() aliases repair hands where the seat lines are missing, happens when observing at FTP flags for storing the reason for winning (best hi, tie for best low, etc.) to DB. not sure actually if this is such a good idea remember that there can be multiple reasons for the same player in the same hand diff --git a/docs/tabledesign.html b/docs/tabledesign.html index 8d283f64..8fcf4884 100644 --- a/docs/tabledesign.html +++ b/docs/tabledesign.html @@ -747,6 +747,11 @@ The program itself is licensed under AGPLv3, see agpl-3.0.txt

Bet stands for bring in, complete, bet, double bet, raise and double raise, since they all - technically - do the same thing. Unbet is used for when an uncalled bet is returned, this will have a negative value for amount.

Other valid values: blind call check fold

+ +

allIn

+

boolean

+

Whether the player went all-in on this action

+

amount

int

diff --git a/packaging/gentoo/fpdb-1.0_alpha4_p86.ebuild b/packaging/gentoo/fpdb-1.0_alpha5_p110.ebuild similarity index 87% rename from packaging/gentoo/fpdb-1.0_alpha4_p86.ebuild rename to packaging/gentoo/fpdb-1.0_alpha5_p110.ebuild index 839f578e..4e55238e 100644 --- a/packaging/gentoo/fpdb-1.0_alpha4_p86.ebuild +++ b/packaging/gentoo/fpdb-1.0_alpha5_p110.ebuild @@ -1,6 +1,7 @@ # Copyright 1999-2008 Gentoo Foundation +# Gentoo had nothing to do with the production of this ebuild, but I'm pre-emptively transferring all copyrights (as far as legally possible under my local jurisdiction) to them. # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/games-util/fpdb/fpdb-1.0_alpha2_p68.ebuild,v 1.0 2008/08/31 23:00:00 steffen@sycamoretest.info Exp $ +# $Header: /var/cvsroot/gentoo-x86/games-util/fpdb/fpdb-1.0_alpha5_p110.ebuild,v 1.0 2008/09/26 steffen@sycamoretest.info Exp $ NEED_PYTHON=2.3 @@ -10,7 +11,6 @@ MY_P="fpdb-${PV}" DESCRIPTION="A database program to track your online poker games" HOMEPAGE="https://sourceforge.net/projects/fpdb/" SRC_URI="mirror://sourceforge/fpdb/${MY_P}.tar.bz2" -#SRC_URI="mirror://sourceforge/fpdb/fpdb-1.0_alpha3-p80.tar.bz2" LICENSE="AGPL-3" SLOT="0" @@ -21,7 +21,10 @@ IUSE="" RDEPEND="virtual/mysql dev-python/mysql-python >=x11-libs/gtk+-2.10 - dev-python/pygtk" + dev-python/pygtk + dev-python/numpy + dev-python/matplotlib" + DEPEND="${RDEPEND}" src_install() { diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py old mode 100644 new mode 100755 diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 612ac2ff..e441f8ba 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -29,7 +29,8 @@ try: from numpy import arange, cumsum from pylab import * except: - print "Failed to load libs for graphing, graphing will not function. Please install numpy and matplotlib." + print "Failed to load libs for graphing, graphing will not function. Please install numpy and matplotlib if you want to use graphs." + print "This is of no consequence for other parts of the program, e.g. import and HUD are NOT affected by this problem." import fpdb_import import fpdb_db diff --git a/pyfpdb/GuiTableViewer.py b/pyfpdb/GuiTableViewer.py index 3714138e..15a21149 100644 --- a/pyfpdb/GuiTableViewer.py +++ b/pyfpdb/GuiTableViewer.py @@ -20,6 +20,7 @@ import pygtk pygtk.require('2.0') import gtk import os +import fpdb_simple try: import MySQLdb diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index c4a84b55..33bdc890 100644 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -38,7 +38,7 @@ import os import thread import Queue -errorfile = open('HUD-error.txt', 'w') +errorfile = open('HUD-error.txt', 'w', 0) sys.stderr = errorfile # pyGTK modules diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 98f0aa27..841d71c0 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -18,8 +18,9 @@ import os import sys -errorfile = open('fpdb-error.log', 'w') -sys.stderr = errorfile +print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." +errorFile = open('fpdb-error-log.txt', 'w', 0) +sys.stderr = errorFile import pygtk pygtk.require('2.0') @@ -346,11 +347,11 @@ class fpdb: #end def load_profile def not_implemented(self): - print "todo: called unimplemented menu entry"#remove this once more entries are implemented + print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented #end def not_implemented def obtain_global_lock(self): - print "todo: implement obtain_global_lock" + print "todo: implement obtain_global_lock (users: pls ignore this)" #end def obtain_global_lock def quit(self, widget, data): @@ -420,7 +421,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy) - self.window.set_title("Free Poker DB - version: alpha4+, p102 or higher") + self.window.set_title("Free Poker DB - version: alpha6+, p118 or higher") self.window.set_border_width(1) self.window.set_size_request(1020,400) self.window.set_resizable(True) @@ -444,7 +445,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") ("/Viewers/_Player Stats (tabulated view) (todo)", None, self.not_implemented, 0, None ), ("/Viewers/Starting _Hands (todo)", None, self.not_implemented, 0, None ), ("/Viewers/_Session Replayer (todo)", None, self.not_implemented, 0, None ), - ("/Viewers/Poker_table Viewer", "T", self.tab_table_viewer, 0, None ), + ("/Viewers/Poker_table Viewer (obselete)", "T", self.tab_table_viewer, 0, None ), #( "/Viewers/Tourney Replayer ( "/_Database", None, None, 0, "" ), ( "/Database/Create or Delete _Database (todo)", None, self.dia_create_del_database, 0, None ), diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 1b672bab..36e39ba9 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -48,7 +48,7 @@ class fpdb_db: try: self.cursor.execute("SELECT * FROM Settings") settings=self.cursor.fetchone() - if settings[0]!=76: + if settings[0]!=118: print "outdated or too new database version - please recreate tables" self.wrongDbVersion=True except:# _mysql_exceptions.ProgrammingError: @@ -152,7 +152,7 @@ class fpdb_db: #end def get_db_info def fillDefaultData(self): - self.cursor.execute("INSERT INTO Settings VALUES (76);") + self.cursor.execute("INSERT INTO Settings VALUES (118);") self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, \"Full Tilt Poker\", 'USD');") self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, \"PokerStars\", 'USD');") self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);") @@ -311,6 +311,7 @@ class fpdb_db: street SMALLINT NOT NULL, actionNo SMALLINT NOT NULL, action CHAR(5) NOT NULL, + allIn BOOLEAN NOT NULL, amount INT NOT NULL, comment TEXT, commentTs DATETIME)""") diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index f4fe56ab..9c52d6bc 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -56,17 +56,17 @@ def import_file_dict(options, settings, callHud=False): inputFile=open(options.inputFile, "rU") #connect to DB - if options.settings['db-backend'] == 2: + if settings['db-backend'] == 2: if not mysqlLibFound: raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file") db = MySQLdb.connect(host = options.server, user = options.user, passwd = options.password, db = options.database) - elif options.settings['db-backend'] == 3: + elif settings['db-backend'] == 3: if not pgsqlLibFound: raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file") db = psycopg2.connect(host = options.server, user = options.user, password = options.password, database = options.database) - elif options.settings['db-backend'] == 4: + elif settings['db-backend'] == 4: pass else: pass @@ -224,5 +224,5 @@ if __name__ == "__main__": (options, sys.argv) = parser.parse_args() - settings={'imp-callFpdbHud':False} + settings={'imp-callFpdbHud':False, 'db-backend':2} import_file_dict(options, settings, False) diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 60cf16de..8ee8f5b2 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -30,7 +30,7 @@ def mainParser(db, cursor, site, category, hand): lineTypes=[] #char, valid values: header, name, cards, action, win, rake, ignore lineStreets=[] #char, valid values: (predeal, preflop, flop, turn, river) - cardValues, cardSuits, boardValues, boardSuits, antes, actionTypes, actionAmounts, actionNos, actionTypeByNo, seatLines, winnings, rakes=[], [],[],[],[],[],[],[],[],[],[],[] + cardValues, cardSuits, boardValues, boardSuits, antes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo, seatLines, winnings, rakes=[],[],[],[],[],[],[],[],[],[],[],[],[] #part 1: read hand no and check for duplicate siteHandNo=fpdb_simple.parseSiteHandNo(hand[0]) @@ -76,7 +76,7 @@ def mainParser(db, cursor, site, category, hand): startCashes=tmp['startCashes'] seatNos=tmp['seatNos'] - fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, winnings, rakes, actionTypes, actionAmounts, actionNos, actionTypeByNo) + fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) #3b read positions if base=="hold": @@ -87,7 +87,7 @@ def mainParser(db, cursor, site, category, hand): if (lineTypes[i]=="cards"): fpdb_simple.parseCardLine (site, category, lineStreets[i], hand[i], names, cardValues, cardSuits, boardValues, boardSuits) elif (lineTypes[i]=="action"): - fpdb_simple.parseActionLine (site, base, hand[i], lineStreets[i], playerIDs, names, actionTypes, actionAmounts, actionNos, actionTypeByNo) + fpdb_simple.parseActionLine (site, base, isTourney, hand[i], lineStreets[i], playerIDs, names, actionTypes, allIns, actionAmounts, actionNos, actionTypeByNo) elif (lineTypes[i]=="win"): fpdb_simple.parseWinLine (hand[i], site, names, winnings, isTourney) elif (lineTypes[i]=="rake"): @@ -99,7 +99,7 @@ def mainParser(db, cursor, site, category, hand): elif (lineTypes[i]=="header" or lineTypes[i]=="rake" or lineTypes[i]=="name" or lineTypes[i]=="ignore"): pass elif (lineTypes[i]=="ante"): - fpdb_simple.parseAnteLine(hand[i], site, names, antes) + fpdb_simple.parseAnteLine(hand[i], site, isTourney, names, antes) elif (lineTypes[i]=="table"): tableResult=fpdb_simple.parseTableLine(site, base, hand[i]) else: @@ -126,9 +126,9 @@ def mainParser(db, cursor, site, category, hand): totalWinnings+=winnings[i] if base=="hold": - hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, actionTypeByNo, winnings, totalWinnings, positions) + hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, positions) else: - hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, actionTypeByNo, winnings, totalWinnings, None) + hudImportData=fpdb_simple.generateHudCacheData(playerIDs, base, category, actionTypes, allIns, actionTypeByNo, winnings, totalWinnings, None) if isTourney: ranks=[] @@ -138,22 +138,22 @@ def mainParser(db, cursor, site, category, hand): if base=="hold": result = fpdb_save_to_db.tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteID, - siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) elif base=="stud": result = fpdb_save_to_db.tourney_stud(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourneyStartTime, payin_amounts, ranks, siteHandNo, siteID, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, cardSuits, winnings, rakes, - actionTypes, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) else: raise fpdb_simple.FpdbError ("unrecognised category") else: if base=="hold": - result = fpdb_save_to_db.ring_holdem_omaha(cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + result = fpdb_save_to_db.ring_holdem_omaha(cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, positions, cardValues, cardSuits, boardValues, boardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) elif base=="stud": result = fpdb_save_to_db.ring_stud(cursor, base, category, siteHandNo, gametypeID, handStartTime, names, playerIDs, startCashes, antes, cardValues, - cardSuits, winnings, rakes, actionTypes, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) + cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts, actionNos, hudImportData, maxSeats, tableName, seatNos) else: raise fpdb_simple.FpdbError ("unrecognised category") db.commit() diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py index c07fd225..5a06b1aa 100644 --- a/pyfpdb/fpdb_save_to_db.py +++ b/pyfpdb/fpdb_save_to_db.py @@ -21,7 +21,7 @@ import fpdb_simple #stores a stud/razz hand into the database -def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): +def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) hands_id=fpdb_simple.storeHands(cursor, site_hand_no, gametype_id, hand_start_time, names, tableName, maxSeats) @@ -31,11 +31,11 @@ def ring_stud(cursor, base, category, site_hand_no, gametype_id, hand_start_time fpdb_simple.storeHudCache(cursor, base, category, gametype_id, player_ids, hudImportData) - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, action_amounts, actionNos) + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) return hands_id #end def ring_stud -def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): +def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a holdem/omaha hand into the database""" fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) fpdb_simple.fill_board_cards(board_values, board_suits) @@ -48,12 +48,12 @@ def ring_holdem_omaha(cursor, base, category, site_hand_no, gametype_id, hand_st fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, action_amounts, actionNos) + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) return hands_id #end def ring_holdem_omaha def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId, siteId, #end of tourney specific params - site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): + site_hand_no, gametype_id, hand_start_time, names, player_ids, start_cashes, positions, card_values, card_suits, board_values, board_suits, winnings, rakes, action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): """stores a tourney holdem/omaha hand into the database""" fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) fpdb_simple.fill_board_cards(board_values, board_suits) @@ -69,7 +69,7 @@ def tourney_holdem_omaha(cursor, base, category, siteTourneyNo, buyin, fee, knoc fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, action_amounts, actionNos) + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) return hands_id #end def tourney_holdem_omaha @@ -77,7 +77,7 @@ def tourney_stud(cursor, base, category, site_tourney_no, buyin, fee, knockout, tourney_start, payin_amounts, ranks, #end of tourney specific params site_hand_no, site_id, gametype_id, hand_start_time, names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes, - action_types, action_amounts, hudImportData): + action_types, allIns, action_amounts, hudImportData): #stores a tourney stud/razz hand into the database fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) @@ -92,6 +92,6 @@ def tourney_stud(cursor, base, category, site_tourney_no, buyin, fee, knockout, fpdb_simple.storeHudData(cursor, base, category, player_ids, hudImportData) - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, action_amounts) + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts) return hands_id #end def tourney_stud diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 2d809763..5d26df28 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -204,7 +204,7 @@ def convertCardValuesBoard(arr): #end def convertCardValuesBoard #this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. -def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, action_amounts, actionNos, actionTypeByNo): +def createArrays(category, seats, card_values, card_suits, antes, winnings, rakes, action_types, allIns, action_amounts, actionNos, actionTypeByNo): for i in range(seats):#create second dimension arrays tmp=[] card_values.append(tmp) @@ -223,6 +223,8 @@ def createArrays(category, seats, card_values, card_suits, antes, winnings, rake tmp=[] action_types.append(tmp) tmp=[] + allIns.append(tmp) + tmp=[] action_amounts.append(tmp) tmp=[] actionNos.append(tmp) @@ -232,6 +234,8 @@ def createArrays(category, seats, card_values, card_suits, antes, winnings, rake tmp=[] action_types[i].append(tmp) tmp=[] + allIns[i].append(tmp) + tmp=[] action_amounts[i].append(tmp) tmp=[] actionNos[i].append(tmp) @@ -542,11 +546,11 @@ def isWinLine(line): #end def isWinLine #returns the amount of cash/chips put into the put in the given action line -def parseActionAmount(line, atype, site): - if (line.endswith(" and is all-in")): - line=line[:-14] - elif (line.endswith(", and is all in")): - line=line[:-15] +def parseActionAmount(line, atype, site, isTourney): + #if (line.endswith(" and is all-in")): + # line=line[:-14] + #elif (line.endswith(", and is all in")): + # line=line[:-15] if line.endswith(", and is capped"):#ideally we should recognise this as an all-in if category is capXl line=line[:-15] @@ -573,8 +577,8 @@ def parseActionAmount(line, atype, site): pos=line.find("to $")+4 amount=float2int(line[pos:]) else: - pos=line.rfind("$")+1 - if pos!=0: + if not isTourney: + pos=line.rfind("$")+1 amount=float2int(line[pos:]) else: #print "line:"+line+"EOL" @@ -591,7 +595,7 @@ def parseActionAmount(line, atype, site): #doesnt return anything, simply changes the passed arrays action_types and # action_amounts. For stud this expects numeric streets (3-7), for # holdem/omaha it expects predeal, preflop, flop, turn or river -def parseActionLine(site, base, line, street, playerIDs, names, action_types, action_amounts, actionNos, actionTypeByNo): +def parseActionLine(site, base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo): if (street=="predeal" or street=="preflop"): street=0 elif (street=="flop"): @@ -606,18 +610,32 @@ def parseActionLine(site, base, line, street, playerIDs, names, action_types, ac for count in range(len(actionNos[street][player])): if actionNos[street][player][count]>=nextActionNo: nextActionNo=actionNos[street][player][count]+1 - + + line, allIn=goesAllInOnThisLine(line) atype=parseActionType(line) playerno=recognisePlayerNo(line, names, atype) - amount=parseActionAmount(line, atype, site) + amount=parseActionAmount(line, atype, site, isTourney) action_types[street][playerno].append(atype) + allIns[street][playerno].append(allIn) action_amounts[street][playerno].append(amount) actionNos[street][playerno].append(nextActionNo) tmp=(playerIDs[playerno], atype) actionTypeByNo[street].append(tmp) #end def parseActionLine +def goesAllInOnThisLine(line): + """returns whether the player went all-in on this line and removes the all-in text from the line.""" + isAllIn=False + if (line.endswith(" and is all-in")): + line=line[:-14] + isAllIn=True + elif (line.endswith(", and is all in")): + line=line[:-15] + isAllIn=True + return (line, isAllIn) +#end def goesAllInOnThisLine + #returns the action type code (see table design) of the given action line def parseActionType(line): if (line.startswith("Uncalled bet")): @@ -657,15 +675,21 @@ def parseActionType(line): #end def parseActionType #parses the ante out of the given line and checks which player paid it, updates antes accordingly. -def parseAnteLine(line, site, names, antes): +def parseAnteLine(line, site, isTourney, names, antes): + #print "parseAnteLine line: ",line for i in range(len(names)): if (line.startswith(names[i].encode("latin-1"))): #found the ante'er pos=line.rfind("$")+1 - if pos!=0: #found $, so must be ring + if not isTourney: antes[i]+=float2int(line[pos:]) else: - pos=line.rfind(" ")+1 - antes[i]+=int(line[pos:]) + if line.find("all-in")==-1: + pos=line.rfind(" ")+1 + antes[i]+=int(line[pos:]) + else: + pos1=line.rfind("ante")+5 + pos2=line.find(" ",pos1) + antes[i]+=int(line[pos1:pos2]) #end def parseAntes #returns the buyin of a tourney in cents @@ -938,7 +962,7 @@ def parseWinLine(line, site, names, winnings, isTourney): for i in range(len(names)): if (line.startswith(names[i].encode("latin-1"))): #found a winner if isTourney: - pos1=line.rfind("collected ")+11 + pos1=line.rfind("collected ")+10 if (site=="ftp"): pos2=line.find(")", pos1) elif (site=="ps"): @@ -1179,14 +1203,14 @@ def splitRake(winnings, rakes, totalRake): rakes[i]=totalRake*winPortion #end def splitRake -def storeActions(cursor, hands_players_ids, action_types, action_amounts, actionNos): +def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, actionNos): #stores into table hands_actions #print "start of storeActions, actionNos:",actionNos #print " action_amounts:",action_amounts - for i in range (len(action_types)): #iterate through streets - for j in range (len(action_types[i])): #iterate through names - for k in range (len(action_types[i][j])): #iterate through individual actions of that player on that street - cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, amount) VALUES (%s, %s, %s, %s, %s)", (hands_players_ids[j], i, actionNos[i][j][k], action_types[i][j][k], action_amounts[i][j][k])) + for i in range (len(actionTypes)): #iterate through streets + for j in range (len(actionTypes[i])): #iterate through names + for k in range (len(actionTypes[i][j])): #iterate through individual actions of that player on that street + cursor.execute ("INSERT INTO HandsActions (handPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", (handsPlayersIds[j], i, actionNos[i][j][k], actionTypes[i][j][k], allIns[i][j][k], actionAmounts[i][j][k])) #end def storeActions def store_board_cards(cursor, hands_id, board_values, board_suits): @@ -1317,7 +1341,7 @@ def store_hands_players_stud_tourney(cursor, hands_id, player_ids, start_cashes, return result #end def store_hands_players_stud_tourney -def generateHudCacheData(player_ids, base, category, action_types, actionTypeByNo, winnings, totalWinnings, positions): +def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo, winnings, totalWinnings, positions): """calculates data for the HUD during import. IMPORTANT: if you change this method make sure to also change the following storage method and table_viewer.prepare_data if necessary""" #setup subarrays of the result dictionary. street0VPI=[] @@ -1465,14 +1489,28 @@ def generateHudCacheData(player_ids, base, category, action_types, actionTypeByN if myStealAttempted: someoneStole=True - + + #calculate saw* values - if (len(action_types[1][player])>0): + isAllIn=False + for i in range(len(allIns[0][player])): + if allIns[0][player][i]: + isAllIn=True + if (len(action_types[1][player])>0 or isAllIn): myStreet1Seen=True - if (len(action_types[2][player])>0): + + for i in range(len(allIns[1][player])): + if allIns[1][player][i]: + isAllIn=True + if (len(action_types[2][player])>0 or isAllIn): myStreet2Seen=True - if (len(action_types[3][player])>0): + + for i in range(len(allIns[2][player])): + if allIns[2][player][i]: + isAllIn=True + if (len(action_types[3][player])>0 or isAllIn): myStreet3Seen=True + mySawShowdown=True for count in range (len(action_types[3][player])): if action_types[3][player][count]=="fold": @@ -1577,7 +1615,7 @@ def generateHudCacheData(player_ids, base, category, action_types, actionTypeByN elif pos>=2 and pos<=4: hudDataPositions.append('M') elif pos>=5 and pos<=7: - hudDataPositions.append('L') + hudDataPositions.append('E') ### RHH Added this elif to handle being a dead hand before the BB (pos==9) elif pos==9: hudDataPositions.append('X') diff --git a/pyfpdb/schema.postgres.sql b/pyfpdb/schema.postgres.sql index 74653ba6..2affb1c6 100644 --- a/pyfpdb/schema.postgres.sql +++ b/pyfpdb/schema.postgres.sql @@ -137,6 +137,7 @@ CREATE TABLE HandsActions ( street SMALLINT, actionNo SMALLINT, action CHAR(5), + allIn BOOLEAN, amount INT, comment TEXT, commentTs timestamp without time zone); @@ -211,7 +212,7 @@ CREATE TABLE HudCache ( street4CheckCallRaiseChance INT, street4CheckCallRaiseDone INT); -INSERT INTO Settings VALUES (76); +INSERT INTO Settings VALUES (118); INSERT INTO Sites ("name", currency) VALUES ('Full Tilt Poker', 'USD'); INSERT INTO Sites ("name", currency) VALUES ('PokerStars', 'USD'); INSERT INTO TourneyTypes (buyin, fee, knockout, rebuyOrAddon) VALUES (0, 0, 0, FALSE); diff --git a/regression-test/PrintPlayerHudData.py b/regression-test/PrintPlayerHudData.py index 351472b1..5b4b0599 100755 --- a/regression-test/PrintPlayerHudData.py +++ b/regression-test/PrintPlayerHudData.py @@ -29,7 +29,7 @@ parser.add_option("-e", "--seats", default="7", type="int", help="number of acti parser.add_option("-g", "--gameType", default="ring", help="Whether its a ringgame (ring) or a tournament (tour)") parser.add_option("-l", "--limit", "--limitType", default="fl", help="Limit Type, one of: nl, pl, fl, cn, cp") parser.add_option("-n", "--name", "--playername", default="Player_1", help="Name of the player to print") -parser.add_option("-o", "--position", default="B", help="Position, can be B, S, or a number between 0 and 7") +parser.add_option("-o", "--position", default="B", help="Position, can be B, S, D, C, M or E (see tabledesign.html)") parser.add_option("-p", "--password", help="The password for the MySQL user") parser.add_option("-s", "--site", default="PokerStars", help="Name of the site (as written in the history files)") @@ -54,6 +54,7 @@ cursor.execute("SELECT id FROM Players WHERE name=%s", (options.name,)) playerId=cursor.fetchone()[0] cursor.execute("SELECT id FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats=%s AND position=%s",(gametypeId, playerId, options.seats, options.position)) +#print "debug: gametypeId:", gametypeId, "playerId:", playerId, "options.seats:", options.seats, "options.position:", options.position hudDataId=cursor.fetchone()[0] print "siteId:", siteId, "gametypeId:", gametypeId, "playerId:", playerId, "hudDataId:", hudDataId diff --git a/regression-test/ps-flags-B-1hands.expected.txt b/regression-test/ps-flags-B-1hands.expected.txt new file mode 100644 index 00000000..9b134e91 --- /dev/null +++ b/regression-test/ps-flags-B-1hands.expected.txt @@ -0,0 +1,68 @@ +Connected to MySQL on localhost. Print Player Flags Utility + +Basic Data +========== +bigblind: 2 category: holdem limitType: fl name: Player_5 gameType: ring site: PokerStars +siteId: 2 gametypeId: 1 playerId: 5 hudDataId: 12 + +HUD Raw Hand Counts +=================== +HDs: 1 +street0VPI: 0 +street0Aggr: 0 +street0_3B4BChance: 0 +street0_3B4BDone: 0 + +street1Seen: 1 +street2Seen: 1 +street3Seen: 1 +street4Seen: 0 +sawShowdown: 1 + +street1Aggr: 1 +street2Aggr: 1 +street3Aggr: 0 +street4Aggr: 0 + +otherRaisedStreet1: 0 +otherRaisedStreet2: 1 +otherRaisedStreet3: 1 +otherRaisedStreet4: 0 +foldToOtherRaisedStreet1: 0 +foldToOtherRaisedStreet2: 0 +foldToOtherRaisedStreet3: 0 +foldToOtherRaisedStreet4: 0 + +wonWhenSeenStreet1: 0 +wonAtSD: 0 +stealAttemptChance: 0 +stealAttempted: 0 +foldBbToStealChance: 0 +foldedBbToSteal: 0 +foldSbToStealChance: 0 +foldedSbToSteal: 0 +street1CBChance: 0 +street1CBDone: 0 +street2CBChance: 0 +street2CBDone: 0 +street3CBChance: 0 +street3CBDone: 0 +street4CBChance: 0 +street4CBDone: 0 +foldToStreet1CBChance: 0 +foldToStreet1CBDone: 0 +foldToStreet2CBChance: 0 +foldToStreet2CBDone: 0 +foldToStreet3CBChance: 0 +foldToStreet3CBDone: 0 +foldToStreet4CBChance: 0 +foldToStreet4CBDone: 0 +totalProfit: +street1CheckCallRaiseChance: +street1CheckCallRaiseDone: +street2CheckCallRaiseChance: +street2CheckCallRaiseDone: +street3CheckCallRaiseChance: +street3CheckCallRaiseDone: +street4CheckCallRaiseChance: 0 +street4CheckCallRaiseDone: 0 diff --git a/regression-test/ps-flags-CBflop.expected.txt b/regression-test/ps-flags-CBflop.expected.txt new file mode 100644 index 00000000..7fea235d --- /dev/null +++ b/regression-test/ps-flags-CBflop.expected.txt @@ -0,0 +1,68 @@ +Connected to MySQL on localhost. Print Player Flags Utility + +Basic Data +========== +bigblind: 25 category: holdem limitType: fl name: player3 gameType: ring site: PokerStars +siteId: 2 gametypeId: 2 playerId: 11 hudDataId: 22 + +HUD Raw Hand Counts +=================== +HDs: 1 +street0VPI: 1 +street0Aggr: 1 +street0_3B4BChance: 1 +street0_3B4BDone: 1 + +street1Seen: 1 +street2Seen: 1 +street3Seen: 1 +street4Seen: 0 +sawShowdown: 1 + +street1Aggr: 1 +street2Aggr: 0 +street3Aggr: 0 +street4Aggr: 0 + +otherRaisedStreet1: 0 +otherRaisedStreet2: +otherRaisedStreet3: +otherRaisedStreet4: 0 +foldToOtherRaisedStreet1: 0 +foldToOtherRaisedStreet2: 0 +foldToOtherRaisedStreet3: 0 +foldToOtherRaisedStreet4: 0 + +wonWhenSeenStreet1: 0.0 +wonAtSD: 0.0 +stealAttemptChance: 0 +stealAttempted: 0 +foldBbToStealChance: 0 +foldedBbToSteal: 0 +foldSbToStealChance: 0 +foldedSbToSteal: 0 +street1CBChance: 1 +street1CBDone: 1 +street2CBChance: 0 +street2CBDone: 0 +street3CBChance: 0 +street3CBDone: 0 +street4CBChance: 0 +street4CBDone: 0 +foldToStreet1CBChance: 0 +foldToStreet1CBDone: 0 +foldToStreet2CBChance: 0 +foldToStreet2CBDone: 0 +foldToStreet3CBChance: 0 +foldToStreet3CBDone: 0 +foldToStreet4CBChance: 0 +foldToStreet4CBDone: 0 +totalProfit: +street1CheckCallRaiseChance: 0 +street1CheckCallRaiseDone: 0 +street2CheckCallRaiseChance: 0 +street2CheckCallRaiseDone: 0 +street3CheckCallRaiseChance: 0 +street3CheckCallRaiseDone: 0 +street4CheckCallRaiseChance: 0 +street4CheckCallRaiseDone: 0 diff --git a/regression-test/ps-flags-M-2hands.expected.txt b/regression-test/ps-flags-M-2hands.expected.txt new file mode 100644 index 00000000..aa55e1c5 --- /dev/null +++ b/regression-test/ps-flags-M-2hands.expected.txt @@ -0,0 +1,68 @@ +Connected to MySQL on localhost. Print Player Flags Utility + +Basic Data +========== +bigblind: 2 category: holdem limitType: fl name: Player_1 gameType: ring site: PokerStars +siteId: 2 gametypeId: 1 playerId: 1 hudDataId: 8 + +HUD Raw Hand Counts +=================== +HDs: 2 +street0VPI: 0 +street0Aggr: 0 +street0_3B4BChance: 0 +street0_3B4BDone: 0 + +street1Seen: 0 +street2Seen: 0 +street3Seen: 0 +street4Seen: 0 +sawShowdown: 0 + +street1Aggr: 0 +street2Aggr: 0 +street3Aggr: 0 +street4Aggr: 0 + +otherRaisedStreet1: 0 +otherRaisedStreet2: 0 +otherRaisedStreet3: 0 +otherRaisedStreet4: 0 +foldToOtherRaisedStreet1: 0 +foldToOtherRaisedStreet2: 0 +foldToOtherRaisedStreet3: 0 +foldToOtherRaisedStreet4: 0 + +wonWhenSeenStreet1: 0.0 +wonAtSD: 0.0 +stealAttemptChance: 0 +stealAttempted: 0 +foldBbToStealChance: 0 +foldedBbToSteal: 0 +foldSbToStealChance: 0 +foldedSbToSteal: 0 +street1CBChance: 0 +street1CBDone: 0 +street2CBChance: 0 +street2CBDone: 0 +street3CBChance: 0 +street3CBDone: 0 +street4CBChance: 0 +street4CBDone: 0 +foldToStreet1CBChance: 0 +foldToStreet1CBDone: 0 +foldToStreet2CBChance: 0 +foldToStreet2CBDone: 0 +foldToStreet3CBChance: 0 +foldToStreet3CBDone: 0 +foldToStreet4CBChance: 0 +foldToStreet4CBDone: 0 +totalProfit: 0 +street1CheckCallRaiseChance: 0 +street1CheckCallRaiseDone: 0 +street2CheckCallRaiseChance: 0 +street2CheckCallRaiseDone: 0 +street3CheckCallRaiseChance: 0 +street3CheckCallRaiseDone: 0 +street4CheckCallRaiseChance: 0 +street4CheckCallRaiseDone: 0 diff --git a/regression-test/regression-test.sh b/regression-test/regression-test.sh index 5e0cfb9d..5bf93149 100755 --- a/regression-test/regression-test.sh +++ b/regression-test/regression-test.sh @@ -30,7 +30,13 @@ echo "it should've reported first that it stored 3, then that it had 3 duplicate ./PrintHand.py -p$1 --hand=14519420999 > ps.14519420999.found.txt && colordiff ps.14519420999.found.txt ps.14519420999.expected.txt ./PrintHand.py -p$1 --hand=14519433154 > ps.14519433154.found.txt && colordiff ps.14519433154.found.txt ps.14519433154.expected.txt -./PrintPlayerHudData.py -p$1 > ps-flags-3hands.found.txt && colordiff ps-flags-3hands.found.txt ps-flags-3hands.expected.txt +./PrintPlayerHudData.py -p$1 -oM > ps-flags-M-2hands.found.txt && colordiff ps-flags-M-2hands.found.txt ps-flags-M-2hands.expected.txt +./PrintPlayerHudData.py -p$1 -nPlayer_5 -oB > ps-flags-B-1hands.found.txt && colordiff ps-flags-B-1hands.found.txt ps-flags-B-1hands.expected.txt + + +../pyfpdb/fpdb_import.py -p$1 --file=ps-lhe-ring-call-3B-preflop-cb-no2b.txt -x +echo "it should've now reported another successful store of 1 hand" +./PrintPlayerHudData.py -p$1 -nplayer3 -oE -e10 -b25 > ps-flags-CBflop.found.txt && colordiff ps-flags-CBflop.found.txt ps-flags-CBflop.expected.txt #./print_hand.py -p$1 --site="Full Tilt Poker" --hand=6367428246 > ftp.6367428246.found.txt && colordiff ftp.6367428246.found.txt ftp.6367428246.expected.txt