diff --git a/pyfpdb/Card.py b/pyfpdb/Card.py index 75c742f9..ab6843c5 100755 --- a/pyfpdb/Card.py +++ b/pyfpdb/Card.py @@ -57,6 +57,21 @@ def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4): #AAKKs #AAKKr # Is probably what we are looking for + + # mct: + # my maths says there are 4 classes of suitedness + # SSSS SSSx SSxy SSHH + # encode them as follows: + # SSSS (K, J, 6, 3) + # - 13C4 = 715 possibilities + # SSSx (K, J, 6),(3) + # - 13C3 * 13 = 3718 possibilities + # SSxy (K, J),(6),(3) + # - 13C2 * 13*13 = 13182 possibilities + # SSHH (K, J),(6, 3) + # - 13C2 * 13C2 = 6084 possibilities + # Needless to say they won't fit on a 13x13 grid. + # The actual number of hands in each class is far greater return(0) def cardFromValueSuit(value, suit): @@ -70,7 +85,7 @@ def cardFromValueSuit(value, suit): def valueSuitFromCard(card): """ Function to convert a card stored in the database (int 0-52) into value and suit like 9s, 4c etc """ - if card < 0 or card > 52: + if card < 0 or card > 52 or not card: return('') else: return( ['', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', 'Th', 'Jh', 'Qh', 'Kh', 'Ah' diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 1d93f3f1..0ea4b371 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -250,6 +250,7 @@ class Config: self.default_config_path = self.get_default_config_path() if file != None: # configuration file path has been passed + file = os.path.expanduser(file) if not os.path.exists(file): print "Configuration file %s not found. Using defaults." % (file) sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py old mode 100644 new mode 100755 index e5fbda6d..932a8578 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -33,6 +33,7 @@ import string # FreePokerTools modules import fpdb_db +import fpdb_simple import Configuration import SQL import Card @@ -44,8 +45,10 @@ class Database: self.connection = self.fdb.db db_params = c.get_db_parameters() + self.import_options = c.get_import_parameters() self.type = db_params['db-type'] - self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-backend']) + self.backend = db_params['db-backend'] + self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) self.connection.rollback() # To add to config: @@ -76,6 +79,11 @@ class Database: self.hand_nhands_ago = 0 # todo #cur.execute(self.sql.query['get_table_name'], (hand_id, )) #row = cur.fetchone() + self.saveActions = False if self.import_options['saveActions'] == False else True + + + def commit(self): + self.fdb.db.commit() def close_connection(self): self.connection.close() @@ -116,21 +124,13 @@ class Database: def get_cards(self, hand): """Get and return the cards for each player in the hand.""" - cards = {} # dict of cards, the key is the seat number example: {1: 'AcQd9hTs5d'} + cards = {} # dict of cards, the key is the seat number, + # the value is a tuple of the players cards + # example: {1: (0, 0, 20, 21, 22, 0 , 0)} c = self.connection.cursor() c.execute(self.sql.query['get_cards'], [hand]) - colnames = [desc[0] for desc in c.description] - cardnames = ['card1', 'card2', 'card3', 'card4', 'card5', 'card6', 'card7'] for row in c.fetchall(): - cs = ['', '', '', '', '', '', ''] - seat = -1 - for col,name in enumerate(colnames): - if name in cardnames: - cs[cardnames.index(name)] = Card.valueSuitFromCard(row[col]) - elif name == 'seat_number': - seat = row[col] - if seat != -1: - cards[seat] = ''.join(cs) + cards[row[0]] = row[1:] return cards def get_common_cards(self, hand): @@ -272,6 +272,129 @@ class Database: else: return None + def get_last_insert_id(self): + return self.fdb.getLastInsertId() + + + #stores a stud/razz hand into the database + def ring_stud(self, config, settings, db, 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(self.backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats, hudImportData) + + #print "before calling store_hands_players_stud, antes:", antes + hands_players_ids = fpdb_simple.store_hands_players_stud(self.backend, db, cursor, hands_id, player_ids + ,start_cashes, antes, card_values + ,card_suits, winnings, rakes, seatNos) + + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + + if self.saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, action_types + ,allIns, action_amounts, actionNos) + return hands_id + #end def ring_stud + + def ring_holdem_omaha(self, config, settings, db, 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""" + + t0 = time() + fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) + t1 = time() + fpdb_simple.fill_board_cards(board_values, board_suits) + t2 = time() + + hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats, + hudImportData, board_values, board_suits) + #TEMPORARY CALL! - Just until all functions are migrated + t3 = time() + hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( + self.backend, db, cursor, category, hands_id, player_ids, start_cashes + , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) + t4 = time() + #print "ring holdem, backend=%d" % backend + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + t5 = time() + fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) + t6 = time() + if self.saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) + t7 = time() + #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4, t6-t5) + return hands_id + #end def ring_holdem_omaha + + def tourney_holdem_omaha(self, config, settings, db, 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, 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) + + tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) + tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) + + hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id + ,hand_start_time, names, tableName, maxSeats) + + hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha_tourney( + self.backend, db, cursor, category, hands_id, player_ids, start_cashes, positions + , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) + + #print "tourney holdem, backend=%d" % backend + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) + + fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) + + if self.saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) + return hands_id + #end def tourney_holdem_omaha + + def tourney_stud(self, config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries + ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId + ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes + ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts + ,actionNos, hudImportData, maxSeats, tableName, seatNos): + #stores a tourney stud/razz hand into the database + + fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) + + tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) + + tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) + + hands_id = fpdb_simple.storeHands(self.backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) + + hands_players_ids = fpdb_simple.store_hands_players_stud_tourney(self.backend, db, cursor, hands_id + , playerIds, startCashes, antes, cardValues, cardSuits + , winnings, rakes, seatNos, tourneys_players_ids) + + if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': + fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) + + if self.saveActions: + fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) + return hands_id + #end def tourney_stud + if __name__=="__main__": c = Configuration.Config() diff --git a/pyfpdb/FpdbRegex.py b/pyfpdb/FpdbRegex.py deleted file mode 100644 index 8bfb9362..00000000 --- a/pyfpdb/FpdbRegex.py +++ /dev/null @@ -1,161 +0,0 @@ -# pokerstars_cash.py -# -*- coding: iso-8859-15 -# -# PokerStats, an online poker statistics tracking software for Linux -# Copyright (C) 2007-2008 Mika Boström -# -# 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, version 3 of the License. -# - -# Modified for use in fpdb by Carl Gherardi - -import re - -# These are PokerStars specific; -# More importantly, they are currently valid for cash game only. -##### -# XXX: There was a weird problem with saved hand histories in PokerStars -# client 2.491; if a user was present on the table (and thus anywhere in -# the hand history), with non-standard characters in their username, the -# client would prepend a literal Ctrl-P (ASCII 16, 0x10) character to -# the hand history title line. Hence, to allow these strangely saved -# hands to be parsed and imported, there is a conditional "one extra -# character" allowed at the start of the new hand regex. - - -class FpdbRegex: - def __init__(self): - self.__GAME_INFO_REGEX='' - self.__SPLIT_HAND_REGEX='\n\n\n' - self.__NEW_HAND_REGEX='^.?PokerStars Game #\d+:\s+Hold\'em' - self.__HAND_INFO_REGEX='^.*#(\d+):\s+(\S+)\s([\s\S]+)\s\(\$?([.0-9]+)/\$?([.0-9]+)\)\s-\s(\S+)\s-?\s?(\S+)\s\(?(\w+)\)?' - self.__TABLE_INFO_REGEX='^\S+\s+\'.*\'\s+(\d+)-max\s+Seat\s#(\d+)' - self.__PLAYER_INFO_REGEX='^Seat\s(\d+):\s(.*)\s\(\$?([.\d]+)\s' - self.__POST_SB_REGEX='^(.*):\sposts small blind' - self.__POST_BB_REGEX='^(.*):\sposts big blind' - self.__POST_BOTH_REGEX='^(.*):\sposts small & big blinds' - self.__HAND_STAGE_REGEX='^\*{3}\s(.*)\s\*{3}' - self.__HOLE_CARD_REGEX='^\*{3}\sHOLE CARDS' - self.__FLOP_CARD_REGEX='^\*{3}\sFLOP\s\*{3}\s\[(\S{2})\s(\S{2})\s(\S{2})\]' - self.__TURN_CARD_REGEX='^\*{3}\sTURN\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' - self.__RIVER_CARD_REGEX='^\*{3}\sRIVER\s\*{3}\s\[\S{2}\s\S{2}\s\S{2}\s\S{2}\]\s\[(\S{2})\]' - self.__SHOWDOWN_REGEX='^\*{3}\sSHOW DOWN' - self.__SUMMARY_REGEX='^\*{3}\sSUMMARY' - self.__UNCALLED_BET_REGEX='^Uncalled bet \(\$([.\d]+)\) returned to (.*)' - self.__POT_AND_RAKE_REGEX='^Total\spot\s\$([.\d]+).*\|\sRake\s\$([.\d]+)' - self.__COLLECT_POT_REGEX='^(.*)\scollected\s\$([.\d]+)\sfrom\s((main|side)\s)?pot' - self.__HERO_CARDS_REGEX='^Dealt\sto\s(.*)\s\[(\S{2})\s(\S{2})\]' - self.__SHOWN_CARDS_REGEX='^(.*):\sshows\s\[(\S{2})\s(\S{2})\]' - self.__ACTION_STEP_REGEX='^(.*):\s(bets|checks|raises|calls|folds)((\s\$([.\d]+))?(\sto\s\$([.\d]+))?)?' - - self.__SHOWDOWN_ACTION_REGEX='^(.*):\s(shows|mucks)' - self.__SUMMARY_CARDS_REGEX='^Seat\s\d+:\s(.*)\s(showed|mucked)\s\[(\S{2})\s(\S{2})\]' - self.__SUMMARY_CARDS_EXTRA_REGEX='^Seat\s\d+:\s(.*)\s(\(.*\)\s)(showed|mucked)\s\[(\S{2})\s(\S{2})\]' - - def compileRegexes(self): - ### Compile the regexes - self.game_info_re = re.compile(self.__GAME_INFO_REGEX) - self.split_hand_re = re.compile(self.__SPLIT_HAND_REGEX) - self.hand_start_re = re.compile(self.__NEW_HAND_REGEX) - self.hand_info_re = re.compile(self.__HAND_INFO_REGEX) - self.table_info_re = re.compile(self.__TABLE_INFO_REGEX) - self.player_info_re = re.compile(self.__PLAYER_INFO_REGEX) - self.small_blind_re = re.compile(self.__POST_SB_REGEX) - self.big_blind_re = re.compile(self.__POST_BB_REGEX) - self.both_blinds_re = re.compile(self.__POST_BOTH_REGEX) - self.hand_stage_re = re.compile(self.__HAND_STAGE_REGEX) - self.hole_cards_re = re.compile(self.__HOLE_CARD_REGEX) - self.flop_cards_re = re.compile(self.__FLOP_CARD_REGEX) - self.turn_card_re = re.compile(self.__TURN_CARD_REGEX) - self.river_card_re = re.compile(self.__RIVER_CARD_REGEX) - self.showdown_re = re.compile(self.__SHOWDOWN_REGEX) - self.summary_re = re.compile(self.__SUMMARY_REGEX) - self.uncalled_bet_re = re.compile(self.__UNCALLED_BET_REGEX) - self.collect_pot_re = re.compile(self.__COLLECT_POT_REGEX) - self.hero_cards_re = re.compile(self.__HERO_CARDS_REGEX) - self.cards_shown_re = re.compile(self.__SHOWN_CARDS_REGEX) - self.summary_cards_re = re.compile(self.__SUMMARY_CARDS_REGEX) - self.summary_cards_extra_re = re.compile(self.__SUMMARY_CARDS_EXTRA_REGEX) - self.action_re = re.compile(self.__ACTION_STEP_REGEX) - self.rake_re = re.compile(self.__POT_AND_RAKE_REGEX) - self.showdown_action_re = re.compile(self.__SHOWDOWN_ACTION_REGEX) - - # Set methods for plugins to override - - def setGameInfoRegex(self, string): - self.__GAME_INFO_REGEX = string - - def setSplitHandRegex(self, string): - self.__SPLIT_HAND_REGEX = string - - def setNewHandRegex(self, string): - self.__NEW_HAND_REGEX = string - - def setHandInfoRegex(self, string): - self.__HAND_INFO_REGEX = string - - def setTableInfoRegex(self, string): - self.__TABLE_INFO_REGEX = string - - def setPlayerInfoRegex(self, string): - self.__PLAYER_INFO_REGEX = string - - def setPostSbRegex(self, string): - self.__POST_SB_REGEX = string - - def setPostBbRegex(self, string): - self.__POST_BB_REGEX = string - - def setPostBothRegex(self, string): - self.__POST_BOTH_REGEX = string - - def setHandStageRegex(self, string): - self.__HAND_STAGE_REGEX = string - - def setHoleCardRegex(self, string): - self.__HOLE_CARD_REGEX = string - - def setFlopCardRegex(self, string): - self.__FLOP_CARD_REGEX = string - - def setTurnCardRegex(self, string): - self.__TURN_CARD_REGEX = string - - def setRiverCardRegex(self, string): - self.__RIVER_CARD_REGEX = string - - def setShowdownRegex(self, string): - self.__SHOWDOWN_REGEX = string - - def setSummaryRegex(self, string): - self.__SUMMARY_REGEX = string - - def setUncalledBetRegex(self, string): - self.__UNCALLED_BET_REGEX = string - - def setCollectPotRegex(self, string): - self.__COLLECT_POT_REGEX = string - - def setHeroCardsRegex(self, string): - self.__HERO_CARDS_REGEX = string - - def setShownCardsRegex(self, string): - self.__SHOWN_CARDS_REGEX = string - - def setSummaryCardsRegex(self, string): - self.__SUMMARY_CARDS_REGEX = string - - def setSummaryCardsExtraRegex(self, string): - self.__SUMMARY_CARDS_EXTRA_REGEX = string - - def setActionStepRegex(self, string): - self.__ACTION_STEP_REGEX = string - - def setPotAndRakeRegex(self, string): - self.__POT_AND_RAKE_REGEX = string - - def setShowdownActionRegex(self, string): - self.__SHOWDOWN_ACTION_REGEX = string - diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 2b4c8b76..fb278f17 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -28,6 +28,7 @@ import time import fpdb_import from optparse import OptionParser import Configuration +import string class GuiAutoImport (threading.Thread): def __init__(self, settings, config): @@ -157,21 +158,15 @@ class GuiAutoImport (threading.Thread): widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: if os.name == 'nt': - command = "python HUD_main.py" + " %s" % (self.database) + command = "python HUD_main.py" + " " + self.settings['cl_options'] bs = 0 # windows is not happy with line buffing here self.pipe_to_hud = subprocess.Popen(command, bufsize = bs, stdin = subprocess.PIPE, universal_newlines=True) else: command = os.path.join(sys.path[0], 'HUD_main.py') - #command = self.config.execution_path('HUD_main.py') # Hi Ray. Sorry about this, kludging. - bs = 1 - self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, + cl = [command, ] + string.split(self.settings['cl_options']) + self.pipe_to_hud = subprocess.Popen(cl, bufsize = 1, stdin = subprocess.PIPE, universal_newlines=True) - # self.pipe_to_hud = subprocess.Popen((command, self.database), bufsize = bs, stdin = subprocess.PIPE, - # universal_newlines=True) - # command = command + " %s" % (self.database) - # print "command = ", command - # self.pipe_to_hud = os.popen(command, 'w') # Add directories to importer object. for site in self.input_settings: diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 64cafaf8..218707bd 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -29,12 +29,16 @@ Main for FreePokerTools HUD. # Standard Library modules import sys - -# redirect the stderr -errorfile = open('HUD-error.txt', 'w', 0) -sys.stderr = errorfile - import os +import Options + +(options, sys.argv) = Options.fpdb_options() + +if not options.errorsToConsole: + 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 thread import time import string @@ -59,7 +63,7 @@ class HUD_main(object): def __init__(self, db_name = 'fpdb'): self.db_name = db_name - self.config = Configuration.Config() + self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.hud_dict = {} # a thread to read stdin @@ -198,17 +202,12 @@ class HUD_main(object): self.db_connection.connection.rollback() if __name__== "__main__": - sys.stderr.write("HUD_main starting\n") -# database name can be passed on command line - try: - db_name = sys.argv[1] - except: - db_name = 'fpdb' - sys.stderr.write("Using db name = %s\n" % (db_name)) + sys.stderr.write("HUD_main starting\n") + sys.stderr.write("Using db name = %s\n" % (options.dbname)) # start the HUD_main object - hm = HUD_main(db_name = db_name) + hm = HUD_main(db_name = options.dbname) # start the event loop gtk.main() diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index c505a68a..38c3609b 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -39,15 +39,14 @@ class Hand: self.starttime = 0 self.handText = handText self.handid = 0 - self.tablename = "Slartibartfast" - self.hero = "Hiro" + self.tablename = "" + self.hero = "" self.maxseats = 10 self.counted_seats = 0 self.buttonpos = 0 self.seating = [] self.players = [] self.posted = [] - self.involved = True # Collections indexed by street names self.bets = {} @@ -55,23 +54,26 @@ class Hand: self.streets = {} self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']] self.board = {} # dict from street names to community cards - for street in self.streetList: + self.holecards = {} + for street in self.allStreets: self.streets[street] = "" # portions of the handText, filled by markStreets() self.bets[street] = {} self.lastBet[street] = 0 self.actions[street] = [] self.board[street] = [] + self.holecards[street] = {} # dict from player names to holecards # Collections indexed by player names - self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards +# self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards self.stacks = {} self.collected = [] #list of ? self.collectees = {} # dict from player names to amounts collected (?) # Sets of players - self.shown = set() self.folded = set() + self.dealt = set() # 'dealt to' line to be printed + self.shown = set() # cards were shown # self.action = [] # Things to do with money @@ -80,6 +82,10 @@ class Hand: self.totalcollected = None self.rake = None + def __str__(self): + str = '' + str = str + "Hand Object for %s at %s" % (self.handid, self.sitename) + return str def insert(self, db): """ Function to insert Hand into database @@ -90,7 +96,7 @@ db: a connected fpdb_db object""" sqlids = db.getSqlPlayerIDs([p[1] for p in self.players], self.siteId) # HudCache data to come from DerivedStats class # HandsActions - all actions for all players for all streets - self.actions - # BoardCards - Skip - no longer necessary? + # BoardCards - Skip - no longer necessary # Hands - Summary information of hand indexed by handId - gameinfo #hh['siteHandNo'] = self.handid # gametypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (gametypeId) REFERENCES Gametypes(id), @@ -105,6 +111,14 @@ db: a connected fpdb_db object""" # boardcard3 smallint, # boardcard4 smallint, # boardcard5 smallint, + # Flop turn and river may all be empty - add (likely) too many elements and trim with range + # boardcards = board['FLOP'] + board['TURN'] + board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x'] + # cards = [Card.cardFromValueSuit(v,s) for v,s in boardcards[0:4]] + # hh['boardcard1'] = cards[0] + # hh['boardcard2'] = cards[1] + # hh['boardcard3'] = cards[2] + # hh['boardcard4'] = cards[3] + # hh['boardcard5'] = cards[4] # texture smallint, # playersVpi SMALLINT NOT NULL, /* num of players vpi */ # Needs to be recorded @@ -163,12 +177,10 @@ If a player has None chips he won't be added.""" if chips is not None: self.players.append([seat, name, chips]) self.stacks[name] = Decimal(chips) - self.holecards[name] = [] - self.discards[name] = [] self.pot.addPlayer(name) - for street in self.streetList: + for street in self.allStreets: self.bets[street][name] = [] - self.holecards[name] = {} # dict from street names. + #self.holecards[name] = {} # dict from street names. self.discards[name] = {} # dict from street names. @@ -190,6 +202,7 @@ If a player has None chips he won't be added.""" def setCommunityCards(self, street, cards): logging.debug("setCommunityCards %s %s" %(street, cards)) self.board[street] = [self.card(c) for c in cards] + print "DEBUG: self.board: %s" % self.board def card(self,c): """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" @@ -382,7 +395,7 @@ Map the tuple self.gametype onto the pokerstars string describing it "omahahilo" : "Omaha Hi/Lo", "razz" : "Razz", "studhi" : "7 Card Stud", - "studhilo" : "FIXME", + "studhilo" : "7 Card Stud Hi/Lo", "fivedraw" : "5 Card Draw", "27_1draw" : "FIXME", "27_3draw" : "Triple Draw 2-7 Lowball", @@ -407,32 +420,32 @@ Map the tuple self.gametype onto the pokerstars string describing it def printHand(self): self.writeHand(sys.stdout) - def printActionLine(self, act, fh): + def actionString(self, act): if act[1] == 'folds': - print >>fh, ("%s: folds " %(act[0])) + return ("%s: folds " %(act[0])) elif act[1] == 'checks': - print >>fh, ("%s: checks " %(act[0])) + return ("%s: checks " %(act[0])) elif act[1] == 'calls': - print >>fh, ("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: calls $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'bets': - print >>fh, ("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: bets $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'raises': - print >>fh, ("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else '')) + return ("%s: raises $%s to $%s%s" %(act[0], act[2], act[3], ' and is all-in' if act[5] else '')) elif act[1] == 'completea': - print >>fh, ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: completes to $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'posts': if(act[2] == "small blind"): - print >>fh, ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "big blind"): - print >>fh, ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts big blind $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif(act[2] == "both"): - print >>fh, ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) + return ("%s: posts small & big blinds $%s%s" %(act[0], act[3], ' and is all-in' if act[4] else '')) elif act[1] == 'bringin': - print >>fh, ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) + return ("%s: brings in for $%s%s" %(act[0], act[2], ' and is all-in' if act[3] else '')) elif act[1] == 'discards': - print >>fh, ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else '')) + return ("%s: discards %s %s%s" %(act[0], act[2], 'card' if act[2] == 1 else 'cards' , " [" + " ".join(self.discards[act[0]]['DRAWONE']) + "]" if self.hero == act[0] else '')) elif act[1] == 'stands pat': - print >>fh, ("%s: stands pat" %(act[0])) + return ("%s: stands pat" %(act[0])) class HoldemOmahaHand(Hand): @@ -440,9 +453,10 @@ class HoldemOmahaHand(Hand): if gametype['base'] != 'hold': pass # or indeed don't pass and complain instead logging.debug("HoldemOmahaHand") - self.streetList = ['BLINDSANTES', 'DEAL', 'PREFLOP','FLOP','TURN','RIVER'] # a list of the observed street names in order + self.allStreets = ['BLINDSANTES', 'PREFLOP','FLOP','TURN','RIVER'] + self.holeStreets = ['PREFLOP'] self.communityStreets = ['FLOP', 'TURN', 'RIVER'] - self.actionStreets = ['PREFLOP','FLOP','TURN','RIVER'] + self.actionStreets = ['BLINDSANTES','PREFLOP','FLOP','TURN','RIVER'] Hand.__init__(self, sitename, gametype, handText, builtFrom = "HHC") self.sb = gametype['sb'] self.bb = gametype['bb'] @@ -480,24 +494,32 @@ class HoldemOmahaHand(Hand): pass - def addHoleCards(self, cards, player, shown=False): + def addHoleCards(self, cards, player, shown=False, dealt=False): """\ Assigns observed holecards to a player. cards list of card bigrams e.g. ['2h','Jc'] player (string) name of player +shown whether they were revealed at showdown +dealt whether they were seen in a 'dealt to' line """ logging.debug("addHoleCards %s %s" % (cards, player)) try: self.checkPlayerExists(player) - cardset = set(self.card(c) for c in cards) - if shown and len(cardset) > 0: - self.shown.add(player) - if 'PREFLOP' in self.holecards[player]: - self.holecards[player]['PREFLOP'].update(cardset) - else: - self.holecards[player]['PREFLOP'] = cardset except FpdbParseError, e: print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) + return + + cardset = set((self.card(c) for c in cards)) + if len(cardset) == 0: + return + if dealt: + self.dealt.add(player) + if shown: + self.shown.add(player) + if player in self.holecards['PREFLOP']: + self.holecards['PREFLOP'][player].update(cardset) + else: + self.holecards['PREFLOP'][player] = cardset def addShownCards(self, cards, player, holeandboard=None): """\ @@ -506,14 +528,108 @@ Card ranks will be uppercased """ logging.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard)) if cards is not None: - self.shown.add(player) - self.addHoleCards(cards,player) + self.addHoleCards(cards,player,shown=True) elif holeandboard is not None: holeandboard = set([self.card(c) for c in holeandboard]) board = set([c for s in self.board.values() for c in s]) self.addHoleCards(holeandboard.difference(board),player,shown=True) + def writeHTMLHand(self, fh=sys.__stdout__): + from nevow import tags as T + from nevow import flat + players_who_act_preflop = (([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) + players_stacks = [x for x in self.players if x[1] in players_who_act_preflop] + action_streets = [x for x in self.actionStreets if len(self.actions[x]) > 0] + def render_stack(context,data): + pat = context.tag.patternGenerator('list_item') + for player in data: + x = "Seat %s: %s ($%s in chips) " %(player[0], player[1], + player[2]) + context.tag[ pat().fillSlots('playerStack', x)] + return context.tag + + def render_street(context,data): + pat = context.tag.patternGenerator('list_item') + for street in data: + lines = [] + if street in self.holeStreets and self.holecards[street]: + lines.append( + T.ol(class_='dealclosed', data=street, + render=render_deal) [ + T.li(pattern='list_item')[ T.slot(name='deal') ] + ] + ) + if street in self.communityStreets and self.board[street]: + lines.append( + T.ol(class_='community', data=street, + render=render_deal_community)[ + T.li(pattern='list_item')[ T.slot(name='deal') ] + ] + ) + if street in self.actionStreets and self.actions[street]: + lines.append( + T.ol(class_='actions', data=self.actions[street], render=render_action) [ + T.li(pattern='list_item')[ T.slot(name='action') ] + ] + ) + if lines: + context.tag[ pat().fillSlots('street', [ T.h3[ street ] ]+lines)] + return context.tag + + def render_deal(context,data): + # data is streetname +# we can have open+closed, or just open, or just closed. + + if self.holecards[data]: + for player in self.holecards[data]: + somestuff = 'dealt to %s %s' % (player, self.holecards[data][player]) + pat = context.tag.patternGenerator('list_item') + context.tag[ pat().fillSlots('deal', somestuff)] + return context.tag + + def render_deal_community(context,data): + # data is streetname + if self.board[data]: + somestuff = '[' + ' '.join(self.board[data]) + ']' + pat = context.tag.patternGenerator('list_item') + context.tag[ pat().fillSlots('deal', somestuff)] + return context.tag + def render_action(context,data): + pat = context.tag.patternGenerator('list_item') + for act in data: + x = self.actionString(act) + context.tag[ pat().fillSlots('action', x)] + return context.tag + + s = T.p[ + T.h1[ + T.span(class_='site')["%s Game #%s]" % ('PokerStars', self.handid)], + T.span(class_='type_limit')[ "%s ($%s/$%s)" %(self.getGameTypeAsString(), self.sb, self.bb) ], + T.span(class_='date')[ datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET') ] + ], + T.h2[ "Table '%s' %d-max Seat #%s is the button" %(self.tablename, + self.maxseats, self.buttonpos)], + T.ol(class_='stacks', data = players_stacks, render=render_stack)[ + T.li(pattern='list_item')[ T.slot(name='playerStack') ] + ], + T.ol(class_='streets', data = self.allStreets, + render=render_street)[ + T.li(pattern='list_item')[ T.slot(name='street')] + ] + ] + import tidy + + options = dict(input_xml=True, + output_xhtml=True, + add_xml_decl=False, + doctype='omit', + indent='auto', + tidy_mark=False) + + return str(tidy.parseString(flat.flatten(s), **options)) + + def writeHand(self, fh=sys.__stdout__): # PokerStars format. print >>fh, ("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) @@ -527,33 +643,36 @@ Card ranks will be uppercased if self.actions['BLINDSANTES']: for act in self.actions['BLINDSANTES']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) print >>fh, ("*** HOLE CARDS ***") - if self.involved: - print >>fh, ("Dealt to %s [%s]" %(self.hero , " ".join(self.holecards[self.hero]['PREFLOP']))) + for player in self.dealt: + print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) + if self.hero == "": + for player in self.shown.difference(self.dealt): + print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) if self.actions['PREFLOP']: for act in self.actions['PREFLOP']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if self.board['FLOP']: print >>fh, ("*** FLOP *** [%s]" %( " ".join(self.board['FLOP']))) if self.actions['FLOP']: for act in self.actions['FLOP']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if self.board['TURN']: print >>fh, ("*** TURN *** [%s] [%s]" %( " ".join(self.board['FLOP']), " ".join(self.board['TURN']))) if self.actions['TURN']: for act in self.actions['TURN']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if self.board['RIVER']: print >>fh, ("*** RIVER *** [%s] [%s]" %(" ".join(self.board['FLOP']+self.board['TURN']), " ".join(self.board['RIVER']) )) if self.actions['RIVER']: for act in self.actions['RIVER']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) #Some sites don't have a showdown section so we have to figure out if there should be one @@ -569,8 +688,8 @@ Card ranks will be uppercased numOfHoleCardsNeeded = 4 elif self.gametype['category'] in ('holdem'): numOfHoleCardsNeeded = 2 - if len(self.holecards[name]['PREFLOP']) == numOfHoleCardsNeeded: - print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards[name]['PREFLOP']))) + if len(self.holecards['PREFLOP'][name]) == numOfHoleCardsNeeded: + print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name]))) # Current PS format has the lines: # Uncalled bet ($111.25) returned to s0rrow @@ -597,7 +716,7 @@ Card ranks will be uppercased seatnum = player[0] name = player[1] if name in self.collectees and name in self.shown: - print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']), self.collectees[name])) + print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]), self.collectees[name])) elif name in self.collectees: print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) #~ elif name in self.shown: @@ -606,7 +725,7 @@ Card ranks will be uppercased print >>fh, ("Seat %d: %s folded" % (seatnum, name)) else: if name in self.shown: - print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards[name]['PREFLOP']))) + print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]))) else: print >>fh, ("Seat %d: %s mucked" % (seatnum, name)) @@ -739,12 +858,12 @@ Card ranks will be uppercased (nc,oc) = self.holecards[player]['DEAL'] print >>fh, _("Dealt to %s: [%s]") % (player, " ".join(nc)) for act in self.actions['DEAL']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'DRAWONE' in self.actions: print >>fh, _("*** FIRST DRAW ***") for act in self.actions['DRAWONE']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': (nc,oc) = self.holecards[act[0]]['DRAWONE'] dc = self.discards[act[0]]['DRAWONE'] @@ -754,7 +873,7 @@ Card ranks will be uppercased if 'DRAWTWO' in self.actions: print >>fh, _("*** SECOND DRAW ***") for act in self.actions['DRAWTWO']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': (nc,oc) = self.holecards[act[0]]['DRAWTWO'] dc = self.discards[act[0]]['DRAWTWO'] @@ -764,7 +883,7 @@ Card ranks will be uppercased if 'DRAWTHREE' in self.actions: print >>fh, _("*** THIRD DRAW ***") for act in self.actions['DRAWTHREE']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if act[0] == self.hero and act[1] == 'discards': (nc,oc) = self.holecards[act[0]]['DRAWTHREE'] dc = self.discards[act[0]]['DRAWTHREE'] @@ -878,7 +997,8 @@ Add a complete on [street] by [player] to [amountTo] def writeHand(self, fh=sys.__stdout__): # PokerStars format. - print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) +# print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) + print >>fh, _("%s Game #%s: %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) @@ -903,7 +1023,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(closed) + "] " if closed else " ", "[" + " ".join(open) + "]" if open else "") for act in self.actions['THIRD']: #FIXME: Need some logic here for bringin vs completes - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'FOURTH' in self.actions: dealt = 0 @@ -920,7 +1040,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** 4TH STREET ***") print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['FOURTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'FIFTH' in self.actions: dealt = 0 @@ -938,7 +1058,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** 5TH STREET ***") print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['FIFTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'SIXTH' in self.actions: dealt = 0 @@ -956,7 +1076,7 @@ Add a complete on [street] by [player] to [amountTo] print >>fh, _("*** 6TH STREET ***") print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['SIXTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) if 'SEVENTH' in self.actions: # OK. It's possible that they're all in at an earlier street, but only closed cards are dealt. @@ -975,7 +1095,7 @@ Add a complete on [street] by [player] to [amountTo] if new: print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") for act in self.actions['SEVENTH']: - self.printActionLine(act, fh) + print >>fh, self.actionString(act) #Some sites don't have a showdown section so we have to figure out if there should be one # The logic for a showdown is: at the end of river action there are at least two players in the hand @@ -1106,7 +1226,8 @@ class Pot(object): def assemble(cnxn, handid): c = cnxn.cursor() - # We need the following for the Hand.__init__ + # We need at least sitename, gametype, handid + # for the Hand.__init__ c.execute(""" select s.name, @@ -1115,27 +1236,24 @@ select g.type, g.limitType, g.hilo, - g.smallBlind / 100.0, - g.bigBlind / 100.0 , - g.smallBet / 100.0, - g.bigBet / 100.0, + round(g.smallBlind / 100.0,2), + round(g.bigBlind / 100.0,2), + round(g.smallBet / 100.0,2), + round(g.bigBet / 100.0,2), s.currency, - bc.card1value, - bc.card1suit, - bc.card2value,bc.card2suit, - bc.card3value,bc.card3suit, - bc.card4value,bc.card4suit, - bc.card5value,bc.card5suit + h.boardcard1, + h.boardcard2, + h.boardcard3, + h.boardcard4, + h.boardcard5 from hands as h, - boardcards as bc, sites as s, gametypes as g, handsplayers as hp, players as p where h.id = %(handid)s -and bc.handid = h.id and g.id = h.gametypeid and hp.handid = h.id and p.id = hp.playerid @@ -1145,20 +1263,15 @@ limit 1""", {'handid':handid}) res = c.fetchone() gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]} h = HoldemOmahaHand(hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid) - cards = map("".join, zip(map(str,res[11:21:2]), res[12:21:2])) - - if cards[0] != "0x": + cards = map(Card.valueSuitFromCard, res[11:16] ) + if cards[0]: h.setCommunityCards('FLOP', cards[0:3]) - if cards[3] != "0x": - h.setCommunityCards('TURN', cards[3]) - if cards[4] != "0x": - h.setCommunityCards('RIVER', cards[4]) + if cards[3]: + h.setCommunityCards('TURN', [cards[3]]) + if cards[4]: + h.setCommunityCards('RIVER', [cards[4]]) #[Card.valueSuitFromCard(x) for x in cards] - - #TODO : doesn't look like this is in the database; don't like the way Hand requires it - h.hero = 'mcturnbull' - # HandInfo : HID, TABLE # BUTTON - why is this treated specially in Hand? # answer: it is written out in hand histories @@ -1181,9 +1294,11 @@ WHERE h.id = %(handid)s c.execute(""" SELECT hp.seatno, + round(hp.winnings / 100.0,2) as winnings, p.name, round(hp.startcash / 100.0,2) as chips, - (hp.card1,hp.card2) as hole + hp.card1,hp.card2, + hp.position FROM handsplayers as hp, players as p @@ -1191,10 +1306,16 @@ WHERE hp.handid = %(handid)s and p.id = hp.playerid """, {'handid':handid}) - for (seat, name, chips, cards) in c.fetchall(): + for (seat, winnings, name, chips, card1,card2, position) in c.fetchall(): h.addPlayer(seat,name,chips) - h.addHoleCards([Card.valueSuitFromCard(x) for x in cards],name) + if card1 and card2: + h.addHoleCards(map(Card.valueSuitFromCard, (card1,card2)), name, dealt=True) + if winnings > 0: + h.addCollectPot(name, winnings) + if position == 'B': + h.buttonpos = seat + # actions c.execute(""" SELECT @@ -1203,7 +1324,7 @@ SELECT ha.street, ha.action, ha.allin, - ha.amount / 100.0 + round(ha.amount / 100.0,2) FROM handsplayers as hp, handsactions as ha, @@ -1218,7 +1339,7 @@ ORDER BY res = c.fetchall() for (actnum,player, streetnum, act, allin, amount) in res: act=act.strip() - street = h.streetList[streetnum+2] + street = h.allStreets[streetnum+1] if act==u'blind': h.addBlind(player, 'big blind', amount) # TODO: The type of blind is not recorded in the DB. @@ -1236,7 +1357,7 @@ ORDER BY else: print act, player, streetnum, allin, amount # TODO : other actions - #hhc.readCollectPot(self) + #hhc.readShowdownActions(self) #hc.readShownCards(self) h.totalPot() diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index 363175a1..56ad08f3 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -43,7 +43,7 @@ import Configuration import Stats import Mucked import Database -import HUD_main +#import HUD_main def importName(module_name, name): """Import a named object 'name' from module 'module_name'.""" diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py index 93f6d102..8ae6bc60 100755 --- a/pyfpdb/Mucked.py +++ b/pyfpdb/Mucked.py @@ -35,6 +35,7 @@ import gobject # FreePokerTools modules import Configuration import Database +import Card class Aux_Window: def __init__(self, hud, params, config): @@ -67,19 +68,27 @@ class Aux_Window: # Some utility routines useful for Aux_Windows # def get_card_images(self): - card_images = {} - suits = ('S', 'H', 'D', 'C') - ranks = ('A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2', 'B') + + card_images = 53 * [0] + suits = ('s', 'h', 'd', 'c') + ranks = (14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2) pb = gtk.gdk.pixbuf_new_from_file(self.config.execution_path(self.params['deck'])) - for j in range(0, 14): + for j in range(0, 13): for i in range(0, 4): - temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) - pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) - card_images[(ranks[j], suits[i])] = temp_pb + card_images[Card.cardFromValueSuit(ranks[j], suits[i])] = self.cropper(pb, i, j) + temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) +# also pick out a card back and store in [0] + card_images[0] = self.cropper(pb, 2, 13) return(card_images) # cards are 30 wide x 42 high + def cropper(self, pb, i, j): + """Crop out a card image given an FTP deck and the i, j position.""" + temp_pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pb.get_has_alpha(), pb.get_bits_per_sample(), 30, 42) + pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) + return temp_pb + def split_cards(self, card): if card == 'xx': return ('B', 'S') return (card[0], card[1].upper()) @@ -108,9 +117,10 @@ class Stud_mucked(Aux_Window): def create(self): - self.container =gtk.Window() + self.container = gtk.Window() self.vbox = gtk.VBox() self.container.add(self.vbox) + self.container.set_title(self.hud.table.name) self.mucked_list.create(self.vbox) self.mucked_cards.create(self.vbox) @@ -207,7 +217,9 @@ class Stud_list: # find the hero's seat from the stat_dict for stat in self.parent.hud.stat_dict.itervalues(): if stat['screen_name'] == hero: - return self.parent.hud.cards[stat['seat']][0:6] + return Card.valueSuitFromCard(self.parent.hud.cards[stat['seat']][0]) +\ + Card.valueSuitFromCard(self.parent.hud.cards[stat['seat']][1]) +\ + Card.valueSuitFromCard(self.parent.hud.cards[stat['seat']][2]) return "xxxxxx" def update_gui(self, new_hand_id): @@ -240,7 +252,7 @@ class Stud_cards: for r in range(0, self.rows): for c in range(0, self.cols): - self.seen_cards[(c, r)] = gtk.image_new_from_pixbuf(self.card_images[('B', 'S')]) + self.seen_cards[(c, r)] = gtk.image_new_from_pixbuf(self.card_images[(0)]) self.eb[(c, r)]= gtk.EventBox() # set up the contents for the cells @@ -287,11 +299,11 @@ class Stud_cards: self.clear() for c, cards in self.parent.hud.cards.iteritems(): self.grid_contents[(1, c - 1)].set_text(self.get_screen_name(c)) - for i in ((0, cards[0:2]), (1, cards[2:4]), (2, cards[4:6]), (3, cards[6:8]), - (4, cards[8:10]), (5, cards[10:12]), (6, cards[12:14])): - if not i[1] == "xx": + for i in ((0, cards[0]), (1, cards[1]), (2, cards[2]), (3, cards[3]), + (4, cards[4]), (5, cards[5]), (6, cards[6])): + if not i[1] == 0: self.seen_cards[(i[0], c - 1)]. \ - set_from_pixbuf(self.card_images[self.parent.split_cards(i[1])]) + set_from_pixbuf(self.card_images[i[1]]) ## action in tool tips for 3rd street cards for c in (0, 1, 2): for r in range(0, self.rows): @@ -314,7 +326,7 @@ class Stud_cards: for r in range(0, self.rows): self.grid_contents[(1, r)].set_text(" ") for c in range(0, 7): - self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[('B', 'S')]) + self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) self.eb[(c, r)].set_tooltip_text('') class Flop_Mucked(Aux_Window): @@ -459,29 +471,31 @@ class Flop_Mucked(Aux_Window): new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) -if __name__== "__main__": - - def destroy(*args): # call back for terminating the main eventloop - gtk.main_quit() # used only for testing +# This test program doesn't work - def process_new_hand(source, condition, db_connection): #callback from stdin watch -- testing only -# there is a new hand_id to be processed -# just read it and pass it to update - new_hand_id = sys.stdin.readline() - new_hand_id = new_hand_id.rstrip() # remove trailing whitespace - m.update_data(new_hand_id, db_connection) - m.update_gui(new_hand_id) - return(True) - - config = Configuration.Config() - db_connection = Database.Database(config, 'fpdb', '') - main_window = gtk.Window() - main_window.set_keep_above(True) - main_window.connect("destroy", destroy) - - aux_to_call = "stud_mucked" - aux_params = config.get_aux_parameters(aux_to_call) - m = eval("%s(main_window, None, config, aux_params)" % aux_params['class']) - - s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection) - gtk.main() +#if __name__== "__main__": +# +# def destroy(*args): # call back for terminating the main eventloop +# gtk.main_quit() # used only for testing +# +# def process_new_hand(source, condition, db_connection): #callback from stdin watch -- testing only +## there is a new hand_id to be processed +## just read it and pass it to update +# new_hand_id = sys.stdin.readline() +# new_hand_id = new_hand_id.rstrip() # remove trailing whitespace +# m.update_data(new_hand_id, db_connection) +# m.update_gui(new_hand_id) +# return(True) +# +# config = Configuration.Config() +# db_connection = Database.Database(config, 'fpdbTEST', '') +# main_window = gtk.Window() +# main_window.set_keep_above(True) +# main_window.connect("destroy", destroy) +# +# aux_to_call = "stud_mucked" +# aux_params = config.get_aux_parameters(aux_to_call) +# m = eval("%s(None, config, aux_params)" % aux_params['class']) +# +# s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection) +# gtk.main() diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py new file mode 100644 index 00000000..38307d40 --- /dev/null +++ b/pyfpdb/Options.py @@ -0,0 +1,45 @@ +#!/usr/bin/python + +#Copyright 2008 Ray E. Barker +#This program is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, version 3 of the License. +# +#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 Affero General Public License +#along with this program. If not, see . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + +import os +import sys +from optparse import OptionParser + +def fpdb_options(): + + """Process command line options for fpdb and HUD_main.""" + parser = OptionParser() + parser.add_option("-x", "--errorsToConsole", + action="store_true", + help="If passed error output will go to the console rather than .") + parser.add_option("-d", "--databaseName", + dest="dbname", default="fpdb", + help="Overrides the default database name") + parser.add_option("-c", "--configFile", + dest="config", default=None, + help="Specifies a configuration file.") + (options, sys.argv) = parser.parse_args() + return (options, sys.argv) + +if __name__== "__main__": + (options, sys.argv) = fpdb_options() + print "errorsToConsole =", options.errorsToConsole + print "database name =", options.dbname + print "config file =", options.config + + print "press enter to end" + sys.stdin.readline() \ No newline at end of file diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 703dadcf..5350713c 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python + #!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright 2008, Carl Gherardi @@ -26,7 +26,7 @@ from HandHistoryConverter import * class PokerStars(HandHistoryConverter): # Static regexes - re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(HORSE)? \(?(?PHold\'em|Razz|7 Card Stud|Omaha|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) + re_GameInfo = re.compile("PokerStars Game #(?P[0-9]+):\s+(HORSE)? \(?(?PHold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?PNo Limit|Limit|Pot Limit),? \(?(?P\$|)?(?P[.0-9]+)/\$?(?P[.0-9]+)\) - (?P.*$)", re.MULTILINE) re_SplitHands = re.compile('\n\n+') re_TailSplitHands = re.compile('(\n\n\n+)') re_HandInfo = re.compile("^Table \'(?P[- a-zA-Z]+)\'(?P.+?$)?", re.MULTILINE) @@ -95,6 +95,7 @@ follow : whether to tail -f the input""" 'Omaha Hi/Lo' : ('hold','omahahilo'), 'Razz' : ('stud','razz'), '7 Card Stud' : ('stud','studhi'), + '7 Card Stud Hi/Lo' : ('stud','studhilo'), 'Badugi' : ('draw','badugi') } currencies = { u'€':'EUR', '$':'USD', '':'T$' } @@ -208,7 +209,7 @@ follow : whether to tail -f the input""" for a in self.re_PostBB.finditer(hand.handText): hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) for a in self.re_PostBoth.finditer(hand.handText): - hand.addBlind(a.group('PNAME'), 'small & big blinds', a.group('SBBB')) + hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) def readHeroCards(self, hand): m = self.re_HeroCards.search(hand.handText) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index a36f812d..1a9deb60 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -528,7 +528,6 @@ class Sql: self.query['get_cards'] = """ select seatNo AS seat_number, - name AS screen_name, card1, /*card1Value, card1Suit, */ card2, /*card2Value, card2Suit, */ card3, /*card3Value, card3Suit, */ diff --git a/pyfpdb/WinTables.py b/pyfpdb/WinTables.py index 1b064eef..b867b83d 100644 --- a/pyfpdb/WinTables.py +++ b/pyfpdb/WinTables.py @@ -62,7 +62,7 @@ class Table(Table_Window): return None (x, y, width, height) = win32gui.GetWindowRect(hwnd) - print "x = %s y = %s width = %s height = %s" % (x, y, width, height) + print "x = %s y = %s width = %s height = %s" % (x, y, width, height) self.x = int(x) + b_width self.y = int(y) + tb_height self.height = int(height) - b_width - tb_height @@ -72,7 +72,8 @@ class Table(Table_Window): self.title = titles[hwnd] self.site = "" self.hud = None - self.number = gtk.gdk.window_foreign_new(long(self.window)) + self.number = hwnd + self.gdkhandle = gtk.gdk.window_foreign_new(long(self.window)) def get_geometry(self): @@ -112,32 +113,31 @@ class Table(Table_Window): win32api.CloseHandle(hToken) return exename + def topify(self, hud): + """Set the specified gtk window to stayontop in MS Windows.""" + + def windowEnumerationHandler(hwnd, resultList): + '''Callback for win32gui.EnumWindows() to generate list of window handles.''' + resultList.append((hwnd, win32gui.GetWindowText(hwnd))) + + unique_name = 'unique name for finding this window' + real_name = hud.main_window.get_title() + hud.main_window.set_title(unique_name) + tl_windows = [] + win32gui.EnumWindows(windowEnumerationHandler, tl_windows) + + for w in tl_windows: + if w[1] == unique_name: + hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) + hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) +# +# style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE) +# style |= win32con.WS_CLIPCHILDREN +# win32gui.SetWindowLong(self.number, win32con.GWL_EXSTYLE, style) + break + + hud.main_window.set_title(real_name) + def win_enum_handler(hwnd, titles): titles[hwnd] = win32gui.GetWindowText(hwnd) -def topify_window(hud, window): - """Set the specified gtk window to stayontop in MS Windows.""" - - def windowEnumerationHandler(hwnd, resultList): - '''Callback for win32gui.EnumWindows() to generate list of window handles.''' - resultList.append((hwnd, win32gui.GetWindowText(hwnd))) - - unique_name = 'unique name for finding this window' - real_name = window.get_title() - window.set_title(unique_name) - tl_windows = [] - win32gui.EnumWindows(windowEnumerationHandler, tl_windows) - - for w in tl_windows: - if w[1] == unique_name: - hud.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(hud.table.number)) - hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) - hud.main_window.gdkhandle.set_transient_for(hud.main_window.parentgdkhandle) - - style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) - style |= win32con.WS_CLIPCHILDREN - win32gui.SetWindowLong(hud.table.number, win32con.GWL_EXSTYLE, style) - break - - window.set_title(real_name) - diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index c0f63a04..b03e8424 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -17,15 +17,11 @@ import os import sys -from optparse import OptionParser +import Options +import string - -parser = OptionParser() -parser.add_option("-x", "--errorsToConsole", action="store_true", - help="If passed error output will go to the console rather than .") -parser.add_option("-d", "--databaseName", dest="dbname", default="fpdb", - help="Overrides the default database name") -(options, sys.argv) = parser.parse_args() +cl_options = string.join(sys.argv[1:]) +(options, sys.argv) = Options.fpdb_options() if not options.errorsToConsole: print "Note: error output is being diverted to fpdb-error-log.txt and HUD-error.txt. Any major error will be reported there _only_." @@ -356,6 +352,7 @@ class fpdb: else: self.settings['os']="windows" + self.settings.update({'cl_options': cl_options}) self.settings.update(self.config.get_db_parameters()) self.settings.update(self.config.get_tv_parameters()) self.settings.update(self.config.get_import_parameters()) @@ -486,7 +483,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def __init__(self): self.threads=[] self.db=None - self.config = Configuration.Config(dbname=options.dbname) + self.config = Configuration.Config(file=options.config, dbname=options.dbname) self.load_profile() self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 7c1fc800..29817af9 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -578,7 +578,7 @@ class fpdb_db: self.cursor.execute( "lock tables Hands write" ) except: # Table 'fpdb.hands' doesn't exist - if str(sys.exc_value).find(".hands' doesn't exist") >= 0: + if str(sys.exc_value).find(".Hands' doesn't exist") >= 0: return(2) print "Error! failed to obtain global lock. Close all programs accessing " \ + "database (including fpdb) and try again (%s)." \ @@ -596,12 +596,41 @@ class fpdb_db: + "database (including fpdb) and try again (%s)." \ % ( str(sys.exc_value).rstrip('\n'), ) return(1) - return(0) + return(0) + + def getLastInsertId(self): + if self.backend == self.MYSQL_INNODB: + ret = self.db.insert_id() + if ret < 1 or ret > 999999999: + print "getLastInsertId(): problem fetching insert_id? ret=", ret + ret = -1 + elif self.backend == self.PGSQL: + # some options: + # currval(hands_id_seq) - use name of implicit seq here + # lastval() - still needs sequences set up? + # insert ... returning is useful syntax (but postgres specific?) + # see rules (fancy trigger type things) + self.cursor.execute ("SELECT lastval()") + row = self.cursor.fetchone() + if not row: + print "getLastInsertId(%s): problem fetching lastval? row=" % seq, row + ret = -1 + else: + ret = row[0] + elif self.backend == self.SQLITE: + # don't know how to do this in sqlite + print "getLastInsertId(): not coded for sqlite yet" + ret = -1 + else: + print "getLastInsertId(): unknown backend ", self.backend + ret = -1 + return ret def storeHand(self, p): #stores into table hands: self.cursor.execute ("""INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats + ,boardcard1, boardcard2, boardcard3, boardcard4, boardcard5 ,playersVpi, playersAtStreet1, playersAtStreet2 ,playersAtStreet3, playersAtStreet4, playersAtShowdown ,street0Raises, street1Raises, street2Raises @@ -612,6 +641,7 @@ class fpdb_db: VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""" ,(p['siteHandNo'], gametype_id, p['handStart'], len(names), p['tableName'], datetime.datetime.today(), p['maxSeats'] + ,p['boardcard1'], ['boardcard2'], p['boardcard3'], ['boardcard4'], ['boardcard5'] ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 3fa20b40..455c1e27 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -288,36 +288,34 @@ class Importer: if os.path.isdir(file): self.addToDirList[file] = [site] + [filter] return - if filter == "passthrough" or filter == "": - (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(file, site) - else: - conv = None - # Load filter, process file, pass returned filename to import_fpdb_file + + conv = None + # Load filter, process file, pass returned filename to import_fpdb_file - print "\nConverting %s" % file - hhbase = self.config.get_import_parameters().get("hhArchiveBase") - hhbase = os.path.expanduser(hhbase) - hhdir = os.path.join(hhbase,site) - try: - out_path = os.path.join(hhdir, file.split(os.path.sep)[-2]+"-"+os.path.basename(file)) - except: - out_path = os.path.join(hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file)) + print "\nConverting %s" % file + hhbase = self.config.get_import_parameters().get("hhArchiveBase") + hhbase = os.path.expanduser(hhbase) + hhdir = os.path.join(hhbase,site) + try: + out_path = os.path.join(hhdir, file.split(os.path.sep)[-2]+"-"+os.path.basename(file)) + except: + out_path = os.path.join(hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file)) - filter_name = filter.replace("ToFpdb", "") + filter_name = filter.replace("ToFpdb", "") - mod = __import__(filter) - obj = getattr(mod, filter_name, None) - if callable(obj): - conv = obj(in_path = file, out_path = out_path) - if(conv.getStatus()): - (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, site) - else: - # conversion didn't work - # TODO: appropriate response? - return (0, 0, 0, 1, 0) + mod = __import__(filter) + obj = getattr(mod, filter_name, None) + if callable(obj): + conv = obj(in_path = file, out_path = out_path) + if(conv.getStatus()): + (stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(out_path, site) else: - print "Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter) - return + # conversion didn't work + # TODO: appropriate response? + return (0, 0, 0, 1, 0) + else: + print "Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter) + return #This will barf if conv.getStatus != True return (stored, duplicates, partial, errors, ttime) @@ -394,8 +392,8 @@ class Importer: self.hand=hand try: - handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb.db - ,self.fdb.cursor, self.siteIds[site], category, hand, self.config) + handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb + , self.siteIds[site], category, hand, self.config) self.fdb.db.commit() stored += 1 diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index ee5d9c40..eff8179f 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -18,11 +18,13 @@ #methods that are specific to holdem but not trivial import fpdb_simple -import fpdb_save_to_db +import Database #parses a holdem hand -def mainParser(settings, db, cursor, siteID, category, hand, config): +def mainParser(settings, fdb, siteID, category, hand, config): backend = settings['db-backend'] + #This is redundant - hopefully fdb will be a Database object in an interation soon + db = Database.Database(config, 'fpdb', '') category = fpdb_simple.recogniseCategory(hand[0]) base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" @@ -47,7 +49,7 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): break #print "small blind line:",smallBlindLine - gametypeID = fpdb_simple.recogniseGametypeID(backend, db, cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) + gametypeID = fpdb_simple.recogniseGametypeID(backend, fdb.db, fdb.cursor, hand[0], hand[smallBlindLine], siteID, category, isTourney) if isTourney: siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0]) buyin = fpdb_simple.parseBuyin(hand[0]) @@ -58,9 +60,9 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): tourneyStartTime= handStartTime #todo: read tourney start time rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0]) - tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(cursor, siteID, buyin, fee, knockout, rebuyOrAddon) + tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(fdb.cursor, siteID, buyin, fee, knockout, rebuyOrAddon) - fpdb_simple.isAlreadyInDB(cursor, gametypeID, siteHandNo) + fpdb_simple.isAlreadyInDB(fdb.cursor, gametypeID, siteHandNo) hand = fpdb_simple.filterCrap(hand, isTourney) @@ -74,7 +76,7 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): seatLines.append(line) names = fpdb_simple.parseNames(seatLines) - playerIDs = fpdb_simple.recognisePlayerIDs(cursor, names, siteID) + playerIDs = fpdb_simple.recognisePlayerIDs(fdb.cursor, names, siteID) tmp = fpdb_simple.parseCashesAndSeatNos(seatLines) startCashes = tmp['startCashes'] seatNos = tmp['seatNos'] @@ -113,7 +115,7 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): tableName = tableResult['tableName'] #print "before part5, antes:", antes - #part 5: final preparations, then call fpdb_save_to_db.* with + #part 5: final preparations, then call Database.* with # the arrays as they are - that file will fill them. fpdb_simple.convertCardValues(cardValues) if base == "hold": @@ -121,8 +123,8 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): fpdb_simple.convertBlindBet(actionTypes, actionAmounts) fpdb_simple.checkPositions(positions) - cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, )) - limit_type = cursor.fetchone()[0] + fdb.cursor.execute("SELECT limitType FROM Gametypes WHERE id=%s",(gametypeID, )) + limit_type = fdb.cursor.fetchone()[0] fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts) totalWinnings = sum(winnings) @@ -143,8 +145,8 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): payin_amounts = fpdb_simple.calcPayin(len(names), buyin, fee) if base == "hold": - result = fpdb_save_to_db.tourney_holdem_omaha( - config, settings, db, cursor, base, category, siteTourneyNo, buyin + result = db.tourney_holdem_omaha( + config, settings, fdb.db, fdb.cursor, base, category, siteTourneyNo, buyin , fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -152,8 +154,8 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): , winnings, rakes, actionTypes, allIns, actionAmounts , actionNos, hudImportData, maxSeats, tableName, seatNos) elif base == "stud": - result = fpdb_save_to_db.tourney_stud( - config, settings, db, cursor, base, category, siteTourneyNo + result = db.tourney_stud( + config, settings, fdb.db, fdb.cursor, base, category, siteTourneyNo , buyin, fee, knockout, entries, prizepool, tourneyStartTime , payin_amounts, ranks, tourneyTypeId, siteID, siteHandNo , gametypeID, handStartTime, names, playerIDs, startCashes @@ -164,23 +166,23 @@ def mainParser(settings, db, cursor, siteID, category, hand, config): raise fpdb_simple.FpdbError("unrecognised category") else: if base == "hold": - result = fpdb_save_to_db.ring_holdem_omaha( - config, settings, db, cursor, base, category, siteHandNo + result = db.ring_holdem_omaha( + config, settings, fdb.db, fdb.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( - config, settings, db, cursor, base, category, siteHandNo, gametypeID + result = db.ring_stud( + config, settings, fdb.db, fdb.cursor, base, category, siteHandNo, gametypeID , handStartTime, names, playerIDs, startCashes, antes , cardValues, cardSuits, winnings, rakes, actionTypes, allIns , actionAmounts, actionNos, hudImportData, maxSeats, tableName , seatNos) else: raise fpdb_simple.FpdbError ("unrecognised category") - db.commit() + fdb.db.commit() return result #end def mainParser diff --git a/pyfpdb/fpdb_save_to_db.py b/pyfpdb/fpdb_save_to_db.py deleted file mode 100644 index d06f8c45..00000000 --- a/pyfpdb/fpdb_save_to_db.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/python - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#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 Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -#This file contains methods to store hands into the db. decides to move this -#into a seperate file since its ugly, fairly long and just generally in the way. - -from time import time - -import fpdb_simple - -MYSQL_INNODB = 2 -PGSQL = 3 -SQLITE = 4 - -#fastStoreHudCache = False # set this to True to test the new storeHudCache routine -# -#saveActions = True # set this to False to avoid storing action data -# # Pros: speeds up imports -# # Cons: no action data is saved, so you need to keep the hand histories -# # variance not available on stats page -# # no graphs - -#stores a stud/razz hand into the database -def ring_stud(config, settings, db, 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): - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - - saveActions = False if import_options['saveActions'] == False else True - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats) - - #print "before calling store_hands_players_stud, antes:", antes - hands_players_ids = fpdb_simple.store_hands_players_stud(backend, db, cursor, hands_id, player_ids - ,start_cashes, antes, card_values - ,card_suits, winnings, rakes, seatNos) - - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, action_types - ,allIns, action_amounts, actionNos) - return hands_id -#end def ring_stud - -def ring_holdem_omaha(config, settings, db, 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""" - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = False if import_options['saveActions'] == False else True - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - -# print "DEBUG: saveActions = '%s' fastStoreHudCache = '%s'"%(saveActions, fastStoreHudCache) -# print "DEBUG: import_options = ", import_options - - t0 = time() - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - t1 = time() - fpdb_simple.fill_board_cards(board_values, board_suits) - t2 = time() - - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudImportData) - t3 = time() - hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha( - backend, db, cursor, category, hands_id, player_ids, start_cashes - , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) - t4 = time() - #print "ring holdem, backend=%d" % backend - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - t5 = time() - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - t6 = time() - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) - t7 = time() - #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4, t6-t5) - return hands_id -#end def ring_holdem_omaha - -def tourney_holdem_omaha(config, settings, db, 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, allIns, action_amounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a tourney holdem/omaha hand into the database""" - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == True else False - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - fpdb_simple.fill_board_cards(board_values, board_suits) - - tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) - tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, player_ids, payin_amounts, ranks, winnings) - - hands_id = fpdb_simple.storeHands(backend, db, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats) - - hands_players_ids = fpdb_simple.store_hands_players_holdem_omaha_tourney( - backend, db, cursor, category, hands_id, player_ids, start_cashes, positions - , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids) - - #print "tourney holdem, backend=%d" % backend - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - if fastStoreHudCache: - fpdb_simple.storeHudCache2(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - else: - fpdb_simple.storeHudCache(backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) - - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) - return hands_id -#end def tourney_holdem_omaha - -def tourney_stud(config, settings, db, cursor, base, category, siteTourneyNo, buyin, fee, knockout, entries - ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId - ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes - ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): -#stores a tourney stud/razz hand into the database - - backend = settings['db-backend'] - import_options = config.get_import_parameters() - saveActions = True if import_options['saveActions'] == True else False - fastStoreHudCache = True if import_options['fastStoreHudCache'] == True else False - - fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) - - tourney_id = fpdb_simple.store_tourneys(cursor, tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) - - tourneys_players_ids = fpdb_simple.store_tourneys_players(cursor, tourney_id, playerIds, payin_amounts, ranks, winnings) - - hands_id = fpdb_simple.storeHands(backend, db, cursor, siteHandNo, gametypeId, handStartTime, names, tableName, maxSeats) - - hands_players_ids = fpdb_simple.store_hands_players_stud_tourney(backend, db, cursor, hands_id - , playerIds, startCashes, antes, cardValues, cardSuits - , winnings, rakes, seatNos, tourneys_players_ids) - - if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': - fpdb_simple.storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData) - - if saveActions: - fpdb_simple.storeActions(cursor, hands_players_ids, actionTypes, allIns, actionAmounts, actionNos) - return hands_id -#end def tourney_stud diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index b140a2a8..34f99e2f 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -1147,10 +1147,13 @@ card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", #end def store_board_cards def storeHands(backend, conn, cursor, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudCache): + ,hand_start_time, names, tableName, maxSeats, hudCache, + board_values, board_suits): + cards = [Card.cardFromValueSuit(v,s) for v,s in zip(board_values,board_suits)] #stores into table hands: cursor.execute ("""INSERT INTO Hands (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats + ,boardcard1,boardcard2,boardcard3,boardcard4,boardcard5 ,playersVpi, playersAtStreet1, playersAtStreet2 ,playersAtStreet3, playersAtStreet4, playersAtShowdown ,street0Raises, street1Raises, street2Raises @@ -1159,9 +1162,11 @@ def storeHands(backend, conn, cursor, site_hand_no, gametype_id ,showdownPot ) VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) + (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, + %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.datetime.today(), maxSeats + ,cards[0], cards[1], cards[2], cards[3], cards[4] ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] @@ -1318,19 +1323,26 @@ def store_hands_players_stud(backend, conn, cursor, hands_id, player_ids, start_ result=[] #print "before inserts in store_hands_players_stud, antes:", antes for i in xrange(len(player_ids)): + card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) + card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) + card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) + card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) + card5 = Card.cardFromValueSuit(card_values[i][4], card_suits[i][4]) + card6 = Card.cardFromValueSuit(card_values[i][5], card_suits[i][5]) + card7 = Card.cardFromValueSuit(card_values[i][6], card_suits[i][6]) + cursor.execute ("""INSERT INTO HandsPlayers -(handId, playerId, startCash, ante, -card1Value, card1Suit, card2Value, card2Suit, -card3Value, card3Suit, card4Value, card4Suit, -card5Value, card5Suit, card6Value, card6Suit, -card7Value, card7Suit, winnings, rake, seatNo) -VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, -%s, %s, %s, %s)""", - (hands_id, player_ids[i], start_cashes[i], antes[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], - card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5], - card_values[i][6], card_suits[i][6], winnings[i], rakes[i], seatNos[i])) +(handId, playerId, startCash, ante, tourneyTypeId, +card1, card2, +card3, card4, +card5, card6, +card7, winnings, rake, seatNo) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", + (hands_id, player_ids[i], start_cashes[i], antes[i], 1, + card1, card2, + card3, card4, + card5, card6, + card7, winnings[i], rakes[i], seatNos[i])) #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) #result.append(cursor.fetchall()[0][0]) result.append( getLastInsertId(backend, conn, cursor) ) @@ -2114,189 +2126,6 @@ def storeHudCache(backend, cursor, base, category, gametypeId, hand_start_time, # hard-code styleKey as 'A000000' (all-time cache, no key) for now styleKey = 'A000000' - #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ - #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) - for player in xrange(len(playerIds)): - - # Set up a clean row - row=[] - row.append(0)#blank for id - row.append(gametypeId) - row.append(playerIds[player]) - row.append(len(playerIds))#seats - for i in xrange(len(hudImportData)+2): - row.append(0) - - if base=="hold": - row[4]=hudImportData['position'][player] - else: - row[4]=0 - row[5]=1 #tourneysGametypeId - row[6]+=1 #HDs - if hudImportData['street0VPI'][player]: row[7]+=1 - if hudImportData['street0Aggr'][player]: row[8]+=1 - if hudImportData['street0_3BChance'][player]: row[9]+=1 - if hudImportData['street0_3BDone'][player]: row[10]+=1 - if hudImportData['street1Seen'][player]: row[11]+=1 - if hudImportData['street2Seen'][player]: row[12]+=1 - if hudImportData['street3Seen'][player]: row[13]+=1 - if hudImportData['street4Seen'][player]: row[14]+=1 - if hudImportData['sawShowdown'][player]: row[15]+=1 - if hudImportData['street1Aggr'][player]: row[16]+=1 - if hudImportData['street2Aggr'][player]: row[17]+=1 - if hudImportData['street3Aggr'][player]: row[18]+=1 - if hudImportData['street4Aggr'][player]: row[19]+=1 - if hudImportData['otherRaisedStreet1'][player]: row[20]+=1 - if hudImportData['otherRaisedStreet2'][player]: row[21]+=1 - if hudImportData['otherRaisedStreet3'][player]: row[22]+=1 - if hudImportData['otherRaisedStreet4'][player]: row[23]+=1 - if hudImportData['foldToOtherRaisedStreet1'][player]: row[24]+=1 - if hudImportData['foldToOtherRaisedStreet2'][player]: row[25]+=1 - if hudImportData['foldToOtherRaisedStreet3'][player]: row[26]+=1 - if hudImportData['foldToOtherRaisedStreet4'][player]: row[27]+=1 - if hudImportData['wonWhenSeenStreet1'][player]!=0.0: row[28]+=hudImportData['wonWhenSeenStreet1'][player] - if hudImportData['wonAtSD'][player]!=0.0: row[29]+=hudImportData['wonAtSD'][player] - if hudImportData['stealAttemptChance'][player]: row[30]+=1 - if hudImportData['stealAttempted'][player]: row[31]+=1 - if hudImportData['foldBbToStealChance'][player]: row[32]+=1 - if hudImportData['foldedBbToSteal'][player]: row[33]+=1 - if hudImportData['foldSbToStealChance'][player]: row[34]+=1 - if hudImportData['foldedSbToSteal'][player]: row[35]+=1 - - if hudImportData['street1CBChance'][player]: row[36]+=1 - if hudImportData['street1CBDone'][player]: row[37]+=1 - if hudImportData['street2CBChance'][player]: row[38]+=1 - if hudImportData['street2CBDone'][player]: row[39]+=1 - if hudImportData['street3CBChance'][player]: row[40]+=1 - if hudImportData['street3CBDone'][player]: row[41]+=1 - if hudImportData['street4CBChance'][player]: row[42]+=1 - if hudImportData['street4CBDone'][player]: row[43]+=1 - - if hudImportData['foldToStreet1CBChance'][player]: row[44]+=1 - if hudImportData['foldToStreet1CBDone'][player]: row[45]+=1 - if hudImportData['foldToStreet2CBChance'][player]: row[46]+=1 - if hudImportData['foldToStreet2CBDone'][player]: row[47]+=1 - if hudImportData['foldToStreet3CBChance'][player]: row[48]+=1 - if hudImportData['foldToStreet3CBDone'][player]: row[49]+=1 - if hudImportData['foldToStreet4CBChance'][player]: row[50]+=1 - if hudImportData['foldToStreet4CBDone'][player]: row[51]+=1 - - #print "player=", player - #print "len(totalProfit)=", len(hudImportData['totalProfit']) - if hudImportData['totalProfit'][player]: - row[52]+=hudImportData['totalProfit'][player] - - if hudImportData['street1CheckCallRaiseChance'][player]: row[53]+=1 - if hudImportData['street1CheckCallRaiseDone'][player]: row[54]+=1 - if hudImportData['street2CheckCallRaiseChance'][player]: row[55]+=1 - if hudImportData['street2CheckCallRaiseDone'][player]: row[56]+=1 - if hudImportData['street3CheckCallRaiseChance'][player]: row[57]+=1 - if hudImportData['street3CheckCallRaiseDone'][player]: row[58]+=1 - if hudImportData['street4CheckCallRaiseChance'][player]: row[59]+=1 - if hudImportData['street4CheckCallRaiseDone'][player]: row[60]+=1 - - # Try to do the update first: - num = cursor.execute("""UPDATE HudCache -SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s, - street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, - street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, - street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, - street4Aggr=street4Aggr+%s, otherRaisedStreet1=otherRaisedStreet1+%s, - otherRaisedStreet2=otherRaisedStreet2+%s, otherRaisedStreet3=otherRaisedStreet3+%s, - otherRaisedStreet4=otherRaisedStreet4+%s, - foldToOtherRaisedStreet1=foldToOtherRaisedStreet1+%s, foldToOtherRaisedStreet2=foldToOtherRaisedStreet2+%s, - foldToOtherRaisedStreet3=foldToOtherRaisedStreet3+%s, foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s, - wonWhenSeenStreet1=wonWhenSeenStreet1+%s, wonAtSD=wonAtSD+%s, stealAttemptChance=stealAttemptChance+%s, - stealAttempted=stealAttempted+%s, foldBbToStealChance=foldBbToStealChance+%s, - foldedBbToSteal=foldedBbToSteal+%s, - foldSbToStealChance=foldSbToStealChance+%s, foldedSbToSteal=foldedSbToSteal+%s, - street1CBChance=street1CBChance+%s, street1CBDone=street1CBDone+%s, street2CBChance=street2CBChance+%s, - street2CBDone=street2CBDone+%s, street3CBChance=street3CBChance+%s, - street3CBDone=street3CBDone+%s, street4CBChance=street4CBChance+%s, street4CBDone=street4CBDone+%s, - foldToStreet1CBChance=foldToStreet1CBChance+%s, foldToStreet1CBDone=foldToStreet1CBDone+%s, - foldToStreet2CBChance=foldToStreet2CBChance+%s, foldToStreet2CBDone=foldToStreet2CBDone+%s, - foldToStreet3CBChance=foldToStreet3CBChance+%s, - foldToStreet3CBDone=foldToStreet3CBDone+%s, foldToStreet4CBChance=foldToStreet4CBChance+%s, - foldToStreet4CBDone=foldToStreet4CBDone+%s, totalProfit=totalProfit+%s, - street1CheckCallRaiseChance=street1CheckCallRaiseChance+%s, - street1CheckCallRaiseDone=street1CheckCallRaiseDone+%s, street2CheckCallRaiseChance=street2CheckCallRaiseChance+%s, - street2CheckCallRaiseDone=street2CheckCallRaiseDone+%s, street3CheckCallRaiseChance=street3CheckCallRaiseChance+%s, - street3CheckCallRaiseDone=street3CheckCallRaiseDone+%s, street4CheckCallRaiseChance=street4CheckCallRaiseChance+%s, - street4CheckCallRaiseDone=street4CheckCallRaiseDone+%s -WHERE gametypeId+0=%s -AND playerId=%s -AND activeSeats=%s -AND position=%s -AND tourneyTypeId+0=%s -AND styleKey=%s - """, (row[6], row[7], row[8], row[9], row[10], - row[11], row[12], row[13], row[14], row[15], - row[16], row[17], row[18], row[19], row[20], - row[21], row[22], row[23], row[24], row[25], - row[26], row[27], row[28], row[29], row[30], - row[31], row[32], row[33], row[34], row[35], - row[36], row[37], row[38], row[39], row[40], - row[41], row[42], row[43], row[44], row[45], - row[46], row[47], row[48], row[49], row[50], - row[51], row[52], row[53], row[54], row[55], - row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5], styleKey)) - # Test statusmessage to see if update worked, do insert if not - #print "storehud2, upd num =", num - if ( (backend == PGSQL and cursor.statusmessage != "UPDATE 1") - or (backend == MYSQL_INNODB and num == 0) ): - #print "playerid before insert:",row[2]," num = ", num - cursor.execute("""INSERT INTO HudCache -(gametypeId, playerId, activeSeats, position, tourneyTypeId, styleKey, -HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, -street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, -street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, -otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, -foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, wonWhenSeenStreet1, wonAtSD, stealAttemptChance, -stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, -street1CBChance, street1CBDone, street2CBChance, street2CBDone, street3CBChance, -street3CBDone, street4CBChance, street4CBDone, foldToStreet1CBChance, foldToStreet1CBDone, -foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, -foldToStreet4CBDone, totalProfit, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, -street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone) -VALUES (%s, %s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s, -%s, %s, %s, %s, %s)""" - , (row[1], row[2], row[3], row[4], row[5], styleKey, row[6], row[7], row[8], row[9], row[10] - ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] - ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] - ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] - ,row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50] - ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60]) ) - #print "hopefully inserted hud data line: ", cursor.statusmessage - # message seems to be "INSERT 0 1" - else: - #print "updated(2) hud data line" - pass -# else: -# print "todo: implement storeHudCache for stud base" -#end def storeHudCache - -def storeHudCache2(backend, cursor, base, category, gametypeId, hand_start_time, playerIds, hudImportData): - """Modified version aiming for more speed ...""" -# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - if use_date_in_hudcache: - #print "key =", "d%02d%02d%02d " % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - else: - # hard-code styleKey as 'A000000' (all-time cache, no key) for now - styleKey = 'A000000' - #print "storeHudCache2, len(playerIds)=", len(playerIds), " len(vpip)=" \ #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) for player in xrange(len(playerIds)):