#!/usr/bin/env python """Database.py Create and manage the database objects. """ # Copyright 2008, Ray E. Barker # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ######################################################################## # postmaster -D /var/lib/pgsql/data # Standard Library modules import sys import traceback from datetime import datetime, date, time, timedelta import string # pyGTK modules # FreePokerTools modules import fpdb_db import Configuration import SQL import Card class Database: def __init__(self, c, db_name, game): self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(c) self.connection = self.fdb.db db_params = c.get_db_parameters() self.type = db_params['db-type'] self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) self.connection.rollback() # To add to config: self.hud_style = 'T' # A=All-time # S=Session # T=timed (last n days) # Future values may also include: # H=Hands (last n hands) self.hud_hands = 1000 # Max number of hands from each player to use for hud stats self.hud_days = 90 # Max number of days from each player to use for hud stats self.hud_session_gap = 30 # Gap (minutes) between hands that indicates a change of session # (hands every 2 mins for 1 hour = one session, if followed # by a 40 minute gap and then more hands on same table that is # a new session) cur = self.connection.cursor() self.hand_1day_ago = 0 cur.execute(self.sql.query['get_hand_1day_ago']) row = cur.fetchone() if row and row[0]: self.hand_1day_ago = row[0] #print "hand 1day ago =", self.hand_1day_ago d = timedelta(days=self.hud_days) now = datetime.utcnow() - d self.date_ndays_ago = "d%02d%02d%02d" % (now.year-2000, now.month, now.day) self.hand_nhands_ago = 0 # todo #cur.execute(self.sql.query['get_table_name'], (hand_id, )) #row = cur.fetchone() def close_connection(self): self.connection.close() def get_table_name(self, hand_id): c = self.connection.cursor() c.execute(self.sql.query['get_table_name'], (hand_id, )) row = c.fetchone() return row def get_last_hand(self): c = self.connection.cursor() c.execute(self.sql.query['get_last_hand']) row = c.fetchone() return row[0] def get_xml(self, hand_id): c = self.connection.cursor() c.execute(self.sql.query['get_xml'], (hand_id)) row = c.fetchone() return row[0] def get_recent_hands(self, last_hand): c = self.connection.cursor() c.execute(self.sql.query['get_recent_hands'], {'last_hand': last_hand}) return c.fetchall() def get_hand_info(self, new_hand_id): c = self.connection.cursor() c.execute(self.sql.query['get_hand_info'], new_hand_id) return c.fetchall() def get_actual_seat(self, hand_id, name): c = self.connection.cursor() c.execute(self.sql.query['get_actual_seat'], (hand_id, name)) row = c.fetchone() return row[0] 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, # 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]) for row in c.fetchall(): cards[row[0]] = row[1:] return cards def get_common_cards(self, hand): """Get and return the community cards for the specified hand.""" cards = {} c = self.connection.cursor() c.execute(self.sql.query['get_common_cards'], [hand]) colnames = [desc[0] for desc in c.description] for row in c.fetchall(): s_dict = {} for name, val in zip(colnames, row): s_dict[name] = val cards['common'] = (self.convert_cards(s_dict)) return cards def convert_cards(self, d): ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') cards = "" for i in xrange(1, 8): # key = 'card' + str(i) + 'Value' # if not d.has_key(key): continue # if d[key] == None: # break # elif d[key] == 0: # cards += "xx" # else: # cards += ranks[d['card' + str(i) + 'Value']] + d['card' +str(i) + 'Suit'] cv = "card%dvalue" % i if cv not in d or d[cv] == None: break elif d[cv] == 0: cards += "xx" else: cs = "card%dsuit" % i cards = "%s%s%s" % (cards, ranks[d[cv]], d[cs]) return cards def get_action_from_hand(self, hand_no): action = [ [], [], [], [], [] ] c = self.connection.cursor() c.execute(self.sql.query['get_action_from_hand'], (hand_no,)) for row in c.fetchall(): street = row[0] act = row[1:] action[street].append(act) return action def get_winners_from_hand(self, hand): """Returns a hash of winners:amount won, given a hand number.""" winners = {} c = self.connection.cursor() c.execute(self.sql.query['get_winners_from_hand'], (hand,)) for row in c.fetchall(): winners[row[0]] = row[1] return winners def get_stats_from_hand(self, hand, aggregate = False): if self.hud_style == 'S': return( self.get_stats_from_hand_session(hand) ) else: # self.hud_style == A if aggregate: query = 'get_stats_from_hand_aggregated' else: query = 'get_stats_from_hand' if self.hud_style == 'T': stylekey = self.date_ndays_ago else: # assume A (all-time) stylekey = '0000000' # all stylekey values should be higher than this subs = (hand, hand, stylekey) #print "get stats: hud style =", self.hud_style, "subs =", subs c = self.connection.cursor() # now get the stats c.execute(self.sql.query[query], subs) colnames = [desc[0] for desc in c.description] stat_dict = {} for row in c.fetchall(): t_dict = {} for name, val in zip(colnames, row): t_dict[name.lower()] = val # print t_dict stat_dict[t_dict['player_id']] = t_dict return stat_dict # uses query on handsplayers instead of hudcache to get stats on just this session def get_stats_from_hand_session(self, hand): if self.hud_style == 'S': query = self.sql.query['get_stats_from_hand_session'] if self.db_server == 'mysql': query = query.replace("", 'signed ') else: query = query.replace("", '') else: # self.hud_style == A return None subs = (self.hand_1day_ago, hand) c = self.connection.cursor() # now get the stats #print "sess_stats: subs =", subs, "subs[0] =", subs[0] c.execute(query, subs) colnames = [desc[0] for desc in c.description] n,stat_dict = 0,{} row = c.fetchone() while row: if colnames[0].lower() == 'player_id': playerid = row[0] else: print "ERROR: query %s result does not have player_id as first column" % (query,) break for name, val in zip(colnames, row): if not playerid in stat_dict: stat_dict[playerid] = {} stat_dict[playerid][name.lower()] = val elif not name.lower() in stat_dict[playerid]: stat_dict[playerid][name.lower()] = val elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'): stat_dict[playerid][name.lower()] += val n += 1 if n >= 4000: break # todo: don't think this is needed so set nice and high # for now - comment out or remove? row = c.fetchone() #print " %d rows fetched, len(stat_dict) = %d" % (n, len(stat_dict)) #print "session stat_dict =", stat_dict return stat_dict def get_player_id(self, config, site, player_name): c = self.connection.cursor() c.execute(self.sql.query['get_player_id'], {'player': player_name, 'site': site}) row = c.fetchone() if row: return row[0] else: return None if __name__=="__main__": c = Configuration.Config() db_connection = Database(c, 'fpdb', 'holdem') # mysql fpdb holdem # db_connection = Database(c, 'fpdb-p', 'test') # mysql fpdb holdem # db_connection = Database(c, 'PTrackSv2', 'razz') # mysql razz # db_connection = Database(c, 'ptracks', 'razz') # postgres print "database connection object = ", db_connection.connection print "database type = ", db_connection.type h = db_connection.get_last_hand() print "last hand = ", h hero = db_connection.get_player_id(c, 'PokerStars', 'nutOmatic') if hero: print "nutOmatic is id_player = %d" % hero stat_dict = db_connection.get_stats_from_hand(h) for p in stat_dict.keys(): print p, " ", stat_dict[p] #print "nutOmatics stats:" #stat_dict = db_connection.get_stats_from_hand(h, hero) #for p in stat_dict.keys(): # print p, " ", stat_dict[p] print "cards =", db_connection.get_cards(u'1') db_connection.close_connection print "press enter to continue" sys.stdin.readline()