Merge branch 'master' of git://git.assembla.com/free_poker_tools
This commit is contained in:
commit
9af903a666
45
pyfpdb/AbsoluteToFpdb.py
Normal file → Executable file
45
pyfpdb/AbsoluteToFpdb.py
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright 2008, Carl Gherardi
|
# Copyright 2008, Carl Gherardi
|
||||||
|
@ -32,6 +32,7 @@ class Absolute(HandHistoryConverter):
|
||||||
filetype = "text"
|
filetype = "text"
|
||||||
codepage = "cp1252"
|
codepage = "cp1252"
|
||||||
siteid = 8
|
siteid = 8
|
||||||
|
HORSEHand = False
|
||||||
|
|
||||||
# Static regexes
|
# Static regexes
|
||||||
re_SplitHands = re.compile(r"\n\n\n+")
|
re_SplitHands = re.compile(r"\n\n\n+")
|
||||||
|
@ -41,8 +42,11 @@ class Absolute(HandHistoryConverter):
|
||||||
#Seat 6 - FETS63 ($0.75 in chips)
|
#Seat 6 - FETS63 ($0.75 in chips)
|
||||||
#Board [10s 5d Kh Qh 8c]
|
#Board [10s 5d Kh Qh 8c]
|
||||||
|
|
||||||
re_GameInfo = re.compile(ur"^Stage #([0-9]+): (?P<GAME>Holdem|) (?P<LIMIT>No Limit|Pot Limit|Normal) (?P<CURRENCY>\$| €|)(?P<BB>[0-9]*[.0-9]+)", re.MULTILINE)
|
re_GameInfo = re.compile(ur"^Stage #([0-9]+): (?P<GAME>Holdem|HORSE)(?: \(1 on 1\)|)? ?(?P<LIMIT>No Limit|Pot Limit|Normal|)? ?(?P<CURRENCY>\$| €|)(?P<SB>[.0-9]+)/?(?:\$| €|)(?P<BB>[.0-9]+)?", re.MULTILINE)
|
||||||
re_HandInfo = re.compile(ur"^Stage #(?P<HID>[0-9]+): .*(?P<DATETIME>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).*\nTable: (?P<TABLE>.*) \(Real Money\)", re.MULTILINE)
|
re_HorseGameInfo = re.compile(ur"^Game Type: (?P<LIMIT>Limit) (?P<GAME>Holdem)", re.MULTILINE)
|
||||||
|
# TODO: can set max seats via (1 on 1) to a known 2 ..
|
||||||
|
re_HandInfo = re.compile(ur"^Stage #(?P<HID>[0-9]+): .*(?P<DATETIME>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d).*\n(Table: (?P<TABLE>.*) \(Real Money\))?", re.MULTILINE)
|
||||||
|
re_TableFromFilename = re.compile(ur".*IHH([0-9]+) (?P<TABLE>.*) -") # on HORSE STUD games, the table name isn't in the hand info!
|
||||||
re_Button = re.compile(ur"Seat #(?P<BUTTON>[0-9]) is the ?[dead]* dealer$", re.MULTILINE) # TODO: that's not the right way to match for "dead" dealer is it?
|
re_Button = re.compile(ur"Seat #(?P<BUTTON>[0-9]) is the ?[dead]* dealer$", re.MULTILINE) # TODO: that's not the right way to match for "dead" dealer is it?
|
||||||
re_PlayerInfo = re.compile(ur"^Seat (?P<SEAT>[0-9]) - (?P<PNAME>.*) \((?:\$| €|)(?P<CASH>[0-9]*[.0-9]+) in chips\)", re.MULTILINE)
|
re_PlayerInfo = re.compile(ur"^Seat (?P<SEAT>[0-9]) - (?P<PNAME>.*) \((?:\$| €|)(?P<CASH>[0-9]*[.0-9]+) in chips\)", re.MULTILINE)
|
||||||
re_Board = re.compile(ur"\[(?P<CARDS>[^\]]*)\]? *$", re.MULTILINE)
|
re_Board = re.compile(ur"\[(?P<CARDS>[^\]]*)\]? *$", re.MULTILINE)
|
||||||
|
@ -69,7 +73,7 @@ class Absolute(HandHistoryConverter):
|
||||||
self.re_Action = re.compile(ur"^%s - (?P<ATYPE>Bets |Raises |All-In |All-In\(Raise\) |Calls |Folds|Checks)?\$?(?P<BET>[0-9]*[.0-9]+)?" % player_re, re.MULTILINE)
|
self.re_Action = re.compile(ur"^%s - (?P<ATYPE>Bets |Raises |All-In |All-In\(Raise\) |Calls |Folds|Checks)?\$?(?P<BET>[0-9]*[.0-9]+)?" % player_re, re.MULTILINE)
|
||||||
# print "^%s - (?P<ATYPE>Bets |Raises |All-In |All-In\(Raise\) |Calls |Folds|Checks)?\$?(?P<BET>[0-9]*[.0-9]+)?" % player_re
|
# print "^%s - (?P<ATYPE>Bets |Raises |All-In |All-In\(Raise\) |Calls |Folds|Checks)?\$?(?P<BET>[0-9]*[.0-9]+)?" % player_re
|
||||||
self.re_ShowdownAction = re.compile(ur"^%s - Shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
self.re_ShowdownAction = re.compile(ur"^%s - Shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
||||||
self.re_CollectPot = re.compile(ur"^Seat [0-9]: %s(?: \(dealer\)| \(big blind\)| \(small blind\)|) (?:won|collected) Total \((?:\$| €|)(?P<POT>[0-9]*[.0-9]+)\)" % player_re, re.MULTILINE)
|
self.re_CollectPot = re.compile(ur"^Seat [0-9]: %s(?: \(dealer\)|)(?: \(big blind\)| \(small blind\)|) (?:won|collected) Total \((?:\$| €|)(?P<POT>[0-9]*[.0-9]+)\)" % player_re, re.MULTILINE)
|
||||||
#self.re_PostSB = re.compile(ur"^%s: posts small blind \[(?:\$| €|) (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
#self.re_PostSB = re.compile(ur"^%s: posts small blind \[(?:\$| €|) (?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
#self.re_PostBB = re.compile(ur"^%s: posts big blind \[(?:\$| €|) (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
#self.re_PostBB = re.compile(ur"^%s: posts big blind \[(?:\$| €|) (?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
#self.re_PostBoth = re.compile(ur"^%s: posts both blinds \[(?:\$| €|) (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
#self.re_PostBoth = re.compile(ur"^%s: posts both blinds \[(?:\$| €|) (?P<SBBB>[.0-9]+)" % player_re, re.MULTILINE)
|
||||||
|
@ -112,7 +116,7 @@ or None if we fail to get the info """
|
||||||
mg = m.groupdict()
|
mg = m.groupdict()
|
||||||
|
|
||||||
# translations from captured groups to our info strings
|
# translations from captured groups to our info strings
|
||||||
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Normal':'fl' }
|
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Normal':'fl', 'Limit':'fl'}
|
||||||
games = { # base, category
|
games = { # base, category
|
||||||
"Holdem" : ('hold','holdem'),
|
"Holdem" : ('hold','holdem'),
|
||||||
'Omaha' : ('hold','omahahi'),
|
'Omaha' : ('hold','omahahi'),
|
||||||
|
@ -120,10 +124,22 @@ or None if we fail to get the info """
|
||||||
'7 Card Stud' : ('stud','studhi')
|
'7 Card Stud' : ('stud','studhi')
|
||||||
}
|
}
|
||||||
currencies = { u' €':'EUR', '$':'USD', '':'T$' }
|
currencies = { u' €':'EUR', '$':'USD', '':'T$' }
|
||||||
if 'LIMIT' in mg:
|
if 'GAME' in mg and mg['GAME'] == "HORSE": # if we're a HORSE game, the game type is on the next line
|
||||||
info['limitType'] = limits[mg['LIMIT']]
|
self.HORSEHand = True
|
||||||
|
m = self.re_HorseGameInfo.search(handText)
|
||||||
|
if not m:
|
||||||
|
return None # it's a HORSE game and we don't understand the game type
|
||||||
|
temp = m.groupdict()
|
||||||
|
#print "AP HORSE processing"
|
||||||
|
if 'GAME' not in temp or 'LIMIT' not in temp:
|
||||||
|
return None # sort of understood it but not really
|
||||||
|
#print "temp=", temp
|
||||||
|
mg['GAME'] = temp['GAME']
|
||||||
|
mg['LIMIT'] = temp['LIMIT']
|
||||||
if 'GAME' in mg:
|
if 'GAME' in mg:
|
||||||
(info['base'], info['category']) = games[mg['GAME']]
|
(info['base'], info['category']) = games[mg['GAME']]
|
||||||
|
if 'LIMIT' in mg:
|
||||||
|
info['limitType'] = limits[mg['LIMIT']]
|
||||||
if 'SB' in mg:
|
if 'SB' in mg:
|
||||||
info['sb'] = mg['SB']
|
info['sb'] = mg['SB']
|
||||||
else:
|
else:
|
||||||
|
@ -135,6 +151,11 @@ or None if we fail to get the info """
|
||||||
if info['currency'] == 'T$':
|
if info['currency'] == 'T$':
|
||||||
info['type'] = 'tour'
|
info['type'] = 'tour'
|
||||||
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
|
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
|
||||||
|
if info['bb'] is None:
|
||||||
|
info['bb'] = mg['SB']
|
||||||
|
info['sb'] = str(float(mg['SB']) * 0.5) # TODO: AP does provide Small BET for Limit .. I think? at least 1-on-1 limit they do.. sigh
|
||||||
|
|
||||||
|
#print info;
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
@ -147,9 +168,15 @@ or None if we fail to get the info """
|
||||||
return None
|
return None
|
||||||
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
|
logging.debug("HID %s, Table %s" % (m.group('HID'), m.group('TABLE')))
|
||||||
hand.handid = m.group('HID')
|
hand.handid = m.group('HID')
|
||||||
hand.tablename = m.group('TABLE')
|
if m.group('TABLE'):
|
||||||
|
hand.tablename = m.group('TABLE')
|
||||||
|
else:
|
||||||
|
t = self.re_TableFromFilename.search(self.in_path)
|
||||||
|
hand.tablename = t.group('TABLE')
|
||||||
hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since absolute doesn't give seat max info
|
hand.maxseats = 6 # assume 6-max unless we have proof it's a larger/smaller game, since absolute doesn't give seat max info
|
||||||
|
# TODO: (1-on-1) does have that info in the game type line
|
||||||
|
if self.HORSEHand:
|
||||||
|
hand.maxseats = 8
|
||||||
hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%Y-%m-%d %H:%M:%S")
|
hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%Y-%m-%d %H:%M:%S")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,11 @@ import shutil
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
from xml.dom.minidom import Node
|
from xml.dom.minidom import Node
|
||||||
|
|
||||||
|
import logging, logging.config
|
||||||
|
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
|
||||||
|
log = logging.getLogger("config")
|
||||||
|
log.debug("config logger initialised")
|
||||||
|
|
||||||
def fix_tf(x, default = True):
|
def fix_tf(x, default = True):
|
||||||
# The xml parser doesn't translate "True" to True. Therefore, we never get
|
# The xml parser doesn't translate "True" to True. Therefore, we never get
|
||||||
# True or False from the parser only "True" or "False". So translate the
|
# True or False from the parser only "True" or "False". So translate the
|
||||||
|
@ -201,6 +206,9 @@ class Database:
|
||||||
self.db_user = node.getAttribute("db_user")
|
self.db_user = node.getAttribute("db_user")
|
||||||
self.db_type = node.getAttribute("db_type")
|
self.db_type = node.getAttribute("db_type")
|
||||||
self.db_pass = node.getAttribute("db_pass")
|
self.db_pass = node.getAttribute("db_pass")
|
||||||
|
self.db_selected = fix_tf(node.getAttribute("default"),"False")
|
||||||
|
log.debug("Database db_name:'%(name)s' db_server:'%(server)s' db_ip:'%(ip)s' db_user:'%(user)s' db_type:'%(type)s' db_pass (not logged) selected:'%(sel)s'" \
|
||||||
|
% { 'name':self.db_name, 'server':self.db_server, 'ip':self.db_ip, 'user':self.db_user, 'type':self.db_type, 'sel':self.db_selected} )
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
temp = 'Database = ' + self.db_name + '\n'
|
temp = 'Database = ' + self.db_name + '\n'
|
||||||
|
@ -208,7 +216,7 @@ class Database:
|
||||||
if key.startswith('__'): continue
|
if key.startswith('__'): continue
|
||||||
value = getattr(self, key)
|
value = getattr(self, key)
|
||||||
if callable(value): continue
|
if callable(value): continue
|
||||||
temp = temp + ' ' + key + " = " + value + "\n"
|
temp = temp + ' ' + key + " = " + repr(value) + "\n"
|
||||||
return temp
|
return temp
|
||||||
|
|
||||||
class Aux_window:
|
class Aux_window:
|
||||||
|
@ -258,6 +266,7 @@ class Popup:
|
||||||
|
|
||||||
class Import:
|
class Import:
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
|
self.node = node
|
||||||
self.interval = node.getAttribute("interval")
|
self.interval = node.getAttribute("interval")
|
||||||
self.callFpdbHud = node.getAttribute("callFpdbHud")
|
self.callFpdbHud = node.getAttribute("callFpdbHud")
|
||||||
self.hhArchiveBase = node.getAttribute("hhArchiveBase")
|
self.hhArchiveBase = node.getAttribute("hhArchiveBase")
|
||||||
|
@ -279,11 +288,10 @@ class Tv:
|
||||||
(self.combinedStealFold, self.combined2B3B, self.combinedPostflop) )
|
(self.combinedStealFold, self.combined2B3B, self.combinedPostflop) )
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
def __init__(self, file = None, dbname = 'fpdb'):
|
def __init__(self, file = None, dbname = ''):
|
||||||
|
|
||||||
# "file" is a path to an xml file with the fpdb/HUD configuration
|
# "file" is a path to an xml file with the fpdb/HUD configuration
|
||||||
# we check the existence of "file" and try to recover if it doesn't exist
|
# we check the existence of "file" and try to recover if it doesn't exist
|
||||||
self.dbname = dbname
|
|
||||||
|
|
||||||
self.default_config_path = self.get_default_config_path()
|
self.default_config_path = self.get_default_config_path()
|
||||||
if file != None: # configuration file path has been passed
|
if file != None: # configuration file path has been passed
|
||||||
|
@ -309,10 +317,10 @@ class Config:
|
||||||
# Parse even if there was no real config file found and we are using the example
|
# Parse even if there was no real config file found and we are using the example
|
||||||
# If using the example, we'll edit it later
|
# If using the example, we'll edit it later
|
||||||
try:
|
try:
|
||||||
print "Reading configuration file %s\n" % (file)
|
log.info("Reading configuration file %s" % (file))
|
||||||
doc = xml.dom.minidom.parse(file)
|
doc = xml.dom.minidom.parse(file)
|
||||||
except:
|
except:
|
||||||
print "Error parsing %s. See error log file." % (file)
|
log.error("Error parsing %s. See error log file." % (file))
|
||||||
traceback.print_exc(file=sys.stderr)
|
traceback.print_exc(file=sys.stderr)
|
||||||
print "press enter to continue"
|
print "press enter to continue"
|
||||||
sys.stdin.readline()
|
sys.stdin.readline()
|
||||||
|
@ -338,9 +346,26 @@ class Config:
|
||||||
self.supported_games[game.game_name] = game
|
self.supported_games[game.game_name] = game
|
||||||
|
|
||||||
# s_dbs = doc.getElementsByTagName("supported_databases")
|
# s_dbs = doc.getElementsByTagName("supported_databases")
|
||||||
|
# select database from those defined in config by:
|
||||||
|
# 1) command line option
|
||||||
|
# or 2) selected="True" in config element
|
||||||
|
# or 3) just choose the first we come across
|
||||||
for db_node in doc.getElementsByTagName("database"):
|
for db_node in doc.getElementsByTagName("database"):
|
||||||
db = Database(node = db_node)
|
try:
|
||||||
self.supported_databases[db.db_name] = db
|
db = Database(node = db_node)
|
||||||
|
if db.db_name in self.supported_databases:
|
||||||
|
raise FpdbError("Database names must be unique")
|
||||||
|
# If there is only one Database node, or none are marked default, the first is selected
|
||||||
|
if len(self.supported_databases) == 0:
|
||||||
|
self.db_selected = db.db_name
|
||||||
|
self.supported_databases[db.db_name] = db
|
||||||
|
if db.db_selected:
|
||||||
|
self.db_selected = db.db_name
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
if dbname and dbname in self.supported_databases:
|
||||||
|
self.db_selected = dbname
|
||||||
|
|
||||||
|
|
||||||
# s_dbs = doc.getElementsByTagName("mucked_windows")
|
# s_dbs = doc.getElementsByTagName("mucked_windows")
|
||||||
for aw_node in doc.getElementsByTagName("aw"):
|
for aw_node in doc.getElementsByTagName("aw"):
|
||||||
|
@ -377,6 +402,8 @@ class Config:
|
||||||
db_pass = df_parms['db-password'])
|
db_pass = df_parms['db-password'])
|
||||||
self.save(file=os.path.join(self.default_config_path, "HUD_config.xml"))
|
self.save(file=os.path.join(self.default_config_path, "HUD_config.xml"))
|
||||||
|
|
||||||
|
def set_hhArchiveBase(self, path):
|
||||||
|
self.imp.node.setAttribute("hhArchiveBase", path)
|
||||||
|
|
||||||
def find_config(self):
|
def find_config(self):
|
||||||
"""Looks in cwd and in self.default_config_path for a config file."""
|
"""Looks in cwd and in self.default_config_path for a config file."""
|
||||||
|
@ -507,7 +534,7 @@ class Config:
|
||||||
|
|
||||||
def get_db_parameters(self):
|
def get_db_parameters(self):
|
||||||
db = {}
|
db = {}
|
||||||
name = self.dbname
|
name = self.db_selected
|
||||||
try: db['db-databaseName'] = name
|
try: db['db-databaseName'] = name
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ Create and manage the database objects.
|
||||||
# postmaster -D /var/lib/pgsql/data
|
# postmaster -D /var/lib/pgsql/data
|
||||||
|
|
||||||
# Standard Library modules
|
# Standard Library modules
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from datetime import datetime, date, time, timedelta
|
from datetime import datetime, date, time, timedelta
|
||||||
|
@ -31,7 +32,6 @@ from time import time, strftime, sleep
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
import string
|
import string
|
||||||
import re
|
import re
|
||||||
import logging
|
|
||||||
import Queue
|
import Queue
|
||||||
|
|
||||||
# pyGTK modules
|
# pyGTK modules
|
||||||
|
@ -42,6 +42,12 @@ import fpdb_simple
|
||||||
import Configuration
|
import Configuration
|
||||||
import SQL
|
import SQL
|
||||||
import Card
|
import Card
|
||||||
|
import Tourney
|
||||||
|
from Exceptions import *
|
||||||
|
|
||||||
|
import logging, logging.config
|
||||||
|
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
|
||||||
|
log = logging.getLogger('db')
|
||||||
|
|
||||||
class Database:
|
class Database:
|
||||||
|
|
||||||
|
@ -93,6 +99,14 @@ class Database:
|
||||||
, {'tab':'TourneyTypes', 'col':'siteId', 'drop':0}
|
, {'tab':'TourneyTypes', 'col':'siteId', 'drop':0}
|
||||||
]
|
]
|
||||||
, [ # indexes for sqlite (list index 4)
|
, [ # indexes for sqlite (list index 4)
|
||||||
|
{'tab':'Players', 'col':'name', 'drop':0}
|
||||||
|
, {'tab':'Hands', 'col':'siteHandNo', 'drop':0}
|
||||||
|
, {'tab':'Hands', 'col':'gametypeId', 'drop':0}
|
||||||
|
, {'tab':'HandsPlayers', 'col':'handId', 'drop':0}
|
||||||
|
, {'tab':'HandsPlayers', 'col':'playerId', 'drop':0}
|
||||||
|
, {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0}
|
||||||
|
, {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0}
|
||||||
|
, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -161,8 +175,14 @@ class Database:
|
||||||
# CREATE INDEX idx ON tab(col)
|
# CREATE INDEX idx ON tab(col)
|
||||||
# DROP INDEX idx
|
# DROP INDEX idx
|
||||||
|
|
||||||
|
# SQLite notes:
|
||||||
|
|
||||||
|
# To add an index:
|
||||||
|
# create index indexname on tablename (col);
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more
|
def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more
|
||||||
print "\ncreating Database instance, sql =", sql
|
log.info("Creating Database instance, sql = %s" % sql)
|
||||||
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
|
self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql
|
||||||
self.fdb.do_connect(c)
|
self.fdb.do_connect(c)
|
||||||
self.connection = self.fdb.db
|
self.connection = self.fdb.db
|
||||||
|
@ -179,12 +199,18 @@ class Database:
|
||||||
#ISOLATION_LEVEL_READ_COMMITTED = 1
|
#ISOLATION_LEVEL_READ_COMMITTED = 1
|
||||||
#ISOLATION_LEVEL_SERIALIZABLE = 2
|
#ISOLATION_LEVEL_SERIALIZABLE = 2
|
||||||
|
|
||||||
|
|
||||||
# where possible avoid creating new SQL instance by using the global one passed in
|
# where possible avoid creating new SQL instance by using the global one passed in
|
||||||
if sql == None:
|
if sql == None:
|
||||||
self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server'])
|
self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server'])
|
||||||
else:
|
else:
|
||||||
self.sql = sql
|
self.sql = sql
|
||||||
|
|
||||||
|
if self.backend == self.SQLITE and db_params['db-databaseName'] == ':memory:' and self.fdb.wrongDbVersion:
|
||||||
|
log.info("sqlite/:memory: - creating")
|
||||||
|
self.recreate_tables()
|
||||||
|
self.fdb.wrongDbVersion = False
|
||||||
|
|
||||||
self.pcache = None # PlayerId cache
|
self.pcache = None # PlayerId cache
|
||||||
self.cachemiss = 0 # Delete me later - using to count player cache misses
|
self.cachemiss = 0 # Delete me later - using to count player cache misses
|
||||||
self.cachehit = 0 # Delete me later - using to count player cache hits
|
self.cachehit = 0 # Delete me later - using to count player cache hits
|
||||||
|
@ -244,7 +270,7 @@ class Database:
|
||||||
elif self.backend==4:
|
elif self.backend==4:
|
||||||
return "SQLite"
|
return "SQLite"
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("invalid backend")
|
raise FpdbError("invalid backend")
|
||||||
|
|
||||||
def get_table_name(self, hand_id):
|
def get_table_name(self, hand_id):
|
||||||
c = self.connection.cursor()
|
c = self.connection.cursor()
|
||||||
|
@ -439,7 +465,7 @@ class Database:
|
||||||
if colnames[0].lower() == 'player_id':
|
if colnames[0].lower() == 'player_id':
|
||||||
playerid = row[0]
|
playerid = row[0]
|
||||||
else:
|
else:
|
||||||
print "ERROR: query %s result does not have player_id as first column" % (query,)
|
log.error("ERROR: query %s result does not have player_id as first column" % (query,))
|
||||||
break
|
break
|
||||||
|
|
||||||
for name, val in zip(colnames, row):
|
for name, val in zip(colnames, row):
|
||||||
|
@ -480,7 +506,7 @@ class Database:
|
||||||
if self.backend == self.MYSQL_INNODB:
|
if self.backend == self.MYSQL_INNODB:
|
||||||
ret = self.connection.insert_id()
|
ret = self.connection.insert_id()
|
||||||
if ret < 1 or ret > 999999999:
|
if ret < 1 or ret > 999999999:
|
||||||
print "getLastInsertId(): problem fetching insert_id? ret=", ret
|
log.warning("getLastInsertId(): problem fetching insert_id? ret=%d" % ret)
|
||||||
ret = -1
|
ret = -1
|
||||||
elif self.backend == self.PGSQL:
|
elif self.backend == self.PGSQL:
|
||||||
# some options:
|
# some options:
|
||||||
|
@ -492,14 +518,14 @@ class Database:
|
||||||
ret = c.execute ("SELECT lastval()")
|
ret = c.execute ("SELECT lastval()")
|
||||||
row = c.fetchone()
|
row = c.fetchone()
|
||||||
if not row:
|
if not row:
|
||||||
print "getLastInsertId(%s): problem fetching lastval? row=" % seq, row
|
log.warning("getLastInsertId(%s): problem fetching lastval? row=%d" % (seq, row))
|
||||||
ret = -1
|
ret = -1
|
||||||
else:
|
else:
|
||||||
ret = row[0]
|
ret = row[0]
|
||||||
elif self.backend == self.SQLITE:
|
elif self.backend == self.SQLITE:
|
||||||
ret = cursor.lastrowid
|
ret = cursor.lastrowid
|
||||||
else:
|
else:
|
||||||
print "getLastInsertId(): unknown backend ", self.backend
|
log.error("getLastInsertId(): unknown backend: %d" % self.backend)
|
||||||
ret = -1
|
ret = -1
|
||||||
except:
|
except:
|
||||||
ret = -1
|
ret = -1
|
||||||
|
@ -584,7 +610,7 @@ class Database:
|
||||||
hands_players_ids = self.store_hands_players_holdem_omaha_tourney(
|
hands_players_ids = self.store_hands_players_holdem_omaha_tourney(
|
||||||
self.backend, category, hands_id, player_ids, start_cashes, positions
|
self.backend, category, hands_id, player_ids, start_cashes, positions
|
||||||
, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids
|
, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids
|
||||||
, hudImportData)
|
, hudImportData, tourneyTypeId)
|
||||||
|
|
||||||
#print "tourney holdem, backend=%d" % backend
|
#print "tourney holdem, backend=%d" % backend
|
||||||
if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop':
|
if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop':
|
||||||
|
@ -612,7 +638,7 @@ class Database:
|
||||||
|
|
||||||
hands_players_ids = self.store_hands_players_stud_tourney(self.backend, hands_id
|
hands_players_ids = self.store_hands_players_stud_tourney(self.backend, hands_id
|
||||||
, playerIds, startCashes, antes, cardValues, cardSuits
|
, playerIds, startCashes, antes, cardValues, cardSuits
|
||||||
, winnings, rakes, seatNos, tourneys_players_ids)
|
, winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId)
|
||||||
|
|
||||||
if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop':
|
if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop':
|
||||||
self.storeHudCache(self.backend, base, category, gametypeId, hand_start_time, playerIds, hudImportData)
|
self.storeHudCache(self.backend, base, category, gametypeId, hand_start_time, playerIds, hudImportData)
|
||||||
|
@ -823,16 +849,16 @@ class Database:
|
||||||
self.create_tables()
|
self.create_tables()
|
||||||
self.createAllIndexes()
|
self.createAllIndexes()
|
||||||
self.commit()
|
self.commit()
|
||||||
print "Finished recreating tables"
|
log.info("Finished recreating tables")
|
||||||
#end def recreate_tables
|
#end def recreate_tables
|
||||||
|
|
||||||
def create_tables(self):
|
def create_tables(self):
|
||||||
#todo: should detect and fail gracefully if tables already exist.
|
#todo: should detect and fail gracefully if tables already exist.
|
||||||
try:
|
try:
|
||||||
logging.debug(self.sql.query['createSettingsTable'])
|
log.debug(self.sql.query['createSettingsTable'])
|
||||||
c = self.get_cursor()
|
c = self.get_cursor()
|
||||||
c.execute(self.sql.query['createSettingsTable'])
|
c.execute(self.sql.query['createSettingsTable'])
|
||||||
logging.debug(self.sql.query['createSitesTable'])
|
log.debug(self.sql.query['createSitesTable'])
|
||||||
c.execute(self.sql.query['createSitesTable'])
|
c.execute(self.sql.query['createSitesTable'])
|
||||||
c.execute(self.sql.query['createGametypesTable'])
|
c.execute(self.sql.query['createGametypesTable'])
|
||||||
c.execute(self.sql.query['createPlayersTable'])
|
c.execute(self.sql.query['createPlayersTable'])
|
||||||
|
@ -859,35 +885,51 @@ class Database:
|
||||||
|
|
||||||
def drop_tables(self):
|
def drop_tables(self):
|
||||||
"""Drops the fpdb tables from the current db"""
|
"""Drops the fpdb tables from the current db"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
c = self.get_cursor()
|
c = self.get_cursor()
|
||||||
if(self.get_backend_name() == 'MySQL InnoDB'):
|
|
||||||
#Databases with FOREIGN KEY support need this switched of before you can drop tables
|
|
||||||
self.drop_referential_integrity()
|
|
||||||
|
|
||||||
# Query the DB to see what tables exist
|
|
||||||
c.execute(self.sql.query['list_tables'])
|
|
||||||
for table in c:
|
|
||||||
c.execute(self.sql.query['drop_table'] + table[0])
|
|
||||||
elif(self.get_backend_name() == 'PostgreSQL'):
|
|
||||||
self.commit()# I have no idea why this makes the query work--REB 07OCT2008
|
|
||||||
c.execute(self.sql.query['list_tables'])
|
|
||||||
tables = c.fetchall()
|
|
||||||
for table in tables:
|
|
||||||
c.execute(self.sql.query['drop_table'] + table[0] + ' cascade')
|
|
||||||
elif(self.get_backend_name() == 'SQLite'):
|
|
||||||
c.execute(self.sql.query['list_tables'])
|
|
||||||
for table in c.fetchall():
|
|
||||||
logging.debug(self.sql.query['drop_table'] + table[0])
|
|
||||||
c.execute(self.sql.query['drop_table'] + table[0])
|
|
||||||
|
|
||||||
self.commit()
|
|
||||||
except:
|
except:
|
||||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
print "*** Error unable to get cursor"
|
||||||
print "***Error dropping tables: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
else:
|
||||||
self.rollback()
|
backend = self.get_backend_name()
|
||||||
raise
|
if backend == 'MySQL InnoDB': # what happens if someone is using MyISAM?
|
||||||
|
try:
|
||||||
|
self.drop_referential_integrity() # needed to drop tables with foreign keys
|
||||||
|
c.execute(self.sql.query['list_tables'])
|
||||||
|
tables = c.fetchall()
|
||||||
|
for table in tables:
|
||||||
|
c.execute(self.sql.query['drop_table'] + table[0])
|
||||||
|
except:
|
||||||
|
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||||
|
print "***Error dropping tables: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||||
|
self.rollback()
|
||||||
|
elif backend == 'PostgreSQL':
|
||||||
|
try:
|
||||||
|
self.commit()
|
||||||
|
c.execute(self.sql.query['list_tables'])
|
||||||
|
tables = c.fetchall()
|
||||||
|
for table in tables:
|
||||||
|
c.execute(self.sql.query['drop_table'] + table[0] + ' cascade')
|
||||||
|
except:
|
||||||
|
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||||
|
print "***Error dropping tables: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||||
|
self.rollback()
|
||||||
|
elif backend == 'SQLite':
|
||||||
|
try:
|
||||||
|
c.execute(self.sql.query['list_tables'])
|
||||||
|
for table in c.fetchall():
|
||||||
|
log.debug(self.sql.query['drop_table'] + table[0])
|
||||||
|
c.execute(self.sql.query['drop_table'] + table[0])
|
||||||
|
except:
|
||||||
|
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||||
|
print "***Error dropping tables: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||||
|
self.rollback()
|
||||||
|
try:
|
||||||
|
self.commit()
|
||||||
|
except:
|
||||||
|
print "*** Error in committing table drop"
|
||||||
|
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||||
|
print "***Error dropping tables: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||||
|
self.rollback()
|
||||||
#end def drop_tables
|
#end def drop_tables
|
||||||
|
|
||||||
def createAllIndexes(self):
|
def createAllIndexes(self):
|
||||||
|
@ -912,14 +954,21 @@ class Database:
|
||||||
self.get_cursor().execute(s)
|
self.get_cursor().execute(s)
|
||||||
except:
|
except:
|
||||||
print " create idx failed: " + str(sys.exc_info())
|
print " create idx failed: " + str(sys.exc_info())
|
||||||
|
elif self.backend == self.SQLITE:
|
||||||
|
log.debug("Creating sqlite index %s %s" % (idx['tab'], idx['col']))
|
||||||
|
try:
|
||||||
|
s = "create index %s_%s_idx on %s(%s)" % (idx['tab'], idx['col'], idx['tab'], idx['col'])
|
||||||
|
self.get_cursor().execute(s)
|
||||||
|
except:
|
||||||
|
log.debug("Create idx failed: " + str(sys.exc_info()))
|
||||||
else:
|
else:
|
||||||
print "Only MySQL and Postgres supported so far"
|
print "Only MySQL, Postgres and SQLite supported so far"
|
||||||
return -1
|
return -1
|
||||||
if self.backend == self.PGSQL:
|
if self.backend == self.PGSQL:
|
||||||
self.connection.set_isolation_level(1) # go back to normal isolation level
|
self.connection.set_isolation_level(1) # go back to normal isolation level
|
||||||
except:
|
except:
|
||||||
print "Error creating indexes: " + str(sys.exc_value)
|
print "Error creating indexes: " + str(sys.exc_value)
|
||||||
raise fpdb_simple.FpdbError( "Error creating indexes " + str(sys.exc_value) )
|
raise FpdbError( "Error creating indexes " + str(sys.exc_value) )
|
||||||
#end def createAllIndexes
|
#end def createAllIndexes
|
||||||
|
|
||||||
def dropAllIndexes(self):
|
def dropAllIndexes(self):
|
||||||
|
@ -964,12 +1013,10 @@ class Database:
|
||||||
c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')")
|
c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')")
|
||||||
c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')")
|
c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')")
|
||||||
if self.backend == self.SQLITE:
|
if self.backend == self.SQLITE:
|
||||||
c.execute("INSERT INTO TourneyTypes VALUES (NULL, 1, 0, 0, 0, 0);")
|
c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);")
|
||||||
else:
|
else:
|
||||||
c.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);")
|
c.execute("insert into TourneyTypes values (0,1,0,0,0,0,0,null,0,0,0);")
|
||||||
#c.execute("""INSERT INTO TourneyTypes
|
|
||||||
# (siteId,buyin,fee,knockout,rebuyOrAddon) VALUES
|
|
||||||
# (1,0,0,0,?)""",(False,) )
|
|
||||||
#end def fillDefaultData
|
#end def fillDefaultData
|
||||||
|
|
||||||
def rebuild_hudcache(self):
|
def rebuild_hudcache(self):
|
||||||
|
@ -1107,7 +1154,7 @@ class Database:
|
||||||
, h.allIns, h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats
|
, h.allIns, h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats
|
||||||
, h.tableName, h.seatNos)
|
, h.tableName, h.seatNos)
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("unrecognised category")
|
raise FpdbError("unrecognised category")
|
||||||
else:
|
else:
|
||||||
if h.base == "hold":
|
if h.base == "hold":
|
||||||
result = self.ring_holdem_omaha(
|
result = self.ring_holdem_omaha(
|
||||||
|
@ -1125,7 +1172,7 @@ class Database:
|
||||||
, h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats, h.tableName
|
, h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats, h.tableName
|
||||||
, h.seatNos)
|
, h.seatNos)
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("unrecognised category")
|
raise FpdbError("unrecognised category")
|
||||||
except:
|
except:
|
||||||
print "Error storing hand: " + str(sys.exc_value)
|
print "Error storing hand: " + str(sys.exc_value)
|
||||||
self.rollback()
|
self.rollback()
|
||||||
|
@ -1245,7 +1292,7 @@ class Database:
|
||||||
ret = self.get_last_insert_id(c)
|
ret = self.get_last_insert_id(c)
|
||||||
except:
|
except:
|
||||||
ret = -1
|
ret = -1
|
||||||
raise fpdb_simple.FpdbError( "storeHands error: " + str(sys.exc_value) )
|
raise FpdbError( "storeHands error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
#end def storeHands
|
#end def storeHands
|
||||||
|
@ -1280,10 +1327,10 @@ class Database:
|
||||||
card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2])
|
card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2])
|
||||||
card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3])
|
card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3])
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("invalid category")
|
raise FpdbError("invalid category")
|
||||||
|
|
||||||
inserts.append( (
|
inserts.append( (
|
||||||
hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid
|
hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid - needed for hudcache
|
||||||
card1, card2, card3, card4, startCards,
|
card1, card2, card3, card4, startCards,
|
||||||
winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i],
|
winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i],
|
||||||
hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
|
hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
|
||||||
|
@ -1314,7 +1361,7 @@ class Database:
|
||||||
c = self.get_cursor()
|
c = self.get_cursor()
|
||||||
c.executemany ("""
|
c.executemany ("""
|
||||||
INSERT INTO HandsPlayers
|
INSERT INTO HandsPlayers
|
||||||
(handId, playerId, startCash, position, tourneyTypeId,
|
(handId, playerId, startCash, position, tourneyTypeId,
|
||||||
card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit,
|
card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit,
|
||||||
street0VPI, street0Aggr, street0_3BChance, street0_3BDone,
|
street0VPI, street0Aggr, street0_3BChance, street0_3BDone,
|
||||||
street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown,
|
street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown,
|
||||||
|
@ -1339,7 +1386,7 @@ class Database:
|
||||||
,inserts )
|
,inserts )
|
||||||
result.append( self.get_last_insert_id(c) ) # wrong? not used currently
|
result.append( self.get_last_insert_id(c) ) # wrong? not used currently
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError( "store_hands_players_holdem_omaha error: " + str(sys.exc_value) )
|
raise FpdbError( "store_hands_players_holdem_omaha error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
return result
|
return result
|
||||||
#end def store_hands_players_holdem_omaha
|
#end def store_hands_players_holdem_omaha
|
||||||
|
@ -1377,7 +1424,7 @@ class Database:
|
||||||
#result.append(cursor.fetchall()[0][0])
|
#result.append(cursor.fetchall()[0][0])
|
||||||
result.append( self.get_last_insert_id(c) )
|
result.append( self.get_last_insert_id(c) )
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError( "store_hands_players_stud error: " + str(sys.exc_value) )
|
raise FpdbError( "store_hands_players_stud error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
return result
|
return result
|
||||||
#end def store_hands_players_stud
|
#end def store_hands_players_stud
|
||||||
|
@ -1385,7 +1432,7 @@ class Database:
|
||||||
def store_hands_players_holdem_omaha_tourney(self, backend, category, hands_id, player_ids
|
def store_hands_players_holdem_omaha_tourney(self, backend, category, hands_id, player_ids
|
||||||
,start_cashes, positions, card_values, card_suits
|
,start_cashes, positions, card_values, card_suits
|
||||||
,winnings, rakes, seatNos, tourneys_players_ids
|
,winnings, rakes, seatNos, tourneys_players_ids
|
||||||
,hudCache):
|
,hudCache, tourneyTypeId):
|
||||||
#stores hands_players for tourney holdem/omaha hands
|
#stores hands_players for tourney holdem/omaha hands
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1407,7 +1454,7 @@ class Database:
|
||||||
else:
|
else:
|
||||||
raise FpdbError ("invalid card_values length:"+str(len(card_values[0])))
|
raise FpdbError ("invalid card_values length:"+str(len(card_values[0])))
|
||||||
|
|
||||||
inserts.append( (hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid
|
inserts.append( (hands_id, player_ids[i], start_cashes[i], positions[i], tourneyTypeId,
|
||||||
card1, card2, card3, card4, startCards,
|
card1, card2, card3, card4, startCards,
|
||||||
winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], hudCache['totalProfit'][i],
|
winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], hudCache['totalProfit'][i],
|
||||||
hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
|
hudCache['street0VPI'][i], hudCache['street0Aggr'][i],
|
||||||
|
@ -1470,13 +1517,13 @@ class Database:
|
||||||
#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[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(cursor.fetchall()[0][0])
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError( "store_hands_players_holdem_omaha_tourney error: " + str(sys.exc_value) )
|
raise FpdbError( "store_hands_players_holdem_omaha_tourney error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
return result
|
return result
|
||||||
#end def store_hands_players_holdem_omaha_tourney
|
#end def store_hands_players_holdem_omaha_tourney
|
||||||
|
|
||||||
def store_hands_players_stud_tourney(self, backend, hands_id, player_ids, start_cashes,
|
def store_hands_players_stud_tourney(self, backend, hands_id, player_ids, start_cashes,
|
||||||
antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids):
|
antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId):
|
||||||
#stores hands_players for tourney stud/razz hands
|
#stores hands_players for tourney stud/razz hands
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1488,19 +1535,19 @@ class Database:
|
||||||
card1Value, card1Suit, card2Value, card2Suit,
|
card1Value, card1Suit, card2Value, card2Suit,
|
||||||
card3Value, card3Suit, card4Value, card4Suit,
|
card3Value, card3Suit, card4Value, card4Suit,
|
||||||
card5Value, card5Suit, card6Value, card6Suit,
|
card5Value, card5Suit, card6Value, card6Suit,
|
||||||
card7Value, card7Suit, winnings, rake, tourneysPlayersId, seatNo)
|
card7Value, card7Suit, winnings, rake, tourneysPlayersId, seatNo, tourneyTypeId)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
|
||||||
%s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']),
|
%s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']),
|
||||||
(hands_id, player_ids[i], start_cashes[i], antes[i],
|
(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][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][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][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], tourneys_players_ids[i], seatNos[i]))
|
card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], tourneyTypeId))
|
||||||
#cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[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(cursor.fetchall()[0][0])
|
||||||
result.append( self.get_last_insert_id(c) )
|
result.append( self.get_last_insert_id(c) )
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError( "store_hands_players_stud_tourney error: " + str(sys.exc_value) )
|
raise FpdbError( "store_hands_players_stud_tourney error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
return result
|
return result
|
||||||
#end def store_hands_players_stud_tourney
|
#end def store_hands_players_stud_tourney
|
||||||
|
@ -1697,7 +1744,7 @@ class Database:
|
||||||
# print "todo: implement storeHudCache for stud base"
|
# print "todo: implement storeHudCache for stud base"
|
||||||
|
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError( "storeHudCache error: " + str(sys.exc_value) )
|
raise FpdbError( "storeHudCache error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
#end def storeHudCache
|
#end def storeHudCache
|
||||||
|
|
||||||
|
@ -1720,7 +1767,7 @@ class Database:
|
||||||
tmp=cursor.fetchone()
|
tmp=cursor.fetchone()
|
||||||
#print "created new tourneys.id:",tmp
|
#print "created new tourneys.id:",tmp
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError( "store_tourneys error: " + str(sys.exc_value) )
|
raise FpdbError( "store_tourneys error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
return tmp[0]
|
return tmp[0]
|
||||||
#end def store_tourneys
|
#end def store_tourneys
|
||||||
|
@ -1753,7 +1800,7 @@ class Database:
|
||||||
#print "created new tourneys_players.id:",tmp
|
#print "created new tourneys_players.id:",tmp
|
||||||
result.append(tmp[0])
|
result.append(tmp[0])
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError( "store_tourneys_players error: " + str(sys.exc_value) )
|
raise FpdbError( "store_tourneys_players error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
return result
|
return result
|
||||||
#end def store_tourneys_players
|
#end def store_tourneys_players
|
||||||
|
@ -1834,6 +1881,236 @@ class Database:
|
||||||
print "***Error sending finish: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
print "***Error sending finish: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||||
# end def send_finish_msg():
|
# end def send_finish_msg():
|
||||||
|
|
||||||
|
def tRecogniseTourneyType(self, tourney):
|
||||||
|
logging.debug("Database.tRecogniseTourneyType")
|
||||||
|
typeId = 1
|
||||||
|
# Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype
|
||||||
|
cursor = self.get_cursor()
|
||||||
|
cursor.execute (self.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(tourney.tourNo, tourney.siteId)
|
||||||
|
)
|
||||||
|
result=cursor.fetchone()
|
||||||
|
|
||||||
|
expectedValues = { 1 : "buyin", 2 : "fee", 4 : "isKO", 5 : "isRebuy", 6 : "speed",
|
||||||
|
7 : "isHU", 8 : "isShootout", 9 : "isMatrix" }
|
||||||
|
typeIdMatch = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
len(result)
|
||||||
|
typeId = result[0]
|
||||||
|
logging.debug("Tourney found in db with Tourney_Type_ID = %d" % typeId)
|
||||||
|
for ev in expectedValues :
|
||||||
|
if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ):
|
||||||
|
logging.debug("TypeId mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) )
|
||||||
|
typeIdMatch = False
|
||||||
|
#break
|
||||||
|
except:
|
||||||
|
# Tourney not found : a TourneyTypeId has to be found or created for that specific tourney
|
||||||
|
typeIdMatch = False
|
||||||
|
|
||||||
|
if typeIdMatch == False :
|
||||||
|
# Check for an existing TTypeId that matches tourney info (buyin/fee, knockout, rebuy, speed, matrix, shootout)
|
||||||
|
# if not found create it
|
||||||
|
logging.debug("Searching for a TourneyTypeId matching TourneyType data")
|
||||||
|
cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO,
|
||||||
|
tourney.isRebuy, tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix)
|
||||||
|
)
|
||||||
|
result=cursor.fetchone()
|
||||||
|
|
||||||
|
try:
|
||||||
|
len(result)
|
||||||
|
typeId = result[0]
|
||||||
|
logging.debug("Existing Tourney Type Id found : %d" % typeId)
|
||||||
|
except TypeError: #this means we need to create a new entry
|
||||||
|
logging.debug("Tourney Type Id not found : create one")
|
||||||
|
cursor.execute (self.sql.query['insertTourneyTypes'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO, tourney.isRebuy,
|
||||||
|
tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix)
|
||||||
|
)
|
||||||
|
typeId = self.get_last_insert_id(cursor)
|
||||||
|
|
||||||
|
return typeId
|
||||||
|
#end def tRecogniseTourneyType
|
||||||
|
|
||||||
|
|
||||||
|
def tRecognizeTourney(self, tourney, dbTourneyTypeId):
|
||||||
|
logging.debug("Database.tRecognizeTourney")
|
||||||
|
tourneyID = 1
|
||||||
|
# Check if tourney exists in db (based on tourney.siteId and tourney.tourNo)
|
||||||
|
# If so retrieve all data to check for consistency
|
||||||
|
cursor = self.get_cursor()
|
||||||
|
cursor.execute (self.sql.query['getTourney'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(tourney.tourNo, tourney.siteId)
|
||||||
|
)
|
||||||
|
result=cursor.fetchone()
|
||||||
|
|
||||||
|
expectedValuesDecimal = { 2 : "entries", 3 : "prizepool", 6 : "buyInChips", 9 : "rebuyChips",
|
||||||
|
10 : "addOnChips", 11 : "rebuyAmount", 12 : "addOnAmount", 13 : "totalRebuys",
|
||||||
|
14 : "totalAddOns", 15 : "koBounty" }
|
||||||
|
expectedValues = { 7 : "tourneyName", 16 : "tourneyComment" }
|
||||||
|
|
||||||
|
tourneyDataMatch = True
|
||||||
|
tCommentTs = None
|
||||||
|
starttime = None
|
||||||
|
endtime = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
len(result)
|
||||||
|
tourneyID = result[0]
|
||||||
|
logging.debug("Tourney found in db with TourneyID = %d" % tourneyID)
|
||||||
|
if result[1] <> dbTourneyTypeId:
|
||||||
|
tourneyDataMatch = False
|
||||||
|
logging.debug("Tourney has wrong type ID (expected : %s - found : %s)" % (dbTourneyTypeId, result[1]))
|
||||||
|
if (tourney.starttime is None and result[4] is not None) or ( tourney.starttime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) <> result[4]) :
|
||||||
|
tourneyDataMatch = False
|
||||||
|
logging.debug("Tourney data mismatch : wrong starttime : Tourney=%s / db=%s" % (tourney.starttime, result[4]))
|
||||||
|
if (tourney.endtime is None and result[5] is not None) or ( tourney.endtime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) <> result[5]) :
|
||||||
|
tourneyDataMatch = False
|
||||||
|
logging.debug("Tourney data mismatch : wrong endtime : Tourney=%s / db=%s" % (tourney.endtime, result[5]))
|
||||||
|
|
||||||
|
for ev in expectedValues :
|
||||||
|
if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ):
|
||||||
|
logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) )
|
||||||
|
tourneyDataMatch = False
|
||||||
|
#break
|
||||||
|
for evD in expectedValuesDecimal :
|
||||||
|
if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD)) ) <> result[evD] ):
|
||||||
|
logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD)), result[evD]) )
|
||||||
|
tourneyDataMatch = False
|
||||||
|
#break
|
||||||
|
|
||||||
|
# TO DO : Deal with matrix summary mutliple parsings
|
||||||
|
|
||||||
|
except:
|
||||||
|
# Tourney not found : create
|
||||||
|
logging.debug("Tourney is not found : create")
|
||||||
|
if tourney.tourneyComment is not None :
|
||||||
|
tCommentTs = datetime.today()
|
||||||
|
if tourney.starttime is not None :
|
||||||
|
starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime)
|
||||||
|
if tourney.endtime is not None :
|
||||||
|
endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime)
|
||||||
|
# TODO : deal with matrix Id processed
|
||||||
|
cursor.execute (self.sql.query['insertTourney'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(dbTourneyTypeId, tourney.tourNo, tourney.entries, tourney.prizepool, starttime,
|
||||||
|
endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips,
|
||||||
|
tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty,
|
||||||
|
tourney.tourneyComment, tCommentTs)
|
||||||
|
)
|
||||||
|
tourneyID = self.get_last_insert_id(cursor)
|
||||||
|
|
||||||
|
|
||||||
|
# Deal with inconsistent tourney in db
|
||||||
|
if tourneyDataMatch == False :
|
||||||
|
# Update Tourney
|
||||||
|
if result[16] <> tourney.tourneyComment :
|
||||||
|
tCommentTs = datetime.today()
|
||||||
|
if tourney.starttime is not None :
|
||||||
|
starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime)
|
||||||
|
if tourney.endtime is not None :
|
||||||
|
endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime)
|
||||||
|
|
||||||
|
cursor.execute (self.sql.query['updateTourney'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(dbTourneyTypeId, tourney.entries, tourney.prizepool, starttime,
|
||||||
|
endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips,
|
||||||
|
tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty,
|
||||||
|
tourney.tourneyComment, tCommentTs, tourneyID)
|
||||||
|
)
|
||||||
|
|
||||||
|
return tourneyID
|
||||||
|
#end def tRecognizeTourney
|
||||||
|
|
||||||
|
def tStoreTourneyPlayers(self, tourney, dbTourneyId):
|
||||||
|
logging.debug("Database.tStoreTourneyPlayers")
|
||||||
|
# First, get playerids for the players and specifically the one for hero :
|
||||||
|
playersIds = fpdb_simple.recognisePlayerIDs(self, tourney.players, tourney.siteId)
|
||||||
|
# hero may be None for matrix tourneys summaries
|
||||||
|
# hero = [ tourney.hero ]
|
||||||
|
# heroId = fpdb_simple.recognisePlayerIDs(self, hero , tourney.siteId)
|
||||||
|
# logging.debug("hero Id = %s - playersId = %s" % (heroId , playersIds))
|
||||||
|
|
||||||
|
tourneyPlayersIds=[]
|
||||||
|
try:
|
||||||
|
cursor = self.get_cursor()
|
||||||
|
|
||||||
|
for i in xrange(len(playersIds)):
|
||||||
|
cursor.execute(self.sql.query['getTourneysPlayers'].replace('%s', self.sql.query['placeholder'])
|
||||||
|
,(dbTourneyId, playersIds[i]))
|
||||||
|
result=cursor.fetchone()
|
||||||
|
#print "tried SELECTing tourneys_players.id:",tmp
|
||||||
|
|
||||||
|
try:
|
||||||
|
len(result)
|
||||||
|
# checking data
|
||||||
|
logging.debug("TourneysPlayers found : checking data")
|
||||||
|
expectedValuesDecimal = { 1 : "payinAmounts", 2 : "finishPositions", 3 : "winnings", 4 : "countRebuys",
|
||||||
|
5 : "countAddOns", 6 : "countKO" }
|
||||||
|
|
||||||
|
tourneyPlayersIds.append(result[0]);
|
||||||
|
|
||||||
|
tourneysPlayersDataMatch = True
|
||||||
|
for evD in expectedValuesDecimal :
|
||||||
|
if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]] ) <> result[evD] ):
|
||||||
|
logging.debug("TourneysPlayers data mismatch for TourneysPlayer id=%d, name=%s : wrong %s : Tourney=%s / db=%s" % (result[0], tourney.players[i], expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]], result[evD]) )
|
||||||
|
tourneysPlayersDataMatch = False
|
||||||
|
#break
|
||||||
|
|
||||||
|
if tourneysPlayersDataMatch == False:
|
||||||
|
logging.debug("TourneysPlayers data update needed")
|
||||||
|
cursor.execute (self.sql.query['updateTourneysPlayers'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]],
|
||||||
|
tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]],
|
||||||
|
tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]],
|
||||||
|
result[7], result[8], result[0])
|
||||||
|
)
|
||||||
|
|
||||||
|
except TypeError:
|
||||||
|
logging.debug("TourneysPlayers not found : need insert")
|
||||||
|
cursor.execute (self.sql.query['insertTourneysPlayers'].replace('%s', self.sql.query['placeholder']),
|
||||||
|
(dbTourneyId, playersIds[i],
|
||||||
|
tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]],
|
||||||
|
tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]],
|
||||||
|
tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]],
|
||||||
|
None, None)
|
||||||
|
)
|
||||||
|
tourneyPlayersIds.append(self.get_last_insert_id(cursor))
|
||||||
|
|
||||||
|
except:
|
||||||
|
raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) )
|
||||||
|
|
||||||
|
return tourneyPlayersIds
|
||||||
|
#end def tStoreTourneyPlayers
|
||||||
|
|
||||||
|
def tUpdateTourneysHandsPlayers(self, tourney, dbTourneysPlayersIds, dbTourneyTypeId):
|
||||||
|
logging.debug("Database.tCheckTourneysHandsPlayers")
|
||||||
|
try:
|
||||||
|
# Massive update seems to take quite some time ...
|
||||||
|
# query = self.sql.query['updateHandsPlayersForTTypeId2'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) )
|
||||||
|
# cursor = self.get_cursor()
|
||||||
|
# cursor.execute (query, dbTourneysPlayersIds)
|
||||||
|
|
||||||
|
query = self.sql.query['selectHandsPlayersWithWrongTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) )
|
||||||
|
#print "query : %s" % query
|
||||||
|
cursor = self.get_cursor()
|
||||||
|
cursor.execute (query, dbTourneysPlayersIds)
|
||||||
|
result=cursor.fetchall()
|
||||||
|
|
||||||
|
if (len(result) > 0):
|
||||||
|
logging.debug("%d lines need update : %s" % (len(result), result) )
|
||||||
|
listIds = []
|
||||||
|
for i in result:
|
||||||
|
listIds.append(i[0])
|
||||||
|
|
||||||
|
query2 = self.sql.query['updateHandsPlayersForTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner_id'].join([self.sql.query['placeholder'] for id in listIds]) )
|
||||||
|
cursor.execute (query2, listIds)
|
||||||
|
else:
|
||||||
|
logging.debug("No need to update, HandsPlayers are correct")
|
||||||
|
|
||||||
|
except:
|
||||||
|
raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) )
|
||||||
|
#end def tUpdateTourneysHandsPlayers
|
||||||
|
|
||||||
|
|
||||||
# Class used to hold all the data needed to write a hand to the db
|
# Class used to hold all the data needed to write a hand to the db
|
||||||
# mainParser() in fpdb_parse_logic.py creates one of these and then passes it to
|
# mainParser() in fpdb_parse_logic.py creates one of these and then passes it to
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
class FPDBError(Exception):
|
class FpdbError(Exception):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
def __str__(self):
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
class FpdbParseError(FpdbError):
|
||||||
|
def __init__(self,value='',hid=''):
|
||||||
|
self.value = value
|
||||||
|
self.hid = hid
|
||||||
|
def __str__(self):
|
||||||
|
if hid:
|
||||||
|
return repr("HID:"+hid+", "+self.value)
|
||||||
|
else:
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
class FpdbDatabaseError(FpdbError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class FpdbParseError(FPDBError):
|
class DuplicateError(FpdbError):
|
||||||
def __init__(self,hid=None):
|
pass
|
||||||
self.hid = hid
|
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,13 @@ class Fulltilt(HandHistoryConverter):
|
||||||
(?P<PARTIAL>\(partial\))?\n
|
(?P<PARTIAL>\(partial\))?\n
|
||||||
(?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))?
|
(?:.*?\n(?P<CANCELLED>Hand\s\#(?P=HID)\shas\sbeen\scanceled))?
|
||||||
''', re.VERBOSE|re.DOTALL)
|
''', re.VERBOSE|re.DOTALL)
|
||||||
|
re_TourneyExtraInfo = re.compile('''(((?P<TOURNEY_NAME>[^$]+)?
|
||||||
|
(?P<CURRENCY>\$)?(?P<BUYIN>[.0-9]+)?\s*\+\s*\$?(?P<FEE>[.0-9]+)?
|
||||||
|
(\s(?P<SPECIAL>(KO|Heads\sUp|Matrix\s\dx|Rebuy|Madness)))?
|
||||||
|
(\s(?P<SHOOTOUT>Shootout))?
|
||||||
|
(\s(?P<SNG>Sit\s&\sGo))?
|
||||||
|
(\s\((?P<TURBO>Turbo)\))?)|(?P<UNREADABLE_INFO>.+))
|
||||||
|
''', re.VERBOSE)
|
||||||
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
|
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
|
||||||
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[,.0-9]+)\)$', re.MULTILINE)
|
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$(?P<CASH>[,.0-9]+)\)$', re.MULTILINE)
|
||||||
re_TourneyPlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[,.0-9]+)\)', re.MULTILINE)
|
re_TourneyPlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[,.0-9]+)\)', re.MULTILINE)
|
||||||
|
@ -66,7 +73,7 @@ class Fulltilt(HandHistoryConverter):
|
||||||
re_TourneyInfo = re.compile('''Tournament\sSummary\s
|
re_TourneyInfo = re.compile('''Tournament\sSummary\s
|
||||||
(?P<TOURNAMENT_NAME>[^$(]+)?\s*
|
(?P<TOURNAMENT_NAME>[^$(]+)?\s*
|
||||||
((?P<CURRENCY>\$|)?(?P<BUYIN>[.0-9]+)\s*\+\s*\$?(?P<FEE>[.0-9]+)\s)?
|
((?P<CURRENCY>\$|)?(?P<BUYIN>[.0-9]+)\s*\+\s*\$?(?P<FEE>[.0-9]+)\s)?
|
||||||
((?P<SPECIAL>(KO|Heads\sUp|Matrix\s\dx|Rebuy))\s)?
|
((?P<SPECIAL>(KO|Heads\sUp|Matrix\s\dx|Rebuy|Madness))\s)?
|
||||||
((?P<SHOOTOUT>Shootout)\s)?
|
((?P<SHOOTOUT>Shootout)\s)?
|
||||||
((?P<SNG>Sit\s&\sGo)\s)?
|
((?P<SNG>Sit\s&\sGo)\s)?
|
||||||
(\((?P<TURBO1>Turbo)\)\s)?
|
(\((?P<TURBO1>Turbo)\)\s)?
|
||||||
|
@ -202,16 +209,30 @@ class Fulltilt(HandHistoryConverter):
|
||||||
if m.group('PLAY') != None:
|
if m.group('PLAY') != None:
|
||||||
hand.gametype['currency'] = 'play'
|
hand.gametype['currency'] = 'play'
|
||||||
|
|
||||||
# TODO: if there's a way to figure these out, we should.. otherwise we have to stuff it with unknowns
|
# Done: if there's a way to figure these out, we should.. otherwise we have to stuff it with unknowns
|
||||||
re_SNGBuyInFee = re.compile('''(?P<CURRENCY>\$)?(?P<BUYIN>[.0-9]+) \+ \$?(?P<FEE>[.0-9]+) (?P<EXTRA_INFO>[\sA-Za-z&()]+)?''')
|
if m.group('TOURNAMENT') is not None:
|
||||||
# TO DO : See if important info can be retrieved from EXTRA_INFO (sould be things like Turbo, Matrix, KO, ...)
|
n = self.re_TourneyExtraInfo.search(m.group('TOURNAMENT'))
|
||||||
try:
|
if n.group('UNREADABLE_INFO') is not None:
|
||||||
n = re_SNGBuyInFee.search(m.group('TOURNAMENT'))
|
hand.tourneyComment = n.group('UNREADABLE_INFO')
|
||||||
#print "cur %s BUYIN %s FEE %s EXTRA %s" %(n.group('CURRENCY'), n.group('BUYIN'), n.group('FEE'), n.group('EXTRA_INFO'))
|
else:
|
||||||
hand.buyin = "%s%s+%s%s" %(n.group('CURRENCY'), n.group('BUYIN'), n.group('CURRENCY'), n.group('FEE'))
|
hand.tourneyComment = n.group('TOURNEY_NAME') # can be None
|
||||||
except:
|
if (n.group('CURRENCY') is not None and n.group('BUYIN') is not None and n.group('FEE') is not None):
|
||||||
#print "Unable to collect BuyIn/Fee Info"
|
hand.buyin = "%s%s+%s%s" %(n.group('CURRENCY'), n.group('BUYIN'), n.group('CURRENCY'), n.group('FEE'))
|
||||||
logging.info("Unable to collect BuyIn/Fee Info from HandInfo")
|
if n.group('TURBO') is not None :
|
||||||
|
hand.speed = "Turbo"
|
||||||
|
if n.group('SPECIAL') is not None :
|
||||||
|
special = n.group('SPECIAL')
|
||||||
|
if special == "Rebuy":
|
||||||
|
hand.isRebuy = True
|
||||||
|
if special == "KO":
|
||||||
|
hand.isKO = True
|
||||||
|
if special == "Head's Up":
|
||||||
|
hand.isHU = True
|
||||||
|
if re.search("Matrix", special):
|
||||||
|
hand.isMatrix = True
|
||||||
|
if special == "Shootout":
|
||||||
|
hand.isShootout = True
|
||||||
|
|
||||||
|
|
||||||
if hand.buyin == None:
|
if hand.buyin == None:
|
||||||
hand.buyin = "$0.00+$0.00"
|
hand.buyin = "$0.00+$0.00"
|
||||||
|
@ -405,9 +426,9 @@ class Fulltilt(HandHistoryConverter):
|
||||||
self.status = False
|
self.status = False
|
||||||
else:
|
else:
|
||||||
self.tourney = Tourney.Tourney(sitename = self.sitename, gametype = None, summaryText = summaryInfoList, builtFrom = "HHC")
|
self.tourney = Tourney.Tourney(sitename = self.sitename, gametype = None, summaryText = summaryInfoList, builtFrom = "HHC")
|
||||||
self.status = self.determineTourneyType(self.tourney)
|
self.status = self.getPlayersPositionsAndWinnings(self.tourney)
|
||||||
if self.status == True :
|
if self.status == True :
|
||||||
self.status = status = self.getPlayersPositionsAndWinnings(self.tourney)
|
self.status = self.determineTourneyType(self.tourney)
|
||||||
#print self.tourney
|
#print self.tourney
|
||||||
else:
|
else:
|
||||||
log.info("Parsing NOK : rejected")
|
log.info("Parsing NOK : rejected")
|
||||||
|
@ -454,10 +475,10 @@ class Fulltilt(HandHistoryConverter):
|
||||||
|
|
||||||
# Additional info can be stored in the tourney object
|
# Additional info can be stored in the tourney object
|
||||||
if mg['BUYIN'] is not None:
|
if mg['BUYIN'] is not None:
|
||||||
tourney.buyin = mg['BUYIN']
|
tourney.buyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
|
||||||
tourney.fee = 0
|
tourney.fee = 0
|
||||||
if mg['FEE'] is not None:
|
if mg['FEE'] is not None:
|
||||||
tourney.fee = mg['FEE']
|
tourney.fee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
|
||||||
if mg['TOURNAMENT_NAME'] is not None:
|
if mg['TOURNAMENT_NAME'] is not None:
|
||||||
# Tournament Name can have a trailing space at the end (depending on the tournament description)
|
# Tournament Name can have a trailing space at the end (depending on the tournament description)
|
||||||
tourney.tourneyName = mg['TOURNAMENT_NAME'].rstrip()
|
tourney.tourneyName = mg['TOURNAMENT_NAME'].rstrip()
|
||||||
|
@ -472,6 +493,8 @@ class Fulltilt(HandHistoryConverter):
|
||||||
tourney.isMatrix = True
|
tourney.isMatrix = True
|
||||||
if special == "Rebuy":
|
if special == "Rebuy":
|
||||||
tourney.isRebuy = True
|
tourney.isRebuy = True
|
||||||
|
if special == "Madness":
|
||||||
|
tourney.tourneyComment = "Madness"
|
||||||
if mg['SHOOTOUT'] is not None:
|
if mg['SHOOTOUT'] is not None:
|
||||||
tourney.isShootout = True
|
tourney.isShootout = True
|
||||||
if mg['TURBO1'] is not None or mg['TURBO2'] is not None :
|
if mg['TURBO1'] is not None or mg['TURBO2'] is not None :
|
||||||
|
@ -500,25 +523,25 @@ class Fulltilt(HandHistoryConverter):
|
||||||
mg = m.groupdict()
|
mg = m.groupdict()
|
||||||
if tourney.isMatrix :
|
if tourney.isMatrix :
|
||||||
if mg['BUYIN'] is not None:
|
if mg['BUYIN'] is not None:
|
||||||
tourney.subTourneyBuyin = mg['BUYIN']
|
tourney.subTourneyBuyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
|
||||||
tourney.subTourneyFee = 0
|
tourney.subTourneyFee = 0
|
||||||
if mg['FEE'] is not None:
|
if mg['FEE'] is not None:
|
||||||
tourney.subTourneyFee = mg['FEE']
|
tourney.subTourneyFee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
|
||||||
else :
|
else :
|
||||||
if mg['BUYIN'] is not None:
|
if mg['BUYIN'] is not None:
|
||||||
if tourney.buyin is None:
|
if tourney.buyin is None:
|
||||||
tourney.buyin = mg['BUYIN']
|
tourney.buyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
|
||||||
else :
|
else :
|
||||||
if mg['BUYIN'] != tourney.buyin:
|
if 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN'])) != tourney.buyin:
|
||||||
log.error( "Conflict between buyins read in topline (%s) and in BuyIn field (%s)" % (touney.buyin, mg['BUYIN']) )
|
log.error( "Conflict between buyins read in topline (%s) and in BuyIn field (%s)" % (touney.buyin, 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))) )
|
||||||
tourney.subTourneyBuyin = mg['BUYIN']
|
tourney.subTourneyBuyin = 100*Decimal(re.sub(u',', u'', "%s" % mg['BUYIN']))
|
||||||
if mg['FEE'] is not None:
|
if mg['FEE'] is not None:
|
||||||
if tourney.fee is None:
|
if tourney.fee is None:
|
||||||
tourney.fee = mg['FEE']
|
tourney.fee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
|
||||||
else :
|
else :
|
||||||
if mg['FEE'] != tourney.fee:
|
if 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE'])) != tourney.fee:
|
||||||
log.error( "Conflict between fees read in topline (%s) and in BuyIn field (%s)" % (touney.fee, mg['FEE']) )
|
log.error( "Conflict between fees read in topline (%s) and in BuyIn field (%s)" % (touney.fee, 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))) )
|
||||||
tourney.subTourneyFee = mg['FEE']
|
tourney.subTourneyFee = 100*Decimal(re.sub(u',', u'', "%s" % mg['FEE']))
|
||||||
|
|
||||||
if tourney.buyin is None:
|
if tourney.buyin is None:
|
||||||
log.info( "Unable to affect a buyin to this tournament : assume it's a freeroll" )
|
log.info( "Unable to affect a buyin to this tournament : assume it's a freeroll" )
|
||||||
|
@ -535,15 +558,12 @@ class Fulltilt(HandHistoryConverter):
|
||||||
"PRIZEPOOL" : self.re_TourneyPrizePool,
|
"PRIZEPOOL" : self.re_TourneyPrizePool,
|
||||||
"REBUY_AMOUNT" : self.re_TourneyRebuyAmount,
|
"REBUY_AMOUNT" : self.re_TourneyRebuyAmount,
|
||||||
"ADDON_AMOUNT" : self.re_TourneyAddOnAmount,
|
"ADDON_AMOUNT" : self.re_TourneyAddOnAmount,
|
||||||
"REBUY_COUNT" : self.re_TourneyRebuyCount,
|
|
||||||
"ADDON_COUNT" : self.re_TourneyAddOnCount,
|
|
||||||
"REBUY_TOTAL" : self.re_TourneyRebuysTotal,
|
"REBUY_TOTAL" : self.re_TourneyRebuysTotal,
|
||||||
"ADDONS_TOTAL" : self.re_TourneyAddOnsTotal,
|
"ADDONS_TOTAL" : self.re_TourneyAddOnsTotal,
|
||||||
"REBUY_CHIPS" : self.re_TourneyRebuyChips,
|
"REBUY_CHIPS" : self.re_TourneyRebuyChips,
|
||||||
"ADDON_CHIPS" : self.re_TourneyAddOnChips,
|
"ADDON_CHIPS" : self.re_TourneyAddOnChips,
|
||||||
"STARTTIME" : self.re_TourneyTimeInfo,
|
"STARTTIME" : self.re_TourneyTimeInfo,
|
||||||
"KO_BOUNTY_AMOUNT" : self.re_TourneyKOBounty,
|
"KO_BOUNTY_AMOUNT" : self.re_TourneyKOBounty,
|
||||||
"COUNT_KO" : self.re_TourneyCountKO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -552,15 +572,12 @@ class Fulltilt(HandHistoryConverter):
|
||||||
"PRIZEPOOL" : "prizepool",
|
"PRIZEPOOL" : "prizepool",
|
||||||
"REBUY_AMOUNT" : "rebuyAmount",
|
"REBUY_AMOUNT" : "rebuyAmount",
|
||||||
"ADDON_AMOUNT" : "addOnAmount",
|
"ADDON_AMOUNT" : "addOnAmount",
|
||||||
"REBUY_COUNT" : "countRebuys",
|
|
||||||
"ADDON_COUNT" : "countAddOns",
|
|
||||||
"REBUY_TOTAL" : "totalRebuys",
|
"REBUY_TOTAL" : "totalRebuys",
|
||||||
"ADDONS_TOTAL" : "totalAddOns",
|
"ADDONS_TOTAL" : "totalAddOns",
|
||||||
"REBUY_CHIPS" : "rebuyChips",
|
"REBUY_CHIPS" : "rebuyChips",
|
||||||
"ADDON_CHIPS" : "addOnChips",
|
"ADDON_CHIPS" : "addOnChips",
|
||||||
"STARTTIME" : "starttime",
|
"STARTTIME" : "starttime",
|
||||||
"KO_BOUNTY_AMOUNT" : "koBounty",
|
"KO_BOUNTY_AMOUNT" : "koBounty"
|
||||||
"COUNT_KO" : "countKO"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mg = {} # After the loop, mg will contain all the matching groups, including the ones that have not been used, like ENDTIME and IN-PROGRESS
|
mg = {} # After the loop, mg will contain all the matching groups, including the ones that have not been used, like ENDTIME and IN-PROGRESS
|
||||||
|
@ -573,8 +590,43 @@ class Fulltilt(HandHistoryConverter):
|
||||||
if mg['IN_PROGRESS'] is not None or mg['ENDTIME'] is not None:
|
if mg['IN_PROGRESS'] is not None or mg['ENDTIME'] is not None:
|
||||||
# Assign endtime to tourney (if None, that's ok, it's because the tourney wans't over over when the summary file was produced)
|
# Assign endtime to tourney (if None, that's ok, it's because the tourney wans't over over when the summary file was produced)
|
||||||
tourney.endtime = mg['ENDTIME']
|
tourney.endtime = mg['ENDTIME']
|
||||||
#print mg
|
|
||||||
|
|
||||||
|
# Deal with hero specific information
|
||||||
|
if tourney.hero is not None :
|
||||||
|
m = self.re_TourneyRebuyCount.search(tourneyText)
|
||||||
|
if m is not None:
|
||||||
|
mg = m.groupdict()
|
||||||
|
if mg['REBUY_COUNT'] is not None :
|
||||||
|
tourney.countRebuys.update( { tourney.hero : Decimal(mg['REBUY_COUNT']) } )
|
||||||
|
m = self.re_TourneyAddOnCount.search(tourneyText)
|
||||||
|
if m is not None:
|
||||||
|
mg = m.groupdict()
|
||||||
|
if mg['ADDON_COUNT'] is not None :
|
||||||
|
tourney.countAddOns.update( { tourney.hero : Decimal(mg['ADDON_COUNT']) } )
|
||||||
|
m = self.re_TourneyCountKO.search(tourneyText)
|
||||||
|
if m is not None:
|
||||||
|
mg = m.groupdict()
|
||||||
|
if mg['COUNT_KO'] is not None :
|
||||||
|
tourney.countKO.update( { tourney.hero : Decimal(mg['COUNT_KO']) } )
|
||||||
|
|
||||||
|
# Deal with money amounts
|
||||||
|
tourney.koBounty = 100*Decimal(re.sub(u',', u'', "%s" % tourney.koBounty))
|
||||||
|
tourney.prizepool = 100*Decimal(re.sub(u',', u'', "%s" % tourney.prizepool))
|
||||||
|
tourney.rebuyAmount = 100*Decimal(re.sub(u',', u'', "%s" % tourney.rebuyAmount))
|
||||||
|
tourney.addOnAmount = 100*Decimal(re.sub(u',', u'', "%s" % tourney.addOnAmount))
|
||||||
|
|
||||||
|
# Calculate payin amounts and update winnings -- not possible to take into account nb of rebuys, addons or Knockouts for other players than hero on FTP
|
||||||
|
for p in tourney.players :
|
||||||
|
tourney.payinAmounts[p] = tourney.buyin + tourney.fee + (tourney.rebuyAmount * tourney.countRebuys[p]) + (tourney.addOnAmount * tourney.countAddOns[p])
|
||||||
|
#print " player %s : payinAmount = %d" %( p, tourney.payinAmounts[p])
|
||||||
|
if tourney.isKO :
|
||||||
|
#tourney.incrementPlayerWinnings(tourney.players[p], Decimal(tourney.koBounty)*Decimal(tourney.countKO[p]))
|
||||||
|
tourney.winnings[p] += Decimal(tourney.koBounty)*Decimal(tourney.countKO[p])
|
||||||
|
#print "player %s : winnings %d" % (p, tourney.winnings[p])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#print mg
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getPlayersPositionsAndWinnings(self, tourney):
|
def getPlayersPositionsAndWinnings(self, tourney):
|
||||||
|
@ -590,15 +642,15 @@ class Fulltilt(HandHistoryConverter):
|
||||||
rank = Decimal(a.group('RANK'))
|
rank = Decimal(a.group('RANK'))
|
||||||
|
|
||||||
if a.group('WINNING') is not None:
|
if a.group('WINNING') is not None:
|
||||||
winnings = a.group('WINNING')
|
winnings = 100*Decimal(re.sub(u',', u'', "%s" % a.group('WINNING')))
|
||||||
else:
|
else:
|
||||||
winnings = "0"
|
winnings = "0"
|
||||||
|
|
||||||
tourney.addPlayer(rank, a.group('PNAME'), winnings)
|
tourney.addPlayer(rank, a.group('PNAME'), winnings, 0, 0, 0, 0)
|
||||||
else:
|
else:
|
||||||
print "Player finishing stats unreadable : %s" % a
|
print "Player finishing stats unreadable : %s" % a
|
||||||
|
|
||||||
# Deal with KO tournaments for hero winnings calculation
|
# Find Hero
|
||||||
n = self.re_TourneyHeroFinishingP.search(playersText)
|
n = self.re_TourneyHeroFinishingP.search(playersText)
|
||||||
if n is not None:
|
if n is not None:
|
||||||
heroName = n.group('HERO_NAME')
|
heroName = n.group('HERO_NAME')
|
||||||
|
@ -606,9 +658,6 @@ class Fulltilt(HandHistoryConverter):
|
||||||
# Is this really useful ?
|
# Is this really useful ?
|
||||||
if (tourney.finishPositions[heroName] != Decimal(n.group('HERO_FINISHING_POS'))):
|
if (tourney.finishPositions[heroName] != Decimal(n.group('HERO_FINISHING_POS'))):
|
||||||
print "Bad parsing : finish position incoherent : %s / %s" % (tourney.finishPositions[heroName], n.group('HERO_FINISHING_POS'))
|
print "Bad parsing : finish position incoherent : %s / %s" % (tourney.finishPositions[heroName], n.group('HERO_FINISHING_POS'))
|
||||||
if tourney.isKO:
|
|
||||||
#Update the winnings with the (KO amount) * (# of KO)
|
|
||||||
tourney.incrementPlayerWinnings(n.group('HERO_NAME'), Decimal(tourney.koBounty)*Decimal(tourney.countKO))
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ import string
|
||||||
class GuiAutoImport (threading.Thread):
|
class GuiAutoImport (threading.Thread):
|
||||||
def __init__(self, settings, config, sql):
|
def __init__(self, settings, config, sql):
|
||||||
"""Constructor for GuiAutoImport"""
|
"""Constructor for GuiAutoImport"""
|
||||||
|
self.importtimer = 0
|
||||||
self.settings=settings
|
self.settings=settings
|
||||||
self.config=config
|
self.config=config
|
||||||
self.sql = sql
|
self.sql = sql
|
||||||
|
@ -196,11 +197,14 @@ class GuiAutoImport (threading.Thread):
|
||||||
self.do_import()
|
self.do_import()
|
||||||
|
|
||||||
interval = int(self.intervalEntry.get_text())
|
interval = int(self.intervalEntry.get_text())
|
||||||
gobject.timeout_add(interval*1000, self.do_import)
|
if self.importtimer != 0:
|
||||||
|
gobject.source_remove(self.importtimer)
|
||||||
|
self.importtimer = gobject.timeout_add(interval*1000, self.do_import)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print "auto-import aborted - global lock not available"
|
print "auto-import aborted - global lock not available"
|
||||||
else: # toggled off
|
else: # toggled off
|
||||||
|
gobject.source_remove(self.importtimer)
|
||||||
self.settings['global_lock'].release()
|
self.settings['global_lock'].release()
|
||||||
self.doAutoImportBool = False # do_import will return this and stop the gobject callback timer
|
self.doAutoImportBool = False # do_import will return this and stop the gobject callback timer
|
||||||
print "Stopping autoimport - global lock released."
|
print "Stopping autoimport - global lock released."
|
||||||
|
|
|
@ -27,11 +27,13 @@ import traceback
|
||||||
import pygtk
|
import pygtk
|
||||||
pygtk.require('2.0')
|
pygtk.require('2.0')
|
||||||
import gtk
|
import gtk
|
||||||
|
import gobject
|
||||||
|
|
||||||
# fpdb/FreePokerTools modules
|
# fpdb/FreePokerTools modules
|
||||||
import fpdb_simple
|
import fpdb_simple
|
||||||
import fpdb_import
|
import fpdb_import
|
||||||
import Configuration
|
import Configuration
|
||||||
|
import Exceptions
|
||||||
|
|
||||||
class GuiBulkImport():
|
class GuiBulkImport():
|
||||||
|
|
||||||
|
@ -53,12 +55,22 @@ class GuiBulkImport():
|
||||||
else:
|
else:
|
||||||
self.importer.RunImportThreaded()
|
self.importer.RunImportThreaded()
|
||||||
|
|
||||||
|
def dopulse(self):
|
||||||
|
self.progressbar.pulse()
|
||||||
|
return True
|
||||||
|
|
||||||
def load_clicked(self, widget, data=None):
|
def load_clicked(self, widget, data=None):
|
||||||
# Does the lock acquisition need to be more sophisticated for multiple dirs?
|
# Does the lock acquisition need to be more sophisticated for multiple dirs?
|
||||||
# (see comment above about what to do if pipe already open)
|
# (see comment above about what to do if pipe already open)
|
||||||
if self.settings['global_lock'].acquire(False): # returns false immediately if lock not acquired
|
if self.settings['global_lock'].acquire(False): # returns false immediately if lock not acquired
|
||||||
try:
|
try:
|
||||||
print "\nGlobal lock taken ..."
|
print "\nGlobal lock taken ..."
|
||||||
|
self.progressbar.set_text("Importing...")
|
||||||
|
self.progressbar.pulse()
|
||||||
|
while gtk.events_pending(): # see http://faq.pygtk.org/index.py?req=index for more hints (3.7)
|
||||||
|
gtk.main_iteration(False)
|
||||||
|
self.timer = gobject.timeout_add(100, self.dopulse)
|
||||||
|
|
||||||
# get the dir to import from the chooser
|
# get the dir to import from the chooser
|
||||||
self.inputFile = self.chooser.get_filename()
|
self.inputFile = self.chooser.get_filename()
|
||||||
|
|
||||||
|
@ -74,9 +86,7 @@ class GuiBulkImport():
|
||||||
cb_hmodel = self.cb_drophudcache.get_model()
|
cb_hmodel = self.cb_drophudcache.get_model()
|
||||||
cb_hindex = self.cb_drophudcache.get_active()
|
cb_hindex = self.cb_drophudcache.get_active()
|
||||||
|
|
||||||
self.lab_info.set_markup('<span foreground="blue">Importing ...</span>') # uses pango markup!
|
#self.lab_info.set_markup('<span foreground="blue">Importing ...</span>') # uses pango markup!
|
||||||
while gtk.events_pending(): # see http://faq.pygtk.org/index.py?req=index for more hints (3.7)
|
|
||||||
gtk.main_iteration(False)
|
|
||||||
|
|
||||||
if cb_index:
|
if cb_index:
|
||||||
self.importer.setDropIndexes(cb_model[cb_index][0])
|
self.importer.setDropIndexes(cb_model[cb_index][0])
|
||||||
|
@ -91,7 +101,14 @@ class GuiBulkImport():
|
||||||
self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename)
|
self.importer.addBulkImportImportFileOrDir(self.inputFile, site = sitename)
|
||||||
self.importer.setCallHud(False)
|
self.importer.setCallHud(False)
|
||||||
starttime = time()
|
starttime = time()
|
||||||
(stored, dups, partial, errs, ttime) = self.importer.runImport()
|
try:
|
||||||
|
(stored, dups, partial, errs, ttime) = self.importer.runImport()
|
||||||
|
except:
|
||||||
|
print "*** EXCEPTION DURING BULKIMPORT!!!"
|
||||||
|
raise Exceptions.FpdbError
|
||||||
|
finally:
|
||||||
|
gobject.source_remove(self.timer)
|
||||||
|
|
||||||
ttime = time() - starttime
|
ttime = time() - starttime
|
||||||
if ttime == 0:
|
if ttime == 0:
|
||||||
ttime = 1
|
ttime = 1
|
||||||
|
@ -106,7 +123,8 @@ class GuiBulkImport():
|
||||||
self.cb_drophudcache.set_active(0)
|
self.cb_drophudcache.set_active(0)
|
||||||
self.lab_hdrop.set_sensitive(True)
|
self.lab_hdrop.set_sensitive(True)
|
||||||
|
|
||||||
self.lab_info.set_text("Import finished")
|
self.progressbar.set_text("Import Complete")
|
||||||
|
self.progressbar.set_fraction(0)
|
||||||
except:
|
except:
|
||||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||||
print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||||
|
@ -251,9 +269,14 @@ class GuiBulkImport():
|
||||||
self.lab_spacer.show()
|
self.lab_spacer.show()
|
||||||
|
|
||||||
# label - info
|
# label - info
|
||||||
self.lab_info = gtk.Label()
|
# self.lab_info = gtk.Label()
|
||||||
self.table.attach(self.lab_info, 3, 5, 4, 5, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK)
|
# self.table.attach(self.lab_info, 3, 5, 4, 5, xpadding = 0, ypadding = 0, yoptions=gtk.SHRINK)
|
||||||
self.lab_info.show()
|
# self.lab_info.show()
|
||||||
|
self.progressbar = gtk.ProgressBar()
|
||||||
|
self.table.attach(self.progressbar, 3, 5, 4, 5, xpadding = 0, ypadding = 0, yoptions = gtk.SHRINK)
|
||||||
|
self.progressbar.set_text("Waiting...")
|
||||||
|
self.progressbar.set_fraction(0)
|
||||||
|
self.progressbar.show()
|
||||||
|
|
||||||
# see how many hands are in the db and adjust accordingly
|
# see how many hands are in the db and adjust accordingly
|
||||||
tcursor = self.importer.database.cursor
|
tcursor = self.importer.database.cursor
|
||||||
|
@ -284,7 +307,7 @@ def main(argv=None):
|
||||||
parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True,
|
parser.add_option("-q", "--quiet", action="store_false", dest="gui", default=True,
|
||||||
help="don't start gui; deprecated (just give a filename with -f).")
|
help="don't start gui; deprecated (just give a filename with -f).")
|
||||||
parser.add_option("-c", "--convert", dest="filtername", default="PokerStars", metavar="FILTER",
|
parser.add_option("-c", "--convert", dest="filtername", default="PokerStars", metavar="FILTER",
|
||||||
help="Conversion filter (*Full Tilt Poker, PokerStars, Everleaf)")
|
help="Conversion filter (*Full Tilt Poker, PokerStars, Everleaf, Absolute)")
|
||||||
parser.add_option("-x", "--failOnError", action="store_true", default=False,
|
parser.add_option("-x", "--failOnError", action="store_true", default=False,
|
||||||
help="If this option is passed it quits when it encounters any error")
|
help="If this option is passed it quits when it encounters any error")
|
||||||
parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int",
|
parser.add_option("-m", "--minPrint", "--status", dest="minPrint", default="0", type="int",
|
||||||
|
@ -319,6 +342,7 @@ def main(argv=None):
|
||||||
# importer.setDropIndexes("auto")
|
# importer.setDropIndexes("auto")
|
||||||
importer.setDropIndexes("don't drop")
|
importer.setDropIndexes("don't drop")
|
||||||
importer.setFailOnError(options.failOnError)
|
importer.setFailOnError(options.failOnError)
|
||||||
|
importer.setThreads(-1)
|
||||||
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername)
|
importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername)
|
||||||
importer.setCallHud(False)
|
importer.setCallHud(False)
|
||||||
importer.runImport()
|
importer.runImport()
|
||||||
|
|
|
@ -21,7 +21,11 @@ pygtk.require('2.0')
|
||||||
import gtk
|
import gtk
|
||||||
import os
|
import os
|
||||||
from time import time, strftime, localtime
|
from time import time, strftime, localtime
|
||||||
from numpy import diff, nonzero
|
try:
|
||||||
|
from numpy import diff, nonzero
|
||||||
|
except:
|
||||||
|
print """Failed to load numpy in Session Viewer"""
|
||||||
|
print """This is of no consequence as the module currently doesn't do anything."""
|
||||||
|
|
||||||
import Card
|
import Card
|
||||||
import fpdb_import
|
import fpdb_import
|
||||||
|
|
|
@ -24,6 +24,7 @@ import fpdb_simple
|
||||||
|
|
||||||
import fpdb_import
|
import fpdb_import
|
||||||
import fpdb_db
|
import fpdb_db
|
||||||
|
from Exceptions import *
|
||||||
|
|
||||||
|
|
||||||
class GuiTableViewer (threading.Thread):
|
class GuiTableViewer (threading.Thread):
|
||||||
|
@ -73,7 +74,7 @@ class GuiTableViewer (threading.Thread):
|
||||||
|
|
||||||
tmp+=("WtSD", "W$wsF", "W$SD")
|
tmp+=("WtSD", "W$wsF", "W$SD")
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("reimplement stud")
|
raise FpdbError("reimplement stud")
|
||||||
arr.append(tmp)
|
arr.append(tmp)
|
||||||
|
|
||||||
#then the data rows
|
#then the data rows
|
||||||
|
@ -93,7 +94,7 @@ class GuiTableViewer (threading.Thread):
|
||||||
elif seatCount==2 or seatCount==3:
|
elif seatCount==2 or seatCount==3:
|
||||||
minSeats,maxSeats=seatCount,seatCount
|
minSeats,maxSeats=seatCount,seatCount
|
||||||
else:
|
else:
|
||||||
fpdb_simple.FpdbError("invalid seatCount")
|
FpdbError("invalid seatCount")
|
||||||
|
|
||||||
self.cursor.execute("SELECT * FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats>=%s AND activeSeats<=%s", (self.gametype_id, self.player_ids[player][0], minSeats, maxSeats))
|
self.cursor.execute("SELECT * FROM HudCache WHERE gametypeId=%s AND playerId=%s AND activeSeats>=%s AND activeSeats<=%s", (self.gametype_id, self.player_ids[player][0], minSeats, maxSeats))
|
||||||
rows=self.cursor.fetchall()
|
rows=self.cursor.fetchall()
|
||||||
|
|
|
@ -195,7 +195,7 @@ class HUD_main(object):
|
||||||
temp_key = tour_number
|
temp_key = tour_number
|
||||||
else: # tourney, but can't get number and table
|
else: # tourney, but can't get number and table
|
||||||
print "could not find tournament: skipping "
|
print "could not find tournament: skipping "
|
||||||
sys.stderr.write("Could not find tournament %d in hand %d. Skipping.\n" % (int(tour_number), int(new_hand_id)))
|
#sys.stderr.write("Could not find tournament %d in hand %d. Skipping.\n" % (int(tour_number), int(new_hand_id)))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#Copyright 2008 Carl Gherardi
|
#Copyright 2008 Carl Gherardi
|
||||||
#This program is free software: you can redistribute it and/or modify
|
#This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -63,6 +64,15 @@ class Hand(object):
|
||||||
self.fee = None # the Database code is looking for this one .. ?
|
self.fee = None # the Database code is looking for this one .. ?
|
||||||
self.level = None
|
self.level = None
|
||||||
self.mixed = None
|
self.mixed = None
|
||||||
|
# Some attributes for hand from a tourney
|
||||||
|
self.speed = "Normal"
|
||||||
|
self.isRebuy = False
|
||||||
|
self.isKO = False
|
||||||
|
self.isHU = False
|
||||||
|
self.isMatrix = False
|
||||||
|
self.isShootout = False
|
||||||
|
self.tourneyComment = None
|
||||||
|
|
||||||
self.seating = []
|
self.seating = []
|
||||||
self.players = []
|
self.players = []
|
||||||
self.posted = []
|
self.posted = []
|
||||||
|
@ -471,7 +481,6 @@ Add a raise on [street] by [player] to [amountTo]
|
||||||
For when a player shows cards for any reason (for showdown or out of choice).
|
For when a player shows cards for any reason (for showdown or out of choice).
|
||||||
Card ranks will be uppercased
|
Card ranks will be uppercased
|
||||||
"""
|
"""
|
||||||
import sys; sys.exit(1)
|
|
||||||
log.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
|
log.debug("addShownCards %s hole=%s all=%s" % (player, cards, holeandboard))
|
||||||
if cards is not None:
|
if cards is not None:
|
||||||
self.addHoleCards(cards,player,shown, mucked)
|
self.addHoleCards(cards,player,shown, mucked)
|
||||||
|
@ -583,8 +592,15 @@ Map the tuple self.gametype onto the pokerstars string describing it
|
||||||
else: # non-mixed cash games
|
else: # non-mixed cash games
|
||||||
gs = gs + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString())
|
gs = gs + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString())
|
||||||
|
|
||||||
return gs + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET')
|
try:
|
||||||
|
timestr = datetime.datetime.strftime(self.starttime, '%Y/%m/%d %H:%M:%S ET')
|
||||||
|
except TypeError:
|
||||||
|
print "*** ERROR - HAND: calling writeGameLine with unexpected STARTTIME value, expecting datetime.date object, received:", self.starttime
|
||||||
|
print "*** Make sure your HandHistoryConverter is setting hand.starttime properly!"
|
||||||
|
print "*** Game String:", gs
|
||||||
|
return gs
|
||||||
|
else:
|
||||||
|
return gs + timestr
|
||||||
|
|
||||||
def writeTableLine(self):
|
def writeTableLine(self):
|
||||||
table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats)
|
table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats)
|
||||||
|
@ -672,7 +688,7 @@ class HoldemOmahaHand(Hand):
|
||||||
tmp5 = 0
|
tmp5 = 0
|
||||||
return (tmp1,tmp2,tmp3,tmp4,tmp5)
|
return (tmp1,tmp2,tmp3,tmp4,tmp5)
|
||||||
|
|
||||||
def writeHTMLHand(self, fh=sys.__stdout__):
|
def writeHTMLHand(self):
|
||||||
from nevow import tags as T
|
from nevow import tags as T
|
||||||
from nevow import flat
|
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_who_act_preflop = (([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']]))
|
||||||
|
|
|
@ -37,9 +37,12 @@ import gettext
|
||||||
gettext.install('fpdb')
|
gettext.install('fpdb')
|
||||||
|
|
||||||
import logging, logging.config
|
import logging, logging.config
|
||||||
logging.config.fileConfig("logging.conf")
|
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
|
||||||
log = logging.getLogger("parser")
|
log = logging.getLogger("parser")
|
||||||
|
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
|
||||||
class HandHistoryConverter():
|
class HandHistoryConverter():
|
||||||
|
|
||||||
READ_CHUNK_SIZE = 10000 # bytes to read at a time from file in tail mode
|
READ_CHUNK_SIZE = 10000 # bytes to read at a time from file in tail mode
|
||||||
|
@ -82,13 +85,21 @@ follow : whether to tail -f the input"""
|
||||||
# TODO: out_path should be sanity checked.
|
# TODO: out_path should be sanity checked.
|
||||||
out_dir = os.path.dirname(self.out_path)
|
out_dir = os.path.dirname(self.out_path)
|
||||||
if not os.path.isdir(out_dir) and out_dir != '':
|
if not os.path.isdir(out_dir) and out_dir != '':
|
||||||
log.info("Creating directory '%s'" % out_dir)
|
try:
|
||||||
os.makedirs(out_dir)
|
os.makedirs(out_dir)
|
||||||
|
except: # we get a WindowsError here in Windows.. pretty sure something else for Linux :D
|
||||||
|
log.error("Unable to create output directory %s for HHC!" % out_dir)
|
||||||
|
print "*** ERROR: UNABLE TO CREATE OUTPUT DIRECTORY", out_dir
|
||||||
|
# TODO: pop up a box to allow person to choose output directory?
|
||||||
|
# TODO: shouldn't that be done when we startup, actually?
|
||||||
|
else:
|
||||||
|
log.info("Created directory '%s'" % out_dir)
|
||||||
try:
|
try:
|
||||||
self.out_fh = codecs.open(self.out_path, 'w', 'cp1252')
|
self.out_fh = codecs.open(self.out_path, 'w', 'cp1252')
|
||||||
log.debug("out_path %s opened as %s" % (self.out_path, self.out_fh))
|
|
||||||
except:
|
except:
|
||||||
log.error("out_path %s couldn't be opened" % (self.out_path))
|
log.error("out_path %s couldn't be opened" % (self.out_path))
|
||||||
|
else:
|
||||||
|
log.debug("out_path %s opened as %s" % (self.out_path, self.out_fh))
|
||||||
|
|
||||||
self.follow = follow
|
self.follow = follow
|
||||||
self.compiledPlayers = set()
|
self.compiledPlayers = set()
|
||||||
|
@ -116,6 +127,9 @@ If in follow mode, wait for more data to turn up.
|
||||||
Otherwise, finish at EOF.
|
Otherwise, finish at EOF.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
while gtk.events_pending():
|
||||||
|
gtk.main_iteration(False)
|
||||||
|
|
||||||
starttime = time.time()
|
starttime = time.time()
|
||||||
if not self.sanityCheck():
|
if not self.sanityCheck():
|
||||||
log.warning("Failed sanity check")
|
log.warning("Failed sanity check")
|
||||||
|
@ -139,7 +153,8 @@ Otherwise, finish at EOF.
|
||||||
handsList = self.allHandsAsList()
|
handsList = self.allHandsAsList()
|
||||||
log.info("Parsing %d hands" % len(handsList))
|
log.info("Parsing %d hands" % len(handsList))
|
||||||
# Determine if we're dealing with a HH file or a Summary file
|
# Determine if we're dealing with a HH file or a Summary file
|
||||||
if self.isSummary(handsList[0]) == False:
|
# quick fix : empty files make the handsList[0] fail ==> If empty file, go on with HH parsing
|
||||||
|
if len(handsList) == 0 or self.isSummary(handsList[0]) == False:
|
||||||
self.parsedObjectType = "HH"
|
self.parsedObjectType = "HH"
|
||||||
for handText in handsList:
|
for handText in handsList:
|
||||||
try:
|
try:
|
||||||
|
@ -411,10 +426,8 @@ or None if we fail to get the info """
|
||||||
log.debug("Reading stdin with %s" % self.codepage) # is this necessary? or possible? or what?
|
log.debug("Reading stdin with %s" % self.codepage) # is this necessary? or possible? or what?
|
||||||
in_fh = codecs.getreader('cp1252')(sys.stdin)
|
in_fh = codecs.getreader('cp1252')(sys.stdin)
|
||||||
else:
|
else:
|
||||||
success = False
|
|
||||||
for kodec in self.__listof(self.codepage):
|
for kodec in self.__listof(self.codepage):
|
||||||
if success: break
|
#print "trying", kodec
|
||||||
print "trying", kodec
|
|
||||||
try:
|
try:
|
||||||
in_fh = codecs.open(self.in_path, 'r', kodec)
|
in_fh = codecs.open(self.in_path, 'r', kodec)
|
||||||
in_fh.seek(self.index)
|
in_fh.seek(self.index)
|
||||||
|
@ -422,9 +435,11 @@ or None if we fail to get the info """
|
||||||
self.obs = in_fh.read()
|
self.obs = in_fh.read()
|
||||||
self.index = in_fh.tell()
|
self.index = in_fh.tell()
|
||||||
in_fh.close()
|
in_fh.close()
|
||||||
success = True
|
break
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
print "unable to read file with any codec in list!", self.in_path
|
||||||
elif(self.filetype == "xml"):
|
elif(self.filetype == "xml"):
|
||||||
doc = xml.dom.minidom.parse(filename)
|
doc = xml.dom.minidom.parse(filename)
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
|
|
215
pyfpdb/Hud.py
215
pyfpdb/Hud.py
|
@ -81,6 +81,10 @@ class Hud:
|
||||||
(font, font_size) = config.get_default_font(self.table.site)
|
(font, font_size) = config.get_default_font(self.table.site)
|
||||||
self.colors = config.get_default_colors(self.table.site)
|
self.colors = config.get_default_colors(self.table.site)
|
||||||
|
|
||||||
|
self.backgroundcolor = gtk.gdk.color_parse(self.colors['hudbgcolor'])
|
||||||
|
self.foregroundcolor = gtk.gdk.color_parse(self.colors['hudfgcolor'])
|
||||||
|
|
||||||
|
|
||||||
if font == None:
|
if font == None:
|
||||||
font = "Sans"
|
font = "Sans"
|
||||||
if font_size == None:
|
if font_size == None:
|
||||||
|
@ -102,84 +106,66 @@ class Hud:
|
||||||
def create_mw(self):
|
def create_mw(self):
|
||||||
|
|
||||||
# Set up a main window for this this instance of the HUD
|
# Set up a main window for this this instance of the HUD
|
||||||
self.main_window = gtk.Window()
|
win = gtk.Window()
|
||||||
self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC)
|
win.set_gravity(gtk.gdk.GRAVITY_STATIC)
|
||||||
self.main_window.set_title("%s FPDBHUD" % (self.table.name))
|
win.set_title("%s FPDBHUD" % (self.table.name))
|
||||||
self.main_window.set_decorated(False)
|
win.set_skip_taskbar_hint(True)
|
||||||
self.main_window.set_opacity(self.colors["hudopacity"])
|
win.set_decorated(False)
|
||||||
self.main_window.set_focus_on_map(False)
|
win.set_opacity(self.colors["hudopacity"])
|
||||||
|
|
||||||
self.ebox = gtk.EventBox()
|
eventbox = gtk.EventBox()
|
||||||
self.label = gtk.Label("FPDB Menu (Right Click)\nLeft-drag to move")
|
label = gtk.Label("FPDB Menu - Right click\nLeft-Drag to Move")
|
||||||
|
|
||||||
self.backgroundcolor = gtk.gdk.color_parse(self.colors['hudbgcolor'])
|
win.add(eventbox)
|
||||||
self.foregroundcolor = gtk.gdk.color_parse(self.colors['hudfgcolor'])
|
eventbox.add(label)
|
||||||
|
|
||||||
self.label.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
|
label.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
|
||||||
self.label.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
|
label.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
|
||||||
|
|
||||||
self.main_window.add(self.ebox)
|
eventbox.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
|
||||||
self.ebox.add(self.label)
|
eventbox.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
|
||||||
|
|
||||||
self.ebox.modify_bg(gtk.STATE_NORMAL, self.backgroundcolor)
|
|
||||||
self.ebox.modify_fg(gtk.STATE_NORMAL, self.foregroundcolor)
|
|
||||||
|
|
||||||
|
self.main_window = win
|
||||||
self.main_window.move(self.table.x, self.table.y)
|
self.main_window.move(self.table.x, self.table.y)
|
||||||
|
|
||||||
# A popup menu for the main window
|
# A popup menu for the main window
|
||||||
self.menu = gtk.Menu()
|
menu = gtk.Menu()
|
||||||
self.item1 = gtk.MenuItem('Kill this HUD')
|
|
||||||
self.menu.append(self.item1)
|
killitem = gtk.MenuItem('Kill This HUD')
|
||||||
|
menu.append(killitem)
|
||||||
if self.parent != None:
|
if self.parent != None:
|
||||||
self.item1.connect("activate", self.parent.kill_hud, self.table_name)
|
killitem.connect("activate", self.parent.kill_hud, self.table_name)
|
||||||
self.item1.show()
|
|
||||||
|
|
||||||
self.item2 = gtk.MenuItem('Save Layout')
|
saveitem = gtk.MenuItem('Save HUD Layout')
|
||||||
self.menu.append(self.item2)
|
menu.append(saveitem)
|
||||||
self.item2.connect("activate", self.save_layout)
|
saveitem.connect("activate", self.save_layout)
|
||||||
self.item2.show()
|
|
||||||
|
|
||||||
self.item3 = gtk.MenuItem('Reposition Stats')
|
repositem = gtk.MenuItem('Reposition StatWindows')
|
||||||
self.menu.append(self.item3)
|
menu.append(repositem)
|
||||||
self.item3.connect("activate", self.reposition_windows)
|
repositem.connect("activate", self.reposition_windows)
|
||||||
self.item3.show()
|
|
||||||
|
|
||||||
self.item4 = gtk.MenuItem('Debug Stat Windows')
|
debugitem = gtk.MenuItem('Debug StatWindows')
|
||||||
self.menu.append(self.item4)
|
menu.append(debugitem)
|
||||||
self.item4.connect("activate", self.debug_stat_windows)
|
debugitem.connect("activate", self.debug_stat_windows)
|
||||||
self.item4.show()
|
|
||||||
|
|
||||||
self.item5 = gtk.MenuItem('Set max seats')
|
item5 = gtk.MenuItem('Set max seats')
|
||||||
self.menu.append(self.item5)
|
menu.append(item5)
|
||||||
self.item5.show()
|
maxSeatsMenu = gtk.Menu()
|
||||||
self.maxSeatsMenu = gtk.Menu()
|
item5.set_submenu(maxSeatsMenu)
|
||||||
self.item5.set_submenu(self.maxSeatsMenu)
|
|
||||||
for i in range(2, 11, 1):
|
for i in range(2, 11, 1):
|
||||||
item = gtk.MenuItem('%d-max' % i)
|
item = gtk.MenuItem('%d-max' % i)
|
||||||
item.ms = i
|
item.ms = i
|
||||||
self.maxSeatsMenu.append(item)
|
maxSeatsMenu.append(item)
|
||||||
item.connect("activate", self.change_max_seats)
|
item.connect("activate", self.change_max_seats)
|
||||||
item.show()
|
|
||||||
setattr(self, 'maxSeatsMenuItem%d' % (i-1), item)
|
setattr(self, 'maxSeatsMenuItem%d' % (i-1), item)
|
||||||
|
|
||||||
|
eventbox.connect_object("button-press-event", self.on_button_press, menu)
|
||||||
|
|
||||||
|
|
||||||
self.ebox.connect_object("button-press-event", self.on_button_press, self.menu)
|
|
||||||
|
|
||||||
self.main_window.show_all()
|
|
||||||
self.mw_created = True
|
self.mw_created = True
|
||||||
|
self.label = label
|
||||||
# TODO: fold all uses of this type of 'topify' code into a single function, if the differences between the versions don't
|
menu.show_all()
|
||||||
# create adverse effects?
|
self.main_window.show_all()
|
||||||
|
self.topify_window(self.main_window)
|
||||||
if os.name == 'nt':
|
|
||||||
self.topify_window(self.main_window)
|
|
||||||
else:
|
|
||||||
self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gets a gdk handle for poker client
|
|
||||||
self.main_window.gdkhandle = gtk.gdk.window_foreign_new(self.main_window.window.xid) # gets a gdk handle for the hud table window
|
|
||||||
self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) #
|
|
||||||
|
|
||||||
self.update_table_position()
|
|
||||||
|
|
||||||
def change_max_seats(self, widget):
|
def change_max_seats(self, widget):
|
||||||
if self.max != widget.ms:
|
if self.max != widget.ms:
|
||||||
|
@ -199,18 +185,18 @@ class Hud:
|
||||||
self.parent.kill_hud(self, self.table.name)
|
self.parent.kill_hud(self, self.table.name)
|
||||||
return False
|
return False
|
||||||
# anyone know how to do this in unix, or better yet, trap the X11 error that is triggered when executing the get_origin() for a closed window?
|
# anyone know how to do this in unix, or better yet, trap the X11 error that is triggered when executing the get_origin() for a closed window?
|
||||||
|
if self.table.gdkhandle is not None:
|
||||||
(x, y) = self.main_window.parentgdkhandle.get_origin()
|
(x, y) = self.table.gdkhandle.get_origin()
|
||||||
if self.table.x != x or self.table.y != y:
|
if self.table.x != x or self.table.y != y:
|
||||||
self.table.x = x
|
self.table.x = x
|
||||||
self.table.y = y
|
self.table.y = y
|
||||||
self.main_window.move(x, y)
|
self.main_window.move(x, y)
|
||||||
adj = self.adj_seats(self.hand, self.config)
|
adj = self.adj_seats(self.hand, self.config)
|
||||||
loc = self.config.get_locations(self.table.site, self.max)
|
loc = self.config.get_locations(self.table.site, self.max)
|
||||||
# TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason?
|
# TODO: is stat_windows getting converted somewhere from a list to a dict, for no good reason?
|
||||||
for i, w in enumerate(self.stat_windows.itervalues()):
|
for i, w in enumerate(self.stat_windows.itervalues()):
|
||||||
(x, y) = loc[adj[i+1]]
|
(x, y) = loc[adj[i+1]]
|
||||||
w.relocate(x, y)
|
w.relocate(x, y)
|
||||||
|
|
||||||
# While we're at it, fix the positions of mucked cards too
|
# While we're at it, fix the positions of mucked cards too
|
||||||
for aux in self.aux_windows:
|
for aux in self.aux_windows:
|
||||||
|
@ -350,7 +336,8 @@ class Hud:
|
||||||
for s in self.stat_dict:
|
for s in self.stat_dict:
|
||||||
statd = self.stat_dict[s]
|
statd = self.stat_dict[s]
|
||||||
try:
|
try:
|
||||||
self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
|
self.stat_windows[statd['seat']].player_id = statd['player_id']
|
||||||
|
#self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
|
||||||
except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here
|
except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here
|
||||||
self.max = 10
|
self.max = 10
|
||||||
self.create(hand, config, self.stat_dict, self.cards)
|
self.create(hand, config, self.stat_dict, self.cards)
|
||||||
|
@ -374,30 +361,12 @@ class Hud:
|
||||||
Stats.do_tip(window.e_box[r][c], tip)
|
Stats.do_tip(window.e_box[r][c], tip)
|
||||||
|
|
||||||
def topify_window(self, window):
|
def topify_window(self, window):
|
||||||
# """Set the specified gtk window to stayontop in MS Windows."""
|
window.set_focus_on_map(False)
|
||||||
#
|
window.set_accept_focus(False)
|
||||||
# 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:
|
|
||||||
self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number))
|
|
||||||
# self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0])
|
|
||||||
self.main_window.gdkhandle = self.main_window.window
|
|
||||||
self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle)
|
|
||||||
|
|
||||||
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
|
if not self.table.gdkhandle:
|
||||||
style |= win32con.WS_CLIPCHILDREN
|
self.table.gdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gtk handle to poker window
|
||||||
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
|
window.window.set_transient_for(self.table.gdkhandle)
|
||||||
# break
|
|
||||||
|
|
||||||
# window.set_title(real_name)
|
|
||||||
|
|
||||||
class Stat_Window:
|
class Stat_Window:
|
||||||
|
|
||||||
|
@ -407,7 +376,10 @@ class Stat_Window:
|
||||||
# and double-clicks.
|
# and double-clicks.
|
||||||
|
|
||||||
if event.button == 3: # right button event
|
if event.button == 3: # right button event
|
||||||
self.popups.append(Popup_window(widget, self))
|
newpopup = Popup_window(self.window, self)
|
||||||
|
#print "added popup", newpopup
|
||||||
|
# TODO: how should we go about making sure it doesn't open a dozen popups if you click?
|
||||||
|
self.popups.append(newpopup)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if event.button == 2: # middle button event
|
if event.button == 2: # middle button event
|
||||||
|
@ -416,6 +388,7 @@ class Stat_Window:
|
||||||
|
|
||||||
if event.button == 1: # left button event
|
if event.button == 1: # left button event
|
||||||
# TODO: make position saving save sizes as well?
|
# TODO: make position saving save sizes as well?
|
||||||
|
self.window.show_all()
|
||||||
if event.state & gtk.gdk.SHIFT_MASK:
|
if event.state & gtk.gdk.SHIFT_MASK:
|
||||||
self.window.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST, event.button, int(event.x_root), int(event.y_root), event.time)
|
self.window.begin_resize_drag(gtk.gdk.WINDOW_EDGE_SOUTH_EAST, event.button, int(event.x_root), int(event.y_root), event.time)
|
||||||
else:
|
else:
|
||||||
|
@ -423,12 +396,13 @@ class Stat_Window:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def noop(self, *args): # i'm going to try to connect the focus-in and focus-out events here, to see if that fixes any of the focus problems.
|
def noop(self, arga=None, argb=None): # i'm going to try to connect the focus-in and focus-out events here, to see if that fixes any of the focus problems.
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def kill_popup(self, popup):
|
def kill_popup(self, popup):
|
||||||
popup.window.destroy()
|
print "remove popup", popup
|
||||||
self.popups.remove(popup)
|
self.popups.remove(popup)
|
||||||
|
popup.window.destroy()
|
||||||
|
|
||||||
def kill_popups(self):
|
def kill_popups(self):
|
||||||
map(lambda x: x.window.destroy(), self.popups)
|
map(lambda x: x.window.destroy(), self.popups)
|
||||||
|
@ -458,7 +432,6 @@ class Stat_Window:
|
||||||
|
|
||||||
self.window.set_title("%s" % seat)
|
self.window.set_title("%s" % seat)
|
||||||
self.window.set_property("skip-taskbar-hint", True)
|
self.window.set_property("skip-taskbar-hint", True)
|
||||||
self.window.set_transient_for(parent.main_window)
|
|
||||||
self.window.set_focus_on_map(False)
|
self.window.set_focus_on_map(False)
|
||||||
|
|
||||||
grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False)
|
grid = gtk.Table(rows = game.rows, columns = game.cols, homogeneous = False)
|
||||||
|
@ -510,11 +483,26 @@ class Stat_Window:
|
||||||
self.window.connect("focus-in-event", self.noop)
|
self.window.connect("focus-in-event", self.noop)
|
||||||
self.window.connect("focus-out-event", self.noop)
|
self.window.connect("focus-out-event", self.noop)
|
||||||
self.window.connect("button_press_event", self.button_press_cb)
|
self.window.connect("button_press_event", self.button_press_cb)
|
||||||
|
self.window.set_focus_on_map(False)
|
||||||
|
self.window.set_accept_focus(False)
|
||||||
|
|
||||||
|
|
||||||
self.window.move(self.x, self.y)
|
self.window.move(self.x, self.y)
|
||||||
|
self.window.realize() # window must be realized before it has a gdkwindow so we can attach it to the table window..
|
||||||
|
self.topify_window(self.window)
|
||||||
|
|
||||||
self.window.hide()
|
self.window.hide()
|
||||||
|
|
||||||
|
def topify_window(self, window):
|
||||||
|
window.set_focus_on_map(False)
|
||||||
|
window.set_accept_focus(False)
|
||||||
|
|
||||||
|
if not self.table.gdkhandle:
|
||||||
|
self.table.gdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gtk handle to poker window
|
||||||
|
# window.window.reparent(self.table.gdkhandle, 0, 0)
|
||||||
|
window.window.set_transient_for(self.table.gdkhandle)
|
||||||
|
# window.present()
|
||||||
|
|
||||||
def destroy(*args): # call back for terminating the main eventloop
|
def destroy(*args): # call back for terminating the main eventloop
|
||||||
gtk.main_quit()
|
gtk.main_quit()
|
||||||
|
|
||||||
|
@ -530,6 +518,8 @@ class Popup_window:
|
||||||
self.window.set_gravity(gtk.gdk.GRAVITY_STATIC)
|
self.window.set_gravity(gtk.gdk.GRAVITY_STATIC)
|
||||||
self.window.set_title("popup")
|
self.window.set_title("popup")
|
||||||
self.window.set_property("skip-taskbar-hint", True)
|
self.window.set_property("skip-taskbar-hint", True)
|
||||||
|
self.window.set_focus_on_map(False)
|
||||||
|
self.window.set_accept_focus(False)
|
||||||
self.window.set_transient_for(parent.get_toplevel())
|
self.window.set_transient_for(parent.get_toplevel())
|
||||||
|
|
||||||
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
self.window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||||
|
@ -595,9 +585,6 @@ class Popup_window:
|
||||||
|
|
||||||
self.window.set_transient_for(stat_window.window)
|
self.window.set_transient_for(stat_window.window)
|
||||||
|
|
||||||
if os.name == 'nt':
|
|
||||||
self.topify_window(self.window)
|
|
||||||
|
|
||||||
def button_press_cb(self, widget, event, *args):
|
def button_press_cb(self, widget, event, *args):
|
||||||
# This handles all callbacks from button presses on the event boxes in
|
# This handles all callbacks from button presses on the event boxes in
|
||||||
# the popup windows. There is a bit of an ugly kludge to separate single-
|
# the popup windows. There is a bit of an ugly kludge to separate single-
|
||||||
|
@ -626,27 +613,15 @@ class Popup_window:
|
||||||
top.move(x, y)
|
top.move(x, y)
|
||||||
|
|
||||||
def topify_window(self, window):
|
def topify_window(self, window):
|
||||||
"""Set the specified gtk window to stayontop in MS Windows."""
|
window.set_focus_on_map(False)
|
||||||
|
window.set_accept_focus(False)
|
||||||
|
|
||||||
# def windowEnumerationHandler(hwnd, resultList):
|
if not self.table.gdkhandle:
|
||||||
# '''Callback for win32gui.EnumWindows() to generate list of window handles.'''
|
self.table.gdkhandle = gtk.gdk.window_foreign_new(int(self.table.number)) # gtk handle to poker window
|
||||||
# resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
|
# window.window.reparent(self.table.gdkhandle, 0, 0)
|
||||||
|
window.window.set_transient_for(self.table.gdkhandle)
|
||||||
|
# window.present()
|
||||||
|
|
||||||
# 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:
|
|
||||||
window.set_transient_for(self.parent.main_window)
|
|
||||||
style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE)
|
|
||||||
style |= win32con.WS_CLIPCHILDREN
|
|
||||||
win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style)
|
|
||||||
# break
|
|
||||||
|
|
||||||
# window.set_title(real_name)
|
|
||||||
|
|
||||||
if __name__== "__main__":
|
if __name__== "__main__":
|
||||||
main_window = gtk.Window()
|
main_window = gtk.Window()
|
||||||
|
@ -657,7 +632,7 @@ if __name__== "__main__":
|
||||||
|
|
||||||
c = Configuration.Config()
|
c = Configuration.Config()
|
||||||
#tables = Tables.discover(c)
|
#tables = Tables.discover(c)
|
||||||
t = Tables.discover_table_by_name(c, "Patriot Dr")
|
t = Tables.discover_table_by_name(c, "Corona")
|
||||||
if t is None:
|
if t is None:
|
||||||
print "Table not found."
|
print "Table not found."
|
||||||
db = Database.Database(c, 'fpdb', 'holdem')
|
db = Database.Database(c, 'fpdb', 'holdem')
|
||||||
|
|
224
pyfpdb/SQL.py
224
pyfpdb/SQL.py
|
@ -325,8 +325,14 @@ class Sql:
|
||||||
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
|
siteId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
|
||||||
buyin INT NOT NULL,
|
buyin INT NOT NULL,
|
||||||
fee INT NOT NULL,
|
fee INT NOT NULL,
|
||||||
knockout INT NOT NULL,
|
maxSeats INT NOT NULL DEFAULT -1,
|
||||||
rebuyOrAddon BOOLEAN NOT NULL)
|
knockout BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
rebuyOrAddon BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
speed varchar(10),
|
||||||
|
headsUp BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
shootout BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
matrix BOOLEAN NOT NULL DEFAULT False
|
||||||
|
)
|
||||||
ENGINE=INNODB"""
|
ENGINE=INNODB"""
|
||||||
elif db_server == 'postgresql':
|
elif db_server == 'postgresql':
|
||||||
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
|
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
|
||||||
|
@ -334,16 +340,28 @@ class Sql:
|
||||||
siteId INT NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
|
siteId INT NOT NULL, FOREIGN KEY (siteId) REFERENCES Sites(id),
|
||||||
buyin INT NOT NULL,
|
buyin INT NOT NULL,
|
||||||
fee INT NOT NULL,
|
fee INT NOT NULL,
|
||||||
knockout INT NOT NULL,
|
maxSeats INT NOT NULL DEFAULT -1,
|
||||||
rebuyOrAddon BOOLEAN NOT NULL)"""
|
knockout BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
rebuyOrAddon BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
speed varchar(10),
|
||||||
|
headsUp BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
shootout BOOLEAN NOT NULL DEFAULT False,
|
||||||
|
matrix BOOLEAN NOT NULL DEFAULT False
|
||||||
|
)"""
|
||||||
elif db_server == 'sqlite':
|
elif db_server == 'sqlite':
|
||||||
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
|
self.query['createTourneyTypesTable'] = """CREATE TABLE TourneyTypes (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
siteId INT NOT NULL,
|
siteId INT NOT NULL,
|
||||||
buyin INT NOT NULL,
|
buyin INT NOT NULL,
|
||||||
fee INT NOT NULL,
|
fee INT NOT NULL,
|
||||||
knockout INT NOT NULL,
|
maxSeats INT NOT NULL DEFAULT -1,
|
||||||
rebuyOrAddon BOOLEAN NOT NULL)"""
|
knockout BOOLEAN NOT NULL DEFAULT 0,
|
||||||
|
rebuyOrAddon BOOLEAN NOT NULL DEFAULT 0,
|
||||||
|
speed TEXT,
|
||||||
|
headsUp BOOLEAN NOT NULL DEFAULT 0,
|
||||||
|
shootout BOOLEAN NOT NULL DEFAULT 0,
|
||||||
|
matrix BOOLEAN NOT NULL DEFAULT 0
|
||||||
|
)"""
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Create Tourneys
|
# Create Tourneys
|
||||||
|
@ -352,32 +370,65 @@ class Sql:
|
||||||
if db_server == 'mysql':
|
if db_server == 'mysql':
|
||||||
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
|
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
|
||||||
id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
|
id INT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id),
|
||||||
tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
tourneyTypeId SMALLINT UNSIGNED NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
||||||
siteTourneyNo BIGINT NOT NULL,
|
siteTourneyNo BIGINT NOT NULL,
|
||||||
entries INT NOT NULL,
|
entries INT NOT NULL,
|
||||||
prizepool INT NOT NULL,
|
prizepool INT NOT NULL,
|
||||||
startTime DATETIME NOT NULL,
|
startTime DATETIME NOT NULL,
|
||||||
|
endTime DATETIME,
|
||||||
|
buyinChips INT,
|
||||||
|
tourneyName varchar(40),
|
||||||
|
matrixIdProcessed TINYINT UNSIGNED DEFAULT 0, /* Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn */
|
||||||
|
rebuyChips INT DEFAULT 0,
|
||||||
|
addonChips INT DEFAULT 0,
|
||||||
|
rebuyAmount INT DEFAULT 0,
|
||||||
|
addonAmount INT DEFAULT 0,
|
||||||
|
totalRebuys INT DEFAULT 0,
|
||||||
|
totalAddons INT DEFAULT 0,
|
||||||
|
koBounty INT DEFAULT 0,
|
||||||
comment TEXT,
|
comment TEXT,
|
||||||
commentTs DATETIME)
|
commentTs DATETIME)
|
||||||
ENGINE=INNODB"""
|
ENGINE=INNODB"""
|
||||||
elif db_server == 'postgresql':
|
elif db_server == 'postgresql':
|
||||||
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
|
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
|
||||||
id SERIAL, PRIMARY KEY (id),
|
id SERIAL, PRIMARY KEY (id),
|
||||||
tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
tourneyTypeId INT DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
||||||
siteTourneyNo BIGINT,
|
siteTourneyNo BIGINT,
|
||||||
entries INT,
|
entries INT,
|
||||||
prizepool INT,
|
prizepool INT,
|
||||||
startTime timestamp without time zone,
|
startTime timestamp without time zone,
|
||||||
|
endTime timestamp without time zone,
|
||||||
|
buyinChips INT,
|
||||||
|
tourneyName varchar(40),
|
||||||
|
matrixIdProcessed SMALLINT UNSIGNED DEFAULT 0, /* Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn */
|
||||||
|
rebuyChips INT DEFAULT 0,
|
||||||
|
addonChips INT DEFAULT 0,
|
||||||
|
rebuyAmount INT DEFAULT 0,
|
||||||
|
addonAmount INT DEFAULT 0,
|
||||||
|
totalRebuys INT DEFAULT 0,
|
||||||
|
totalAddons INT DEFAULT 0,
|
||||||
|
koBounty INT DEFAULT 0,
|
||||||
comment TEXT,
|
comment TEXT,
|
||||||
commentTs timestamp without time zone)"""
|
commentTs timestamp without time zone)"""
|
||||||
elif db_server == 'sqlite':
|
elif db_server == 'sqlite':
|
||||||
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
|
self.query['createTourneysTable'] = """CREATE TABLE Tourneys (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
tourneyTypeId INT,
|
tourneyTypeId INT DEFAULT 1,
|
||||||
siteTourneyNo INT,
|
siteTourneyNo INT,
|
||||||
entries INT,
|
entries INT,
|
||||||
prizepool INT,
|
prizepool INT,
|
||||||
startTime REAL,
|
startTime REAL,
|
||||||
|
endTime REAL,
|
||||||
|
buyinChips INT,
|
||||||
|
tourneyName TEXT,
|
||||||
|
matrixIdProcessed INT UNSIGNED DEFAULT 0, /* Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn */
|
||||||
|
rebuyChips INT DEFAULT 0,
|
||||||
|
addonChips INT DEFAULT 0,
|
||||||
|
rebuyAmount INT DEFAULT 0,
|
||||||
|
addonAmount INT DEFAULT 0,
|
||||||
|
totalRebuys INT DEFAULT 0,
|
||||||
|
totalAddons INT DEFAULT 0,
|
||||||
|
koBounty INT DEFAULT 0,
|
||||||
comment TEXT,
|
comment TEXT,
|
||||||
commentTs REAL)"""
|
commentTs REAL)"""
|
||||||
################################
|
################################
|
||||||
|
@ -409,7 +460,7 @@ class Sql:
|
||||||
comment text,
|
comment text,
|
||||||
commentTs DATETIME,
|
commentTs DATETIME,
|
||||||
tourneysPlayersId BIGINT UNSIGNED,
|
tourneysPlayersId BIGINT UNSIGNED,
|
||||||
tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
tourneyTypeId SMALLINT UNSIGNED NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
||||||
|
|
||||||
wonWhenSeenStreet1 FLOAT,
|
wonWhenSeenStreet1 FLOAT,
|
||||||
wonWhenSeenStreet2 FLOAT,
|
wonWhenSeenStreet2 FLOAT,
|
||||||
|
@ -527,7 +578,7 @@ class Sql:
|
||||||
comment text,
|
comment text,
|
||||||
commentTs timestamp without time zone,
|
commentTs timestamp without time zone,
|
||||||
tourneysPlayersId BIGINT,
|
tourneysPlayersId BIGINT,
|
||||||
tourneyTypeId INT NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
tourneyTypeId INT NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
||||||
|
|
||||||
wonWhenSeenStreet1 FLOAT,
|
wonWhenSeenStreet1 FLOAT,
|
||||||
wonWhenSeenStreet2 FLOAT,
|
wonWhenSeenStreet2 FLOAT,
|
||||||
|
@ -644,7 +695,7 @@ class Sql:
|
||||||
comment TEXT,
|
comment TEXT,
|
||||||
commentTs REAL,
|
commentTs REAL,
|
||||||
tourneysPlayersId INT,
|
tourneysPlayersId INT,
|
||||||
tourneyTypeId INT NOT NULL,
|
tourneyTypeId INT NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
wonWhenSeenStreet1 REAL,
|
wonWhenSeenStreet1 REAL,
|
||||||
wonWhenSeenStreet2 REAL,
|
wonWhenSeenStreet2 REAL,
|
||||||
|
@ -749,6 +800,9 @@ class Sql:
|
||||||
payinAmount INT NOT NULL,
|
payinAmount INT NOT NULL,
|
||||||
rank INT NOT NULL,
|
rank INT NOT NULL,
|
||||||
winnings INT NOT NULL,
|
winnings INT NOT NULL,
|
||||||
|
nbRebuys INT DEFAULT 0,
|
||||||
|
nbAddons INT DEFAULT 0,
|
||||||
|
nbKO INT DEFAULT 0,
|
||||||
comment TEXT,
|
comment TEXT,
|
||||||
commentTs DATETIME)
|
commentTs DATETIME)
|
||||||
ENGINE=INNODB"""
|
ENGINE=INNODB"""
|
||||||
|
@ -760,6 +814,9 @@ class Sql:
|
||||||
payinAmount INT,
|
payinAmount INT,
|
||||||
rank INT,
|
rank INT,
|
||||||
winnings INT,
|
winnings INT,
|
||||||
|
nbRebuys INT DEFAULT 0,
|
||||||
|
nbAddons INT DEFAULT 0,
|
||||||
|
nbKO INT DEFAULT 0,
|
||||||
comment TEXT,
|
comment TEXT,
|
||||||
commentTs timestamp without time zone)"""
|
commentTs timestamp without time zone)"""
|
||||||
elif db_server == 'sqlite':
|
elif db_server == 'sqlite':
|
||||||
|
@ -808,7 +865,7 @@ class Sql:
|
||||||
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
|
playerId INT UNSIGNED NOT NULL, FOREIGN KEY (playerId) REFERENCES Players(id),
|
||||||
activeSeats SMALLINT NOT NULL,
|
activeSeats SMALLINT NOT NULL,
|
||||||
position CHAR(1),
|
position CHAR(1),
|
||||||
tourneyTypeId SMALLINT UNSIGNED NOT NULL, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
tourneyTypeId SMALLINT UNSIGNED NOT NULL DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
||||||
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
|
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
|
||||||
HDs INT NOT NULL,
|
HDs INT NOT NULL,
|
||||||
|
|
||||||
|
@ -909,7 +966,7 @@ class Sql:
|
||||||
playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id),
|
playerId INT, FOREIGN KEY (playerId) REFERENCES Players(id),
|
||||||
activeSeats SMALLINT,
|
activeSeats SMALLINT,
|
||||||
position CHAR(1),
|
position CHAR(1),
|
||||||
tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
tourneyTypeId INT DEFAULT 1, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id),
|
||||||
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
|
styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
|
||||||
HDs INT,
|
HDs INT,
|
||||||
|
|
||||||
|
@ -1008,7 +1065,7 @@ class Sql:
|
||||||
playerId INT,
|
playerId INT,
|
||||||
activeSeats INT,
|
activeSeats INT,
|
||||||
position TEXT,
|
position TEXT,
|
||||||
tourneyTypeId INT,
|
tourneyTypeId INT DEFAULT 1,
|
||||||
styleKey TEXT NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
|
styleKey TEXT NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */
|
||||||
HDs INT,
|
HDs INT,
|
||||||
|
|
||||||
|
@ -2759,6 +2816,143 @@ class Sql:
|
||||||
WHERE gametypeId=%s AND siteHandNo=%s
|
WHERE gametypeId=%s AND siteHandNo=%s
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self.query['getTourneyTypeIdByTourneyNo'] = """SELECT tt.id,
|
||||||
|
tt.buyin,
|
||||||
|
tt.fee,
|
||||||
|
tt.maxSeats,
|
||||||
|
tt.knockout,
|
||||||
|
tt.rebuyOrAddon,
|
||||||
|
tt.speed,
|
||||||
|
tt.headsUp,
|
||||||
|
tt.shootout,
|
||||||
|
tt.matrix
|
||||||
|
FROM TourneyTypes tt
|
||||||
|
INNER JOIN Tourneys t ON (t.tourneyTypeId = tt.id)
|
||||||
|
WHERE t.siteTourneyNo=%s AND tt.siteId=%s
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['getTourneyTypeId'] = """SELECT id
|
||||||
|
FROM TourneyTypes
|
||||||
|
WHERE siteId=%s
|
||||||
|
AND buyin=%s
|
||||||
|
AND fee=%s
|
||||||
|
AND knockout=%s
|
||||||
|
AND rebuyOrAddon=%s
|
||||||
|
AND speed=%s
|
||||||
|
AND headsUp=%s
|
||||||
|
AND shootout=%s
|
||||||
|
AND matrix=%s
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['insertTourneyTypes'] = """INSERT INTO TourneyTypes
|
||||||
|
(siteId, buyin, fee, knockout, rebuyOrAddon
|
||||||
|
,speed, headsUp, shootout, matrix)
|
||||||
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['getTourney'] = """SELECT t.id,
|
||||||
|
t.tourneyTypeId,
|
||||||
|
t.entries,
|
||||||
|
t.prizepool,
|
||||||
|
t.startTime,
|
||||||
|
t.endTime,
|
||||||
|
t.buyinChips,
|
||||||
|
t.tourneyName,
|
||||||
|
t.matrixIdProcessed,
|
||||||
|
t.rebuyChips,
|
||||||
|
t.addonChips,
|
||||||
|
t.rebuyAmount,
|
||||||
|
t.addonAmount,
|
||||||
|
t.totalRebuys,
|
||||||
|
t.totalAddons,
|
||||||
|
t.koBounty,
|
||||||
|
t.comment
|
||||||
|
FROM Tourneys t
|
||||||
|
INNER JOIN TourneyTypes tt ON (t.tourneyTypeId = tt.id)
|
||||||
|
WHERE t.siteTourneyNo=%s AND tt.siteId=%s
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['insertTourney'] = """INSERT INTO Tourneys
|
||||||
|
(tourneyTypeId, siteTourneyNo, entries, prizepool,
|
||||||
|
startTime, endTime, buyinChips, tourneyName, matrixIdProcessed,
|
||||||
|
rebuyChips, addonChips, rebuyAmount, addonAmount, totalRebuys,
|
||||||
|
totalAddons, koBounty, comment, commentTs)
|
||||||
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
|
||||||
|
%s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['updateTourney'] = """UPDATE Tourneys
|
||||||
|
SET tourneyTypeId = %s,
|
||||||
|
entries = %s,
|
||||||
|
prizepool = %s,
|
||||||
|
startTime = %s,
|
||||||
|
endTime = %s,
|
||||||
|
buyinChips = %s,
|
||||||
|
tourneyName = %s,
|
||||||
|
matrixIdProcessed = %s,
|
||||||
|
rebuyChips = %s,
|
||||||
|
addonChips = %s,
|
||||||
|
rebuyAmount = %s,
|
||||||
|
addonAmount = %s,
|
||||||
|
totalRebuys = %s,
|
||||||
|
totalAddons = %s,
|
||||||
|
koBounty = %s,
|
||||||
|
comment = %s,
|
||||||
|
commentTs = %s
|
||||||
|
WHERE id=%s
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['getTourneysPlayers'] = """SELECT id,
|
||||||
|
payinAmount,
|
||||||
|
rank,
|
||||||
|
winnings,
|
||||||
|
nbRebuys,
|
||||||
|
nbAddons,
|
||||||
|
nbKO,
|
||||||
|
comment,
|
||||||
|
commentTs
|
||||||
|
FROM TourneysPlayers
|
||||||
|
WHERE tourneyId=%s AND playerId+0=%s
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['updateTourneysPlayers'] = """UPDATE TourneysPlayers
|
||||||
|
SET payinAmount = %s,
|
||||||
|
rank = %s,
|
||||||
|
winnings = %s,
|
||||||
|
nbRebuys = %s,
|
||||||
|
nbAddons = %s,
|
||||||
|
nbKO = %s,
|
||||||
|
comment = %s,
|
||||||
|
commentTs = %s
|
||||||
|
WHERE id=%s
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['insertTourneysPlayers'] = """INSERT INTO TourneysPlayers
|
||||||
|
(tourneyId, playerId, payinAmount, rank, winnings, nbRebuys, nbAddons, nbKO, comment, commentTs)
|
||||||
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.query['selectHandsPlayersWithWrongTTypeId'] = """SELECT id
|
||||||
|
FROM HandsPlayers
|
||||||
|
WHERE tourneyTypeId <> %s AND (TourneysPlayersId+0=%s)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# self.query['updateHandsPlayersForTTypeId2'] = """UPDATE HandsPlayers
|
||||||
|
# SET tourneyTypeId= %s
|
||||||
|
# WHERE (TourneysPlayersId+0=%s)
|
||||||
|
# """
|
||||||
|
|
||||||
|
self.query['updateHandsPlayersForTTypeId'] = """UPDATE HandsPlayers
|
||||||
|
SET tourneyTypeId= %s
|
||||||
|
WHERE (id=%s)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
self.query['handsPlayersTTypeId_joiner'] = " OR TourneysPlayersId+0="
|
||||||
|
self.query['handsPlayersTTypeId_joiner_id'] = " OR id="
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if db_server == 'mysql':
|
if db_server == 'mysql':
|
||||||
self.query['placeholder'] = u'%s'
|
self.query['placeholder'] = u'%s'
|
||||||
elif db_server == 'postgresql':
|
elif db_server == 'postgresql':
|
||||||
|
|
|
@ -69,6 +69,7 @@ class Table_Window:
|
||||||
if 'site' in info: self.site = info['site']
|
if 'site' in info: self.site = info['site']
|
||||||
if 'title' in info: self.title = info['title']
|
if 'title' in info: self.title = info['title']
|
||||||
if 'name' in info: self.name = info['name']
|
if 'name' in info: self.name = info['name']
|
||||||
|
self.gdkhandle = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# __str__ method for testing
|
# __str__ method for testing
|
||||||
|
@ -243,6 +244,9 @@ def discover_nt_by_name(c, tablename):
|
||||||
if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window
|
if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window
|
||||||
if 'HUD:' in titles[hwnd]: continue # FPDB HUD window
|
if 'HUD:' in titles[hwnd]: continue # FPDB HUD window
|
||||||
if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows
|
if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows
|
||||||
|
if ' - Table ' in titles[hwnd]: continue # Absolute table Chat window.. sigh. TODO: Can we tell what site we're trying to discover for somehow in here, so i can limit this check just to AP searches?
|
||||||
|
temp = decode_windows(c, titles[hwnd], hwnd)
|
||||||
|
#print "attach to window", temp
|
||||||
return decode_windows(c, titles[hwnd], hwnd)
|
return decode_windows(c, titles[hwnd], hwnd)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ class Tourney(object):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, sitename, gametype, summaryText, builtFrom = "HHC"):
|
def __init__(self, sitename, gametype, summaryText, builtFrom = "HHC"):
|
||||||
print "Tourney.__init__"
|
|
||||||
self.sitename = sitename
|
self.sitename = sitename
|
||||||
self.siteId = self.SITEIDS[sitename]
|
self.siteId = self.SITEIDS[sitename]
|
||||||
self.gametype = gametype
|
self.gametype = gametype
|
||||||
|
@ -74,21 +73,21 @@ class Tourney(object):
|
||||||
self.subTourneyFee = None
|
self.subTourneyFee = None
|
||||||
self.rebuyChips = 0
|
self.rebuyChips = 0
|
||||||
self.addOnChips = 0
|
self.addOnChips = 0
|
||||||
self.countRebuys = 0
|
|
||||||
self.countAddOns = 0
|
|
||||||
self.rebuyAmount = 0
|
self.rebuyAmount = 0
|
||||||
self.addOnAmount = 0
|
self.addOnAmount = 0
|
||||||
self.totalRebuys = 0
|
self.totalRebuys = 0
|
||||||
self.totalAddOns = 0
|
self.totalAddOns = 0
|
||||||
self.koBounty = 0
|
self.koBounty = 0
|
||||||
self.countKO = 0 #To use for winnings calculation which is not counted in the rest of the summary file
|
self.tourneyComment = None
|
||||||
self.players = []
|
self.players = []
|
||||||
|
|
||||||
# Collections indexed by player names
|
# Collections indexed by player names
|
||||||
self.finishPositions = {}
|
self.finishPositions = {}
|
||||||
self.winnings = {}
|
self.winnings = {}
|
||||||
|
self.payinAmounts = {}
|
||||||
|
self.countRebuys = {}
|
||||||
|
self.countAddOns = {}
|
||||||
|
self.countKO = {}
|
||||||
|
|
||||||
# currency symbol for this summary
|
# currency symbol for this summary
|
||||||
self.sym = None
|
self.sym = None
|
||||||
|
@ -122,20 +121,20 @@ class Tourney(object):
|
||||||
("ADDON CHIPS", self.addOnChips),
|
("ADDON CHIPS", self.addOnChips),
|
||||||
("REBUY AMOUNT", self.rebuyAmount),
|
("REBUY AMOUNT", self.rebuyAmount),
|
||||||
("ADDON AMOUNT", self.addOnAmount),
|
("ADDON AMOUNT", self.addOnAmount),
|
||||||
("COUNT REBUYS", self.countRebuys),
|
|
||||||
("COUNT ADDONS", self.countAddOns),
|
|
||||||
("NB REBUYS", self.countRebuys),
|
|
||||||
("NB ADDONS", self.countAddOns),
|
|
||||||
("TOTAL REBUYS", self.totalRebuys),
|
("TOTAL REBUYS", self.totalRebuys),
|
||||||
("TOTAL ADDONS", self.totalAddOns),
|
("TOTAL ADDONS", self.totalAddOns),
|
||||||
("KO BOUNTY", self.koBounty),
|
("KO BOUNTY", self.koBounty),
|
||||||
("NB OF KO", self.countKO)
|
("TOURNEY COMMENT", self.tourneyComment)
|
||||||
)
|
)
|
||||||
|
|
||||||
structs = ( ("GAMETYPE", self.gametype),
|
structs = ( ("GAMETYPE", self.gametype),
|
||||||
("PLAYERS", self.players),
|
("PLAYERS", self.players),
|
||||||
|
("PAYIN AMOUNTS", self.payinAmounts),
|
||||||
("POSITIONS", self.finishPositions),
|
("POSITIONS", self.finishPositions),
|
||||||
("WINNINGS", self.winnings),
|
("WINNINGS", self.winnings),
|
||||||
|
("COUNT REBUYS", self.countRebuys),
|
||||||
|
("COUNT ADDONS", self.countAddOns),
|
||||||
|
("NB OF KO", self.countKO)
|
||||||
)
|
)
|
||||||
str = ''
|
str = ''
|
||||||
for (name, var) in vars:
|
for (name, var) in vars:
|
||||||
|
@ -152,7 +151,6 @@ class Tourney(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def insert(self, db):
|
def insert(self, db):
|
||||||
print "TODO: Insert Tourney in DB"
|
|
||||||
# First : check all needed info is filled in the object, especially for the initial select
|
# First : check all needed info is filled in the object, especially for the initial select
|
||||||
|
|
||||||
# Notes on DB Insert
|
# Notes on DB Insert
|
||||||
|
@ -163,6 +161,19 @@ class Tourney(object):
|
||||||
# Starttime may not match the one in the Summary file : HH = time of the first Hand / could be slighltly different from the one in the summary file
|
# Starttime may not match the one in the Summary file : HH = time of the first Hand / could be slighltly different from the one in the summary file
|
||||||
# Note: If the TourneyNo could be a unique id .... this would really be a relief to deal with matrix matches ==> Ask on the IRC / Ask Fulltilt ??
|
# Note: If the TourneyNo could be a unique id .... this would really be a relief to deal with matrix matches ==> Ask on the IRC / Ask Fulltilt ??
|
||||||
|
|
||||||
|
dbTourneyTypeId = db.tRecogniseTourneyType(self)
|
||||||
|
logging.debug("Tourney Type ID = %d" % dbTourneyTypeId)
|
||||||
|
dbTourneyId = db.tRecognizeTourney(self, dbTourneyTypeId)
|
||||||
|
logging.debug("Tourney ID = %d" % dbTourneyId)
|
||||||
|
dbTourneysPlayersIds = db.tStoreTourneyPlayers(self, dbTourneyId)
|
||||||
|
logging.debug("TourneysPlayersId = %s" % dbTourneysPlayersIds)
|
||||||
|
db.tUpdateTourneysHandsPlayers(self, dbTourneysPlayersIds, dbTourneyTypeId)
|
||||||
|
logging.debug("tUpdateTourneysHandsPlayers done")
|
||||||
|
logging.debug("Tourney Insert done")
|
||||||
|
|
||||||
|
# TO DO : Return what has been done (tourney created, updated, nothing)
|
||||||
|
# ?? stored = 1 if tourney is fully created / duplicates = 1, if everything was already here and correct / partial=1 if some things were already here (between tourney, tourneyPlayers and handsplayers)
|
||||||
|
# if so, prototypes may need changes to know what has been done or make some kind of dict in Tourney object that could be updated during the insert process to store that information
|
||||||
stored = 0
|
stored = 0
|
||||||
duplicates = 0
|
duplicates = 0
|
||||||
partial = 0
|
partial = 0
|
||||||
|
@ -246,18 +257,21 @@ db: a connected fpdb_db object"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def addPlayer(self, rank, name, winnings):
|
def addPlayer(self, rank, name, winnings, payinAmount, nbRebuys, nbAddons, nbKO):
|
||||||
"""\
|
"""\
|
||||||
Adds a player to the tourney, and initialises data structures indexed by player.
|
Adds a player to the tourney, and initialises data structures indexed by player.
|
||||||
rank (int) indicating the finishing rank (can be -1 if unknown)
|
rank (int) indicating the finishing rank (can be -1 if unknown)
|
||||||
name (string) player name
|
name (string) player name
|
||||||
winnings (string) the money the player ended the tourney with (can be 0, or -1 if unknown)
|
winnings (decimal) the money the player ended the tourney with (can be 0, or -1 if unknown)
|
||||||
"""
|
"""
|
||||||
log.debug("addPlayer: rank:%s - name : '%s' - Winnings (%s)" % (rank, name, winnings))
|
log.debug("addPlayer: rank:%s - name : '%s' - Winnings (%s)" % (rank, name, winnings))
|
||||||
winnings = re.sub(u',', u'', winnings) #some sites have commas
|
|
||||||
self.players.append(name)
|
self.players.append(name)
|
||||||
self.finishPositions.update( { name : Decimal(rank) } )
|
self.finishPositions.update( { name : Decimal(rank) } )
|
||||||
self.winnings.update( { name : Decimal(winnings) } )
|
self.winnings.update( { name : Decimal(winnings) } )
|
||||||
|
self.payinAmounts.update( {name : Decimal(payinAmount) } )
|
||||||
|
self.countRebuys.update( {name: Decimal(nbRebuys) } )
|
||||||
|
self.countAddOns.update( {name: Decimal(nbAddons) } )
|
||||||
|
self.countKO.update( {name : Decimal(nbKO) } )
|
||||||
|
|
||||||
|
|
||||||
def incrementPlayerWinnings(self, name, additionnalWinnings):
|
def incrementPlayerWinnings(self, name, additionnalWinnings):
|
||||||
|
@ -270,11 +284,6 @@ winnings (string) the money the player ended the tourney with (can be 0, or -
|
||||||
|
|
||||||
self.winnings[name] = oldWins + Decimal(additionnalWinnings)
|
self.winnings[name] = oldWins + Decimal(additionnalWinnings)
|
||||||
|
|
||||||
|
|
||||||
def calculatePayinAmount(self):
|
|
||||||
return self.buyin + self.fee + (self.rebuyAmount * self.countRebuys) + (self.addOnAmount * self.countAddOns )
|
|
||||||
|
|
||||||
|
|
||||||
def checkPlayerExists(self,player):
|
def checkPlayerExists(self,player):
|
||||||
if player not in [p[1] for p in self.players]:
|
if player not in [p[1] for p in self.players]:
|
||||||
print "checkPlayerExists", player, "fail"
|
print "checkPlayerExists", player, "fail"
|
||||||
|
|
149
pyfpdb/fpdb.py
149
pyfpdb/fpdb.py
|
@ -76,43 +76,37 @@ import SQL
|
||||||
import Database
|
import Database
|
||||||
import FpdbSQLQueries
|
import FpdbSQLQueries
|
||||||
import Configuration
|
import Configuration
|
||||||
|
from Exceptions import *
|
||||||
|
|
||||||
VERSION = "0.11"
|
VERSION = "0.11"
|
||||||
|
|
||||||
class fpdb:
|
class fpdb:
|
||||||
def tab_clicked(self, widget, tab_name):
|
def tab_clicked(self, widget, tab_name):
|
||||||
"""called when a tab button is clicked to activate that tab"""
|
"""called when a tab button is clicked to activate that tab"""
|
||||||
#print "start of tab_clicked"
|
|
||||||
self.display_tab(tab_name)
|
self.display_tab(tab_name)
|
||||||
#end def tab_clicked
|
|
||||||
|
|
||||||
def add_and_display_tab(self, new_tab, new_tab_name):
|
def add_and_display_tab(self, new_tab, new_tab_name):
|
||||||
"""just calls the component methods"""
|
"""just calls the component methods"""
|
||||||
self.add_tab(new_tab, new_tab_name)
|
self.add_tab(new_tab, new_tab_name)
|
||||||
self.display_tab(new_tab_name)
|
self.display_tab(new_tab_name)
|
||||||
#end def add_and_display_tab
|
|
||||||
|
|
||||||
def add_tab(self, new_tab, new_tab_name):
|
def add_tab(self, new_tab, new_tab_name):
|
||||||
"""adds a tab, namely creates the button and displays it and appends all the relevant arrays"""
|
"""adds a tab, namely creates the button and displays it and appends all the relevant arrays"""
|
||||||
#print "start of add_tab"
|
|
||||||
for i in self.tab_names: #todo: check this is valid
|
for i in self.tab_names: #todo: check this is valid
|
||||||
if i==new_tab_name:
|
if i == new_tab_name:
|
||||||
return # we depend on this to not create duplicate tabs, there's no reason to raise an error here?
|
return # if tab already exists, just go to it
|
||||||
# raise fpdb_simple.FpdbError("duplicate tab_name not permitted")
|
|
||||||
|
|
||||||
self.tabs.append(new_tab)
|
self.tabs.append(new_tab)
|
||||||
self.tab_names.append(new_tab_name)
|
self.tab_names.append(new_tab_name)
|
||||||
|
|
||||||
new_tab_sel_button=gtk.ToggleButton(new_tab_name)
|
new_tab_sel_button = gtk.ToggleButton(new_tab_name)
|
||||||
new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name)
|
new_tab_sel_button.connect("clicked", self.tab_clicked, new_tab_name)
|
||||||
self.tab_box.add(new_tab_sel_button)
|
self.tab_box.add(new_tab_sel_button)
|
||||||
new_tab_sel_button.show()
|
new_tab_sel_button.show()
|
||||||
self.tab_buttons.append(new_tab_sel_button)
|
self.tab_buttons.append(new_tab_sel_button)
|
||||||
#end def add_tab
|
|
||||||
|
|
||||||
def display_tab(self, new_tab_name):
|
def display_tab(self, new_tab_name):
|
||||||
"""displays the indicated tab"""
|
"""displays the indicated tab"""
|
||||||
#print "start of display_tab, len(self.tab_names):",len(self.tab_names)
|
|
||||||
tab_no = -1
|
tab_no = -1
|
||||||
for i, name in enumerate(self.tab_names):
|
for i, name in enumerate(self.tab_names):
|
||||||
if name == new_tab_name:
|
if name == new_tab_name:
|
||||||
|
@ -120,73 +114,71 @@ class fpdb:
|
||||||
break
|
break
|
||||||
|
|
||||||
if tab_no == -1:
|
if tab_no == -1:
|
||||||
raise fpdb_simple.FpdbError("invalid tab_no")
|
raise FpdbError("invalid tab_no")
|
||||||
else:
|
else:
|
||||||
self.main_vbox.remove(self.current_tab)
|
self.main_vbox.remove(self.current_tab)
|
||||||
#self.current_tab.destroy()
|
|
||||||
self.current_tab=self.tabs[tab_no]
|
self.current_tab=self.tabs[tab_no]
|
||||||
self.main_vbox.add(self.current_tab)
|
self.main_vbox.add(self.current_tab)
|
||||||
self.tab_buttons[tab_no].set_active(True)
|
self.tab_buttons[tab_no].set_active(True)
|
||||||
self.current_tab.show()
|
self.current_tab.show()
|
||||||
#end def display_tab
|
|
||||||
|
|
||||||
def delete_event(self, widget, event, data=None):
|
def delete_event(self, widget, event, data=None):
|
||||||
return False
|
return False
|
||||||
#end def delete_event
|
|
||||||
|
|
||||||
def destroy(self, widget, data=None):
|
def destroy(self, widget, data=None):
|
||||||
self.quit(widget)
|
self.quit(widget)
|
||||||
#end def destroy
|
|
||||||
|
|
||||||
def dia_about(self, widget, data=None):
|
def dia_about(self, widget, data=None):
|
||||||
print "todo: implement dia_about",
|
#self.warning_box("About FPDB:\n\nFPDB was originally created by a guy named Steffen, sometime in 2008, \nand is mostly worked on these days by people named Eratosthenes, s0rrow, _mt, EricBlade, sqlcoder, and other strange people.\n\n", "ABOUT FPDB")
|
||||||
print " version = %s, requires database version %s" % (VERSION, "118")
|
dia = gtk.AboutDialog()
|
||||||
#end def dia_about
|
dia.set_name("FPDB")
|
||||||
|
dia.set_version(VERSION)
|
||||||
|
dia.set_copyright("2008-2009, Steffen, Eratosthenes, s0rrow, EricBlade, _mt, sqlcoder, and others")
|
||||||
|
dia.set_comments("GTK AboutDialog comments here")
|
||||||
|
dia.set_license("GPL v3")
|
||||||
|
dia.set_website("http://fpdb.sourceforge.net/")
|
||||||
|
dia.set_authors("Steffen, Eratosthenes, s0rrow, EricBlade, _mt, and others")
|
||||||
|
dia.set_program_name("FPDB")
|
||||||
|
dia.run()
|
||||||
|
dia.destroy()
|
||||||
|
|
||||||
def dia_create_del_database(self, widget, data=None):
|
def dia_create_del_database(self, widget, data=None):
|
||||||
print "todo: implement dia_create_del_database"
|
self.warning_box("Unimplemented: Create/Delete Database")
|
||||||
self.obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_create_del_database
|
|
||||||
|
|
||||||
def dia_create_del_user(self, widget, data=None):
|
def dia_create_del_user(self, widget, data=None):
|
||||||
print "todo: implement dia_create_del_user"
|
self.warning_box("Unimplemented: Create/Delete user")
|
||||||
self.obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_create_del_user
|
|
||||||
|
|
||||||
def dia_database_stats(self, widget, data=None):
|
def dia_database_stats(self, widget, data=None):
|
||||||
print "todo: implement dia_database_stats"
|
self.warning_box("Unimplemented: Database Stats")
|
||||||
#string=fpdb_db.getDbStats(db, cursor)
|
|
||||||
#end def dia_database_stats
|
|
||||||
|
|
||||||
def dia_database_sessions(self, widget, data=None):
|
def dia_database_sessions(self, widget, data=None):
|
||||||
new_sessions_thread=GuiSessionViewer.GuiSessionViewer(self.config, self.sql)
|
new_sessions_thread = GuiSessionViewer.GuiSessionViewer(self.config, self.sql)
|
||||||
self.threads.append(new_sessions_thread)
|
self.threads.append(new_sessions_thread)
|
||||||
sessions_tab=new_sessions_thread.get_vbox()
|
sessions_tab=new_sessions_thread.get_vbox()
|
||||||
self.add_and_display_tab(sessions_tab, "Sessions")
|
self.add_and_display_tab(sessions_tab, "Sessions")
|
||||||
|
|
||||||
def dia_delete_db_parts(self, widget, data=None):
|
def dia_delete_db_parts(self, widget, data=None):
|
||||||
print "todo: implement dia_delete_db_parts"
|
self.warning_box("Unimplemented: Delete Database Parts")
|
||||||
self.obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_delete_db_parts
|
|
||||||
|
|
||||||
def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None):
|
def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None):
|
||||||
print "todo: implement dia_edit_profile"
|
self.warning_box("Unimplemented: Edit Profile")
|
||||||
self.obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_edit_profile
|
|
||||||
|
|
||||||
def dia_export_db(self, widget, data=None):
|
def dia_export_db(self, widget, data=None):
|
||||||
print "todo: implement dia_export_db"
|
self.warning_box("Unimplemented: Export Database")
|
||||||
self.obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_export_db
|
|
||||||
|
|
||||||
def dia_get_db_root_credentials(self):
|
def dia_get_db_root_credentials(self):
|
||||||
"""obtains db root credentials from user"""
|
"""obtains db root credentials from user"""
|
||||||
print "todo: implement dia_get_db_root_credentials"
|
self.warning_box("Unimplemented: Get Root Database Credentials")
|
||||||
# user, pw=None, None
|
# user, pw=None, None
|
||||||
#
|
#
|
||||||
# dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0,
|
# dialog=gtk.Dialog(title="DB Credentials needed", parent=None, flags=0,
|
||||||
|
@ -202,17 +194,14 @@ class fpdb:
|
||||||
# response=dialog.run()
|
# response=dialog.run()
|
||||||
# dialog.destroy()
|
# dialog.destroy()
|
||||||
# return (user, pw, response)
|
# return (user, pw, response)
|
||||||
#end def dia_get_db_root_credentials
|
|
||||||
|
|
||||||
def dia_import_db(self, widget, data=None):
|
def dia_import_db(self, widget, data=None):
|
||||||
print "todo: implement dia_import_db"
|
self.warning_box("Unimplemented: Import Database")
|
||||||
self.obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_import_db
|
|
||||||
|
|
||||||
def dia_licensing(self, widget, data=None):
|
def dia_licensing(self, widget, data=None):
|
||||||
print "todo: implement dia_licensing"
|
self.warning_box("Unimplemented: Licensing")
|
||||||
#end def dia_licensing
|
|
||||||
|
|
||||||
def dia_load_profile(self, widget, data=None):
|
def dia_load_profile(self, widget, data=None):
|
||||||
"""Dialogue to select a file to load a profile from"""
|
"""Dialogue to select a file to load a profile from"""
|
||||||
|
@ -236,7 +225,6 @@ class fpdb:
|
||||||
#except:
|
#except:
|
||||||
# pass
|
# pass
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_load_profile
|
|
||||||
|
|
||||||
def dia_recreate_tables(self, widget, data=None):
|
def dia_recreate_tables(self, widget, data=None):
|
||||||
"""Dialogue that asks user to confirm that he wants to delete and recreate the tables"""
|
"""Dialogue that asks user to confirm that he wants to delete and recreate the tables"""
|
||||||
|
@ -266,7 +254,6 @@ class fpdb:
|
||||||
print 'User cancelled recreating tables'
|
print 'User cancelled recreating tables'
|
||||||
#if not lock_released:
|
#if not lock_released:
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_recreate_tables
|
|
||||||
|
|
||||||
def dia_recreate_hudcache(self, widget, data=None):
|
def dia_recreate_hudcache(self, widget, data=None):
|
||||||
if self.obtain_global_lock():
|
if self.obtain_global_lock():
|
||||||
|
@ -282,20 +269,15 @@ class fpdb:
|
||||||
print 'User cancelled rebuilding hud cache'
|
print 'User cancelled rebuilding hud cache'
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
|
|
||||||
|
|
||||||
def dia_regression_test(self, widget, data=None):
|
def dia_regression_test(self, widget, data=None):
|
||||||
print "todo: implement dia_regression_test"
|
self.warning_box("Unimplemented: Regression Test")
|
||||||
self.obtain_global_lock()
|
self.obtain_global_lock()
|
||||||
self.release_global_lock()
|
self.release_global_lock()
|
||||||
#end def dia_regression_test
|
|
||||||
|
|
||||||
def dia_save_profile(self, widget, data=None):
|
def dia_save_profile(self, widget, data=None):
|
||||||
print "todo: implement dia_save_profile"
|
self.warning_box("Unimplemented: Save Profile (try saving a HUD layout, that should do it)")
|
||||||
#end def dia_save_profile
|
|
||||||
|
|
||||||
def diaSetupWizard(self, path):
|
def diaSetupWizard(self, path):
|
||||||
print "todo: implement setup wizard"
|
|
||||||
print "setup wizard not implemented - please create the default configuration file:", path
|
|
||||||
diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK))
|
diaSetupWizard = gtk.Dialog(title="Fatal Error - Config File Missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK))
|
||||||
|
|
||||||
label = gtk.Label("Please copy the config file from the docs folder to:")
|
label = gtk.Label("Please copy the config file from the docs folder to:")
|
||||||
|
@ -312,7 +294,6 @@ class fpdb:
|
||||||
|
|
||||||
response = diaSetupWizard.run()
|
response = diaSetupWizard.run()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
#end def diaSetupWizard
|
|
||||||
|
|
||||||
def get_menu(self, window):
|
def get_menu(self, window):
|
||||||
"""returns the menu for this program"""
|
"""returns the menu for this program"""
|
||||||
|
@ -327,6 +308,7 @@ class fpdb:
|
||||||
<menuitem action="Quit"/>
|
<menuitem action="Quit"/>
|
||||||
</menu>
|
</menu>
|
||||||
<menu action="import">
|
<menu action="import">
|
||||||
|
<menuitem action="sethharchive"/>
|
||||||
<menuitem action="bulkimp"/>
|
<menuitem action="bulkimp"/>
|
||||||
<menuitem action="autoimp"/>
|
<menuitem action="autoimp"/>
|
||||||
<menuitem action="autorate"/>
|
<menuitem action="autorate"/>
|
||||||
|
@ -369,6 +351,7 @@ class fpdb:
|
||||||
('EditProf', None, '_Edit Profile (todo)', '<control>E', 'Edit your profile', self.dia_edit_profile),
|
('EditProf', None, '_Edit Profile (todo)', '<control>E', 'Edit your profile', self.dia_edit_profile),
|
||||||
('SaveProf', None, '_Save Profile (todo)', '<control>S', 'Save your profile', self.dia_save_profile),
|
('SaveProf', None, '_Save Profile (todo)', '<control>S', 'Save your profile', self.dia_save_profile),
|
||||||
('import', None, '_Import'),
|
('import', None, '_Import'),
|
||||||
|
('sethharchive', None, '_Set HandHistory Archive Directory', None, 'Set HandHistory Archive Directory', self.select_hhArchiveBase),
|
||||||
('bulkimp', None, '_Bulk Import', '<control>B', 'Bulk Import', self.tab_bulk_import),
|
('bulkimp', None, '_Bulk Import', '<control>B', 'Bulk Import', self.tab_bulk_import),
|
||||||
('autorate', None, 'Auto _Rating (todo)', '<control>R', 'Auto Rating (todo)', self.not_implemented),
|
('autorate', None, 'Auto _Rating (todo)', '<control>R', 'Auto Rating (todo)', self.not_implemented),
|
||||||
('viewers', None, '_Viewers'),
|
('viewers', None, '_Viewers'),
|
||||||
|
@ -401,7 +384,6 @@ class fpdb:
|
||||||
menubar = uimanager.get_widget('/MenuBar')
|
menubar = uimanager.get_widget('/MenuBar')
|
||||||
window.add_accel_group(accel_group)
|
window.add_accel_group(accel_group)
|
||||||
return menubar
|
return menubar
|
||||||
#end def get_menu
|
|
||||||
|
|
||||||
def load_profile(self):
|
def load_profile(self):
|
||||||
"""Loads profile from the provided path name."""
|
"""Loads profile from the provided path name."""
|
||||||
|
@ -452,11 +434,11 @@ class fpdb:
|
||||||
|
|
||||||
# Database connected to successfully, load queries to pass on to other classes
|
# Database connected to successfully, load queries to pass on to other classes
|
||||||
self.db.connection.rollback()
|
self.db.connection.rollback()
|
||||||
#end def load_profile
|
|
||||||
|
self.validate_config()
|
||||||
|
|
||||||
def not_implemented(self, widget, data=None):
|
def not_implemented(self, widget, data=None):
|
||||||
print "todo: called unimplemented menu entry (users: pls ignore this)"#remove this once more entries are implemented
|
self.warning_box("Unimplemented menu entry")
|
||||||
#end def not_implemented
|
|
||||||
|
|
||||||
def obtain_global_lock(self):
|
def obtain_global_lock(self):
|
||||||
ret = self.lock.acquire(False) # will return false if lock is already held
|
ret = self.lock.acquire(False) # will return false if lock is already held
|
||||||
|
@ -468,31 +450,25 @@ class fpdb:
|
||||||
# need to release it later:
|
# need to release it later:
|
||||||
# self.lock.release()
|
# self.lock.release()
|
||||||
|
|
||||||
#end def obtain_global_lock
|
|
||||||
|
|
||||||
def quit(self, widget, data=None):
|
def quit(self, widget, data=None):
|
||||||
print "Quitting normally"
|
print "Quitting normally"
|
||||||
#check if current settings differ from profile, if so offer to save or abort
|
#check if current settings differ from profile, if so offer to save or abort
|
||||||
self.db.disconnect()
|
self.db.disconnect()
|
||||||
gtk.main_quit()
|
gtk.main_quit()
|
||||||
#end def quit_cliecked
|
|
||||||
|
|
||||||
def release_global_lock(self):
|
def release_global_lock(self):
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
print "Global lock released.\n"
|
print "Global lock released.\n"
|
||||||
#end def release_global_lock
|
|
||||||
|
|
||||||
def tab_abbreviations(self, widget, data=None):
|
def tab_abbreviations(self, widget, data=None):
|
||||||
print "todo: implement tab_abbreviations"
|
print "todo: implement tab_abbreviations"
|
||||||
#end def tab_abbreviations
|
|
||||||
|
|
||||||
def tab_auto_import(self, widget, data=None):
|
def tab_auto_import(self, widget, data=None):
|
||||||
"""opens the auto import tab"""
|
"""opens the auto import tab"""
|
||||||
new_aimp_thread=GuiAutoImport.GuiAutoImport(self.settings, self.config, self.sql)
|
new_aimp_thread = GuiAutoImport.GuiAutoImport(self.settings, self.config, self.sql)
|
||||||
self.threads.append(new_aimp_thread)
|
self.threads.append(new_aimp_thread)
|
||||||
aimp_tab=new_aimp_thread.get_vbox()
|
aimp_tab=new_aimp_thread.get_vbox()
|
||||||
self.add_and_display_tab(aimp_tab, "Auto Import")
|
self.add_and_display_tab(aimp_tab, "Auto Import")
|
||||||
#end def tab_auto_import
|
|
||||||
|
|
||||||
def tab_bulk_import(self, widget, data=None):
|
def tab_bulk_import(self, widget, data=None):
|
||||||
"""opens a tab for bulk importing"""
|
"""opens a tab for bulk importing"""
|
||||||
|
@ -501,10 +477,9 @@ class fpdb:
|
||||||
self.threads.append(new_import_thread)
|
self.threads.append(new_import_thread)
|
||||||
bulk_tab=new_import_thread.get_vbox()
|
bulk_tab=new_import_thread.get_vbox()
|
||||||
self.add_and_display_tab(bulk_tab, "Bulk Import")
|
self.add_and_display_tab(bulk_tab, "Bulk Import")
|
||||||
#end def tab_bulk_import
|
|
||||||
|
|
||||||
def tab_player_stats(self, widget, data=None):
|
def tab_player_stats(self, widget, data=None):
|
||||||
new_ps_thread=GuiPlayerStats.GuiPlayerStats(self.config, self.sql, self.window)
|
new_ps_thread = GuiPlayerStats.GuiPlayerStats(self.config, self.sql, self.window)
|
||||||
self.threads.append(new_ps_thread)
|
self.threads.append(new_ps_thread)
|
||||||
ps_tab=new_ps_thread.get_vbox()
|
ps_tab=new_ps_thread.get_vbox()
|
||||||
self.add_and_display_tab(ps_tab, "Player Stats")
|
self.add_and_display_tab(ps_tab, "Player Stats")
|
||||||
|
@ -517,31 +492,25 @@ class fpdb:
|
||||||
|
|
||||||
def tab_main_help(self, widget, data=None):
|
def tab_main_help(self, widget, data=None):
|
||||||
"""Displays a tab with the main fpdb help screen"""
|
"""Displays a tab with the main fpdb help screen"""
|
||||||
#print "start of tab_main_help"
|
|
||||||
mh_tab=gtk.Label("""Welcome to Fpdb!
|
mh_tab=gtk.Label("""Welcome to Fpdb!
|
||||||
For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder.
|
For documentation please visit our website at http://fpdb.sourceforge.net/ or check the docs directory in the fpdb folder.
|
||||||
Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml
|
Please note that default.conf is no longer needed nor used, all configuration now happens in HUD_config.xml
|
||||||
This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||||
self.add_and_display_tab(mh_tab, "Help")
|
self.add_and_display_tab(mh_tab, "Help")
|
||||||
#end def tab_main_help
|
|
||||||
|
|
||||||
def tab_table_viewer(self, widget, data=None):
|
def tab_table_viewer(self, widget, data=None):
|
||||||
"""opens a table viewer tab"""
|
"""opens a table viewer tab"""
|
||||||
#print "start of tab_table_viewer"
|
|
||||||
new_tv_thread = GuiTableViewer.GuiTableViewer(self.db, self.settings, self.config)
|
new_tv_thread = GuiTableViewer.GuiTableViewer(self.db, self.settings, self.config)
|
||||||
self.threads.append(new_tv_thread)
|
self.threads.append(new_tv_thread)
|
||||||
tv_tab=new_tv_thread.get_vbox()
|
tv_tab = new_tv_thread.get_vbox()
|
||||||
self.add_and_display_tab(tv_tab, "Table Viewer")
|
self.add_and_display_tab(tv_tab, "Table Viewer")
|
||||||
#end def tab_table_viewer
|
|
||||||
|
|
||||||
def tabGraphViewer(self, widget, data=None):
|
def tabGraphViewer(self, widget, data=None):
|
||||||
"""opens a graph viewer tab"""
|
"""opens a graph viewer tab"""
|
||||||
#print "start of tabGraphViewer"
|
|
||||||
new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.sql, self.config)
|
new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.sql, self.config)
|
||||||
self.threads.append(new_gv_thread)
|
self.threads.append(new_gv_thread)
|
||||||
gv_tab=new_gv_thread.get_vbox()
|
gv_tab = new_gv_thread.get_vbox()
|
||||||
self.add_and_display_tab(gv_tab, "Graphs")
|
self.add_and_display_tab(gv_tab, "Graphs")
|
||||||
#end def tabGraphViewer
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.threads = []
|
self.threads = []
|
||||||
|
@ -586,12 +555,50 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||||
self.window.show()
|
self.window.show()
|
||||||
self.load_profile()
|
self.load_profile()
|
||||||
sys.stderr.write("fpdb starting ...")
|
sys.stderr.write("fpdb starting ...")
|
||||||
#end def __init__
|
|
||||||
|
def warning_box(self, str, diatitle="FPDB WARNING"):
|
||||||
|
diaWarning = gtk.Dialog(title=diatitle, parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
|
||||||
|
|
||||||
|
label = gtk.Label(str)
|
||||||
|
diaWarning.vbox.add(label)
|
||||||
|
label.show()
|
||||||
|
|
||||||
|
response = diaWarning.run()
|
||||||
|
diaWarning.destroy()
|
||||||
|
return response
|
||||||
|
|
||||||
|
def validate_config(self):
|
||||||
|
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
|
||||||
|
hhbase = os.path.expanduser(hhbase)
|
||||||
|
#hhdir = os.path.join(hhbase,site)
|
||||||
|
hhdir = hhbase
|
||||||
|
if not os.path.isdir(hhdir):
|
||||||
|
diapath = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Setup hh dir")
|
||||||
|
diastring = "WARNING: Unable to find output hh directory %s\n\n Press YES to create this directory, or NO to select a new one." % hhdir
|
||||||
|
diapath.format_secondary_text(diastring)
|
||||||
|
response = diapath.run()
|
||||||
|
diapath.destroy()
|
||||||
|
if response == gtk.RESPONSE_YES:
|
||||||
|
try:
|
||||||
|
os.makedirs(hhdir)
|
||||||
|
except:
|
||||||
|
self.warning_box("WARNING: Unable to create hand output directory. Importing is not likely to work until this is fixed.")
|
||||||
|
elif response == gtk.RESPONSE_NO:
|
||||||
|
self.select_hhArchiveBase()
|
||||||
|
|
||||||
|
def select_hhArchiveBase(self, widget=None):
|
||||||
|
fc = gtk.FileChooserDialog(title="Select HH Output Directory", parent=None, action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons=(gtk.STOCK_OPEN,gtk.RESPONSE_OK), backend=None)
|
||||||
|
fc.run()
|
||||||
|
# TODO: We need to put in a Cancel button, and handle if the user presses that or the "Close" box without selecting anything as a cancel, and return to the prior setting
|
||||||
|
#self.warning_box("You selected %s" % fc.get_filename())
|
||||||
|
self.config.set_hhArchiveBase(fc.get_filename())
|
||||||
|
self.config.save()
|
||||||
|
self.load_profile() # we can't do this at the end of this func because load_profile calls this func
|
||||||
|
fc.destroy() # TODO: loop this to make sure we get valid data back from it, because the open directory thing in GTK lets you select files and not select things and other stupid bullshit
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
gtk.main()
|
gtk.main()
|
||||||
return 0
|
return 0
|
||||||
#end def main
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
me = fpdb()
|
me = fpdb()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#Copyright 2008 Steffen Jobbagy-Felso
|
#Copyright 2008 Steffen Jobbagy-Felso
|
||||||
#This program is free software: you can redistribute it and/or modify
|
#This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -21,8 +22,18 @@ import sys
|
||||||
import logging
|
import logging
|
||||||
from time import time, strftime
|
from time import time, strftime
|
||||||
|
|
||||||
|
use_pool = False
|
||||||
|
try:
|
||||||
|
import sqlalchemy.pool as pool
|
||||||
|
use_pool = True
|
||||||
|
except:
|
||||||
|
logging.info("Not using sqlalchemy connection pool.")
|
||||||
|
|
||||||
|
|
||||||
import fpdb_simple
|
import fpdb_simple
|
||||||
import FpdbSQLQueries
|
import FpdbSQLQueries
|
||||||
|
from Exceptions import *
|
||||||
|
|
||||||
|
|
||||||
class fpdb_db:
|
class fpdb_db:
|
||||||
MYSQL_INNODB = 2
|
MYSQL_INNODB = 2
|
||||||
|
@ -63,13 +74,17 @@ class fpdb_db:
|
||||||
self.database=database
|
self.database=database
|
||||||
if backend==fpdb_db.MYSQL_INNODB:
|
if backend==fpdb_db.MYSQL_INNODB:
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
|
if use_pool:
|
||||||
|
MySQLdb = pool.manage(MySQLdb, pool_size=5)
|
||||||
try:
|
try:
|
||||||
self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True)
|
self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True)
|
||||||
except:
|
except:
|
||||||
raise fpdb_simple.FpdbError("MySQL connection failed")
|
raise FpdbError("MySQL connection failed")
|
||||||
elif backend==fpdb_db.PGSQL:
|
elif backend==fpdb_db.PGSQL:
|
||||||
import psycopg2
|
import psycopg2
|
||||||
import psycopg2.extensions
|
import psycopg2.extensions
|
||||||
|
if use_pool:
|
||||||
|
psycopg2 = pool.manage(psycopg2, pool_size=5)
|
||||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||||
# If DB connection is made over TCP, then the variables
|
# If DB connection is made over TCP, then the variables
|
||||||
# host, user and password are required
|
# host, user and password are required
|
||||||
|
@ -87,7 +102,7 @@ class fpdb_db:
|
||||||
pass
|
pass
|
||||||
#msg = "PostgreSQL direct connection to database (%s) failed, trying with user ..." % (database,)
|
#msg = "PostgreSQL direct connection to database (%s) failed, trying with user ..." % (database,)
|
||||||
#print msg
|
#print msg
|
||||||
#raise fpdb_simple.FpdbError(msg)
|
#raise FpdbError(msg)
|
||||||
if not connected:
|
if not connected:
|
||||||
try:
|
try:
|
||||||
self.db = psycopg2.connect(host = host,
|
self.db = psycopg2.connect(host = host,
|
||||||
|
@ -97,16 +112,19 @@ class fpdb_db:
|
||||||
except:
|
except:
|
||||||
msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user)
|
msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user)
|
||||||
print msg
|
print msg
|
||||||
raise fpdb_simple.FpdbError(msg)
|
raise FpdbError(msg)
|
||||||
elif backend==fpdb_db.SQLITE:
|
elif backend==fpdb_db.SQLITE:
|
||||||
logging.info("Connecting to SQLite:%(database)s" % {'database':database})
|
logging.info("Connecting to SQLite:%(database)s" % {'database':database})
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
if use_pool:
|
||||||
|
sqlite3 = pool.manage(sqlite3, pool_size=1)
|
||||||
|
else:
|
||||||
|
logging.warning("SQLite won't work well without 'sqlalchemy' installed.")
|
||||||
self.db = sqlite3.connect(database,detect_types=sqlite3.PARSE_DECLTYPES)
|
self.db = sqlite3.connect(database,detect_types=sqlite3.PARSE_DECLTYPES)
|
||||||
sqlite3.register_converter("bool", lambda x: bool(int(x)))
|
sqlite3.register_converter("bool", lambda x: bool(int(x)))
|
||||||
sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
|
sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
|
raise FpdbError("unrecognised database backend:"+backend)
|
||||||
self.cursor=self.db.cursor()
|
self.cursor=self.db.cursor()
|
||||||
# Set up query dictionary as early in the connection process as we can.
|
# Set up query dictionary as early in the connection process as we can.
|
||||||
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
|
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
|
||||||
|
@ -119,7 +137,7 @@ class fpdb_db:
|
||||||
print "outdated or too new database version - please recreate tables"
|
print "outdated or too new database version - please recreate tables"
|
||||||
self.wrongDbVersion=True
|
self.wrongDbVersion=True
|
||||||
except:# _mysql_exceptions.ProgrammingError:
|
except:# _mysql_exceptions.ProgrammingError:
|
||||||
print "failed to read settings table - please recreate tables"
|
if database != ":memory:": print "failed to read settings table - please recreate tables"
|
||||||
self.wrongDbVersion=True
|
self.wrongDbVersion=True
|
||||||
#end def connect
|
#end def connect
|
||||||
|
|
||||||
|
@ -148,7 +166,7 @@ class fpdb_db:
|
||||||
elif self.backend==4:
|
elif self.backend==4:
|
||||||
return "SQLite"
|
return "SQLite"
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("invalid backend")
|
raise FpdbError("invalid backend")
|
||||||
#end def get_backend_name
|
#end def get_backend_name
|
||||||
|
|
||||||
def get_db_info(self):
|
def get_db_info(self):
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
import os # todo: remove this once import_dir is in fpdb_import
|
import os # todo: remove this once import_dir is in fpdb_import
|
||||||
import sys
|
import sys
|
||||||
from time import time, strftime, sleep
|
from time import time, strftime, sleep
|
||||||
import logging
|
|
||||||
import traceback
|
import traceback
|
||||||
import math
|
import math
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -31,6 +30,9 @@ import Queue
|
||||||
from collections import deque # using Queue for now
|
from collections import deque # using Queue for now
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
import pygtk
|
||||||
|
import gtk
|
||||||
|
|
||||||
# fpdb/FreePokerTools modules
|
# fpdb/FreePokerTools modules
|
||||||
|
|
||||||
import fpdb_simple
|
import fpdb_simple
|
||||||
|
@ -38,22 +40,28 @@ import fpdb_db
|
||||||
import Database
|
import Database
|
||||||
import fpdb_parse_logic
|
import fpdb_parse_logic
|
||||||
import Configuration
|
import Configuration
|
||||||
|
import Exceptions
|
||||||
|
|
||||||
|
import logging, logging.config
|
||||||
|
logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf"))
|
||||||
|
log = logging.getLogger('importer')
|
||||||
|
|
||||||
# database interface modules
|
# database interface modules
|
||||||
try:
|
try:
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
mysqlLibFound=True
|
mysqlLibFound=True
|
||||||
|
log.debug("Import module: MySQLdb")
|
||||||
except:
|
except:
|
||||||
pass
|
log.debug("Import module: MySQLdb not found")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import psycopg2
|
import psycopg2
|
||||||
pgsqlLibFound=True
|
pgsqlLibFound=True
|
||||||
import psycopg2.extensions
|
import psycopg2.extensions
|
||||||
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||||
|
log.debug("Import module: psycopg2")
|
||||||
except:
|
except:
|
||||||
pass
|
log.debug("Import module: psycopg2 not found")
|
||||||
|
|
||||||
class Importer:
|
class Importer:
|
||||||
|
|
||||||
|
@ -145,6 +153,8 @@ class Importer:
|
||||||
#Add an individual file to filelist
|
#Add an individual file to filelist
|
||||||
def addImportFile(self, filename, site = "default", filter = "passthrough"):
|
def addImportFile(self, filename, site = "default", filter = "passthrough"):
|
||||||
#TODO: test it is a valid file -> put that in config!!
|
#TODO: test it is a valid file -> put that in config!!
|
||||||
|
if filename in self.filelist or not os.path.exists(filename):
|
||||||
|
return
|
||||||
self.filelist[filename] = [site] + [filter]
|
self.filelist[filename] = [site] + [filter]
|
||||||
if site not in self.siteIds:
|
if site not in self.siteIds:
|
||||||
# Get id from Sites table in DB
|
# Get id from Sites table in DB
|
||||||
|
@ -153,9 +163,9 @@ class Importer:
|
||||||
self.siteIds[site] = result[0][0]
|
self.siteIds[site] = result[0][0]
|
||||||
else:
|
else:
|
||||||
if len(result) == 0:
|
if len(result) == 0:
|
||||||
print "[ERROR] Database ID for %s not found" % site
|
log.error("Database ID for %s not found" % site)
|
||||||
else:
|
else:
|
||||||
print "[ERROR] More than 1 Database ID found for %s - Multiple currencies not implemented yet" % site
|
log.error("[ERROR] More than 1 Database ID found for %s - Multiple currencies not implemented yet" % site)
|
||||||
|
|
||||||
|
|
||||||
# Called from GuiBulkImport to add a file or directory.
|
# Called from GuiBulkImport to add a file or directory.
|
||||||
|
@ -168,7 +178,7 @@ class Importer:
|
||||||
if os.path.isdir(inputPath):
|
if os.path.isdir(inputPath):
|
||||||
for subdir in os.walk(inputPath):
|
for subdir in os.walk(inputPath):
|
||||||
for file in subdir[2]:
|
for file in subdir[2]:
|
||||||
self.addImportFile(os.path.join(inputPath, subdir[0], file), site=site, filter=filter)
|
self.addImportFile(os.path.join(subdir[0], file), site=site, filter=filter)
|
||||||
else:
|
else:
|
||||||
self.addImportFile(inputPath, site=site, filter=filter)
|
self.addImportFile(inputPath, site=site, filter=filter)
|
||||||
#Add a directory of files to filelist
|
#Add a directory of files to filelist
|
||||||
|
@ -189,7 +199,7 @@ class Importer:
|
||||||
#print " adding file ", file
|
#print " adding file ", file
|
||||||
self.addImportFile(os.path.join(dir, file), site, filter)
|
self.addImportFile(os.path.join(dir, file), site, filter)
|
||||||
else:
|
else:
|
||||||
print "Warning: Attempted to add non-directory: '" + str(dir) + "' as an import directory"
|
log.warning("Attempted to add non-directory: '" + str(dir) + "' as an import directory")
|
||||||
|
|
||||||
def runImport(self):
|
def runImport(self):
|
||||||
""""Run full import on self.filelist. This is called from GuiBulkImport.py"""
|
""""Run full import on self.filelist. This is called from GuiBulkImport.py"""
|
||||||
|
@ -199,7 +209,7 @@ class Importer:
|
||||||
# Initial setup
|
# Initial setup
|
||||||
start = datetime.datetime.now()
|
start = datetime.datetime.now()
|
||||||
starttime = time()
|
starttime = time()
|
||||||
print "Started at", start, "--", len(self.filelist), "files to import.", self.settings['dropIndexes']
|
log.info("Started at %s -- %d files to import. indexes: %s" % (start, len(self.filelist), self.settings['dropIndexes']))
|
||||||
if self.settings['dropIndexes'] == 'auto':
|
if self.settings['dropIndexes'] == 'auto':
|
||||||
self.settings['dropIndexes'] = self.calculate_auto2(self.database, 12.0, 500.0)
|
self.settings['dropIndexes'] = self.calculate_auto2(self.database, 12.0, 500.0)
|
||||||
if 'dropHudCache' in self.settings and self.settings['dropHudCache'] == 'auto':
|
if 'dropHudCache' in self.settings and self.settings['dropHudCache'] == 'auto':
|
||||||
|
@ -208,7 +218,7 @@ class Importer:
|
||||||
if self.settings['dropIndexes'] == 'drop':
|
if self.settings['dropIndexes'] == 'drop':
|
||||||
self.database.prepareBulkImport()
|
self.database.prepareBulkImport()
|
||||||
else:
|
else:
|
||||||
print "No need to drop indexes."
|
log.debug("No need to drop indexes.")
|
||||||
#print "dropInd =", self.settings['dropIndexes'], " dropHudCache =", self.settings['dropHudCache']
|
#print "dropInd =", self.settings['dropIndexes'], " dropHudCache =", self.settings['dropHudCache']
|
||||||
|
|
||||||
if self.settings['threads'] <= 0:
|
if self.settings['threads'] <= 0:
|
||||||
|
@ -346,6 +356,7 @@ class Importer:
|
||||||
#rulog.writelines("path exists ")
|
#rulog.writelines("path exists ")
|
||||||
if file in self.updatedsize: # we should be able to assume that if we're in size, we're in time as well
|
if file in self.updatedsize: # we should be able to assume that if we're in size, we're in time as well
|
||||||
if stat_info.st_size > self.updatedsize[file] or stat_info.st_mtime > self.updatedtime[file]:
|
if stat_info.st_size > self.updatedsize[file] or stat_info.st_mtime > self.updatedtime[file]:
|
||||||
|
# print "file",counter," updated", os.path.basename(file), stat_info.st_size, self.updatedsize[file], stat_info.st_mtime, self.updatedtime[file]
|
||||||
self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None)
|
self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None)
|
||||||
self.updatedsize[file] = stat_info.st_size
|
self.updatedsize[file] = stat_info.st_size
|
||||||
self.updatedtime[file] = time()
|
self.updatedtime[file] = time()
|
||||||
|
@ -358,6 +369,7 @@ class Importer:
|
||||||
self.updatedtime[file] = time()
|
self.updatedtime[file] = time()
|
||||||
else:
|
else:
|
||||||
self.removeFromFileList[file] = True
|
self.removeFromFileList[file] = True
|
||||||
|
|
||||||
self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList)
|
self.addToDirList = filter(lambda x: self.addImportDirectory(x, True, self.addToDirList[x][0], self.addToDirList[x][1]), self.addToDirList)
|
||||||
|
|
||||||
for file in self.removeFromFileList:
|
for file in self.removeFromFileList:
|
||||||
|
@ -373,6 +385,7 @@ class Importer:
|
||||||
# This is now an internal function that should not be called directly.
|
# This is now an internal function that should not be called directly.
|
||||||
def import_file_dict(self, db, file, site, filter, q=None):
|
def import_file_dict(self, db, file, site, filter, q=None):
|
||||||
#print "import_file_dict"
|
#print "import_file_dict"
|
||||||
|
|
||||||
if os.path.isdir(file):
|
if os.path.isdir(file):
|
||||||
self.addToDirList[file] = [site] + [filter]
|
self.addToDirList[file] = [site] + [filter]
|
||||||
return
|
return
|
||||||
|
@ -384,9 +397,9 @@ class Importer:
|
||||||
|
|
||||||
# Load filter, process file, pass returned filename to import_fpdb_file
|
# Load filter, process file, pass returned filename to import_fpdb_file
|
||||||
if self.settings['threads'] > 0 and self.writeq != None:
|
if self.settings['threads'] > 0 and self.writeq != None:
|
||||||
print "\nConverting " + file + " (" + str(q.qsize()) + ")"
|
log.info("Converting " + file + " (" + str(q.qsize()) + ")")
|
||||||
else:
|
else:
|
||||||
print "\nConverting " + file
|
log.info("Converting " + file)
|
||||||
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
|
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
|
||||||
hhbase = os.path.expanduser(hhbase)
|
hhbase = os.path.expanduser(hhbase)
|
||||||
hhdir = os.path.join(hhbase,site)
|
hhdir = os.path.join(hhbase,site)
|
||||||
|
@ -396,44 +409,28 @@ class Importer:
|
||||||
out_path = os.path.join(hhdir, "x"+strftime("%d-%m-%y")+os.path.basename(file))
|
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)
|
mod = __import__(filter)
|
||||||
obj = getattr(mod, filter_name, None)
|
obj = getattr(mod, filter_name, None)
|
||||||
if callable(obj):
|
if callable(obj):
|
||||||
hhc = obj(in_path = file, out_path = out_path, index = 0) # Index into file 0 until changeover
|
hhc = obj(in_path = file, out_path = out_path, index = 0) # Index into file 0 until changeover
|
||||||
if hhc.getParsedObjectType() == "HH":
|
if(hhc.getStatus() and self.NEWIMPORT == False):
|
||||||
if(hhc.getStatus() and self.NEWIMPORT == False):
|
(stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q)
|
||||||
(stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q)
|
elif (hhc.getStatus() and self.NEWIMPORT == True):
|
||||||
elif (hhc.getStatus() and self.NEWIMPORT == True):
|
#This code doesn't do anything yet
|
||||||
#This code doesn't do anything yet
|
handlist = hhc.getProcessedHands()
|
||||||
handlist = hhc.getProcessedHands()
|
self.pos_in_file[file] = hhc.getLastCharacterRead()
|
||||||
self.pos_in_file[file] = hhc.getLastCharacterRead()
|
|
||||||
|
|
||||||
for hand in handlist:
|
for hand in handlist:
|
||||||
#hand.prepInsert()
|
#hand.prepInsert()
|
||||||
hand.insert(self.database)
|
hand.insert(self.database)
|
||||||
else:
|
|
||||||
# conversion didn't work
|
|
||||||
# TODO: appropriate response?
|
|
||||||
return (0, 0, 0, 1, 0, -1)
|
|
||||||
elif hhc.getParsedObjectType() == "Summary":
|
|
||||||
if(hhc.getStatus()):
|
|
||||||
tourney = hhc.getTourney()
|
|
||||||
#print tourney
|
|
||||||
#tourney.prepInsert()
|
|
||||||
(stored, duplicates, partial, errors, ttime) = tourney.insert(self.database)
|
|
||||||
return (stored, duplicates, partial, errors, ttime)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# conversion didn't work
|
|
||||||
# Could just be the parsing of a non summary file (classic HH file)
|
|
||||||
return (0, 0, 0, 0, 0)
|
|
||||||
else:
|
else:
|
||||||
print "Unknown objects parsed by HHC :'%s'" %(hhc.getObjectTypeRead())
|
# conversion didn't work
|
||||||
return (0, 0, 0, 1, 0, -1)
|
# TODO: appropriate response?
|
||||||
|
return (0, 0, 0, 1, 0)
|
||||||
else:
|
else:
|
||||||
print "Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter)
|
log.warning("Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter))
|
||||||
return (0, 0, 0, 1, 0, -1)
|
return (0, 0, 0, 1, 0)
|
||||||
|
|
||||||
#This will barf if conv.getStatus != True
|
#This will barf if conv.getStatus != True
|
||||||
return (stored, duplicates, partial, errors, ttime)
|
return (stored, duplicates, partial, errors, ttime)
|
||||||
|
@ -475,7 +472,7 @@ class Importer:
|
||||||
db.commit()
|
db.commit()
|
||||||
ttime = time() - starttime
|
ttime = time() - starttime
|
||||||
if q == None:
|
if q == None:
|
||||||
print "\rTotal stored:", stored, " duplicates:", duplicates, "errors:", errors, " time:", ttime
|
log.info("Total stored: %(stored)d\tduplicates:%(duplicates)d\terrors:%(errors)d\ttime:%(ttime)s" % locals())
|
||||||
|
|
||||||
if not stored:
|
if not stored:
|
||||||
if duplicates:
|
if duplicates:
|
||||||
|
@ -497,6 +494,8 @@ class Importer:
|
||||||
"""Import an fpdb hand history held in the list lines, could be one hand or many"""
|
"""Import an fpdb hand history held in the list lines, could be one hand or many"""
|
||||||
|
|
||||||
#db.lock_for_insert() # should be ok when using one thread, but doesn't help??
|
#db.lock_for_insert() # should be ok when using one thread, but doesn't help??
|
||||||
|
while gtk.events_pending():
|
||||||
|
gtk.main_iteration(False)
|
||||||
|
|
||||||
try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return.
|
try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return.
|
||||||
firstline = lines[0]
|
firstline = lines[0]
|
||||||
|
@ -550,9 +549,9 @@ class Importer:
|
||||||
if self.callHud:
|
if self.callHud:
|
||||||
#print "call to HUD here. handsId:",handsId
|
#print "call to HUD here. handsId:",handsId
|
||||||
#pipe the Hands.id out to the HUD
|
#pipe the Hands.id out to the HUD
|
||||||
print "sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
|
#print "sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
|
||||||
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
||||||
except fpdb_simple.DuplicateError:
|
except Exceptions.DuplicateError:
|
||||||
duplicates += 1
|
duplicates += 1
|
||||||
db.rollback()
|
db.rollback()
|
||||||
except (ValueError), fe:
|
except (ValueError), fe:
|
||||||
|
|
|
@ -22,6 +22,7 @@ import sys
|
||||||
import fpdb_simple
|
import fpdb_simple
|
||||||
import Database
|
import Database
|
||||||
from time import time, strftime
|
from time import time, strftime
|
||||||
|
from Exceptions import *
|
||||||
|
|
||||||
|
|
||||||
#parses a holdem hand
|
#parses a holdem hand
|
||||||
|
@ -67,7 +68,8 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
|
||||||
tourneyStartTime= handStartTime #todo: read tourney start time
|
tourneyStartTime= handStartTime #todo: read tourney start time
|
||||||
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
|
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
|
||||||
|
|
||||||
tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(db.get_cursor(), siteID, buyin, fee, knockout, rebuyOrAddon)
|
## The tourney site id has to be searched because it may already be in db with a TourneyTypeId which is different from the one automatically calculated (Summary import first)
|
||||||
|
tourneyTypeId = fpdb_simple.recogniseTourneyTypeId(db, siteID, siteTourneyNo, buyin, fee, knockout, rebuyOrAddon)
|
||||||
else:
|
else:
|
||||||
siteTourneyNo = -1
|
siteTourneyNo = -1
|
||||||
buyin = -1
|
buyin = -1
|
||||||
|
@ -126,7 +128,7 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non
|
||||||
elif lineTypes[i]=="table":
|
elif lineTypes[i]=="table":
|
||||||
tableResult=fpdb_simple.parseTableLine(base, line)
|
tableResult=fpdb_simple.parseTableLine(base, line)
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("unrecognised lineType:"+lineTypes[i])
|
raise FpdbError("unrecognised lineType:"+lineTypes[i])
|
||||||
|
|
||||||
maxSeats = tableResult['maxSeats']
|
maxSeats = tableResult['maxSeats']
|
||||||
tableName = tableResult['tableName']
|
tableName = tableResult['tableName']
|
||||||
|
|
|
@ -25,6 +25,7 @@ import datetime
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from Exceptions import *
|
||||||
import locale
|
import locale
|
||||||
|
|
||||||
import Card
|
import Card
|
||||||
|
@ -40,18 +41,6 @@ SQLITE = 4
|
||||||
|
|
||||||
LOCALE_ENCODING = locale.getdefaultlocale()[1]
|
LOCALE_ENCODING = locale.getdefaultlocale()[1]
|
||||||
|
|
||||||
class DuplicateError(Exception):
|
|
||||||
def __init__(self, value):
|
|
||||||
self.value = value
|
|
||||||
def __str__(self):
|
|
||||||
return repr(self.value)
|
|
||||||
|
|
||||||
class FpdbError(Exception):
|
|
||||||
def __init__(self, value):
|
|
||||||
self.value = value
|
|
||||||
def __str__(self):
|
|
||||||
return repr(self.value)
|
|
||||||
|
|
||||||
#returns an array of the total money paid. intending to add rebuys/addons here
|
#returns an array of the total money paid. intending to add rebuys/addons here
|
||||||
def calcPayin(count, buyin, fee):
|
def calcPayin(count, buyin, fee):
|
||||||
return [buyin + fee for i in xrange(count)]
|
return [buyin + fee for i in xrange(count)]
|
||||||
|
@ -227,7 +216,7 @@ def fillCardArrays(player_count, base, category, card_values, card_suits):
|
||||||
elif base=="stud":
|
elif base=="stud":
|
||||||
cardCount = 7
|
cardCount = 7
|
||||||
else:
|
else:
|
||||||
raise fpdb_simple.FpdbError("invalid category:", category)
|
raise FpdbError("invalid category:", category)
|
||||||
|
|
||||||
for i in xrange(player_count):
|
for i in xrange(player_count):
|
||||||
while (len(card_values[i]) < cardCount):
|
while (len(card_values[i]) < cardCount):
|
||||||
|
@ -954,17 +943,28 @@ def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, c
|
||||||
return result[0]
|
return result[0]
|
||||||
#end def recogniseGametypeID
|
#end def recogniseGametypeID
|
||||||
|
|
||||||
def recogniseTourneyTypeId(cursor, siteId, buyin, fee, knockout, rebuyOrAddon):
|
def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebuyOrAddon):
|
||||||
cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
cursor = db.get_cursor()
|
||||||
|
# First we try to find the tourney itself (by its tourneySiteId) in case it has already been inserted before (by a summary file for instance)
|
||||||
|
# The reason is that some tourneys may not be identified correctly in the HH toplines (especially Buy-In and Fee which are used to search/create the TourneyTypeId)
|
||||||
|
#TODO: When the summary file will be dumped to BD, if the tourney is already in, Buy-In/Fee may need an update (e.g. creation of a new type and link to the Tourney)
|
||||||
|
cursor.execute (db.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', db.sql.query['placeholder']), (tourneySiteId, siteId))
|
||||||
result=cursor.fetchone()
|
result=cursor.fetchone()
|
||||||
#print "tried SELECTing gametypes.id, result:",result
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
len(result)
|
len(result)
|
||||||
except TypeError:#this means we need to create a new entry
|
except:
|
||||||
cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
cursor.execute ("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
||||||
cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
|
||||||
result=cursor.fetchone()
|
result=cursor.fetchone()
|
||||||
|
#print "tried SELECTing gametypes.id, result:",result
|
||||||
|
|
||||||
|
try:
|
||||||
|
len(result)
|
||||||
|
except TypeError:#this means we need to create a new entry
|
||||||
|
cursor.execute("""INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) VALUES (%s, %s, %s, %s, %s)""", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
||||||
|
cursor.execute("SELECT id FROM TourneyTypes WHERE siteId=%s AND buyin=%s AND fee=%s AND knockout=%s AND rebuyOrAddon=%s", (siteId, buyin, fee, knockout, rebuyOrAddon))
|
||||||
|
result=cursor.fetchone()
|
||||||
|
|
||||||
return result[0]
|
return result[0]
|
||||||
#end def recogniseTourneyTypeId
|
#end def recogniseTourneyTypeId
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[loggers]
|
[loggers]
|
||||||
keys=root,parser
|
keys=root,parser,importer,config,db
|
||||||
|
|
||||||
[handlers]
|
[handlers]
|
||||||
keys=consoleHandler,fileHandler
|
keys=consoleHandler,fileHandler
|
||||||
|
@ -13,20 +13,37 @@ handlers=consoleHandler,fileHandler
|
||||||
|
|
||||||
[logger_parser]
|
[logger_parser]
|
||||||
level=INFO
|
level=INFO
|
||||||
# set to NOTSET or DEBUG to see everything the parser does
|
|
||||||
handlers=consoleHandler,fileHandler
|
handlers=consoleHandler,fileHandler
|
||||||
qualname=parser
|
qualname=parser
|
||||||
propagate=0
|
propagate=0
|
||||||
|
|
||||||
|
[logger_importer]
|
||||||
|
level=DEBUG
|
||||||
|
handlers=consoleHandler,fileHandler
|
||||||
|
qualname=importer
|
||||||
|
propagate=0
|
||||||
|
|
||||||
|
[logger_config]
|
||||||
|
level=DEBUG
|
||||||
|
handlers=consoleHandler,fileHandler
|
||||||
|
qualname=config
|
||||||
|
propagate=0
|
||||||
|
|
||||||
|
[logger_db]
|
||||||
|
level=DEBUG
|
||||||
|
handlers=consoleHandler,fileHandler
|
||||||
|
qualname=db
|
||||||
|
propagate=0
|
||||||
|
|
||||||
[handler_consoleHandler]
|
[handler_consoleHandler]
|
||||||
class=StreamHandler
|
class=StreamHandler
|
||||||
level=INFO
|
level=ERROR
|
||||||
formatter=stderrFormatter
|
formatter=stderrFormatter
|
||||||
args=(sys.stderr,)
|
args=(sys.stderr,)
|
||||||
|
|
||||||
[handler_fileHandler]
|
[handler_fileHandler]
|
||||||
class=FileHandler
|
class=FileHandler
|
||||||
level=INFO
|
level=DEBUG
|
||||||
formatter=fileFormatter
|
formatter=fileFormatter
|
||||||
args=('logging.out', 'a')
|
args=('logging.out', 'a')
|
||||||
|
|
||||||
|
|
54
pyfpdb/py2exe_setup.py
Normal file
54
pyfpdb/py2exe_setup.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""setup.py
|
||||||
|
|
||||||
|
Py2exe script for fpdb.
|
||||||
|
"""
|
||||||
|
# Copyright 2009, 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
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
|
||||||
|
#TODO: change GuiAutoImport so that it knows to start HUD_main.exe, when appropriate
|
||||||
|
# include the lib needed to handle png files in mucked
|
||||||
|
# get rid of all the uneeded libraries (e.g., pyQT)
|
||||||
|
# think about an installer
|
||||||
|
|
||||||
|
from distutils.core import setup
|
||||||
|
import py2exe
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name = 'fpdb',
|
||||||
|
description = 'Free Poker DataBase',
|
||||||
|
version = '0.12',
|
||||||
|
|
||||||
|
console = [ {'script': 'fpdb.py', },
|
||||||
|
{'script': 'HUD_main.py', }
|
||||||
|
],
|
||||||
|
|
||||||
|
options = {'py2exe': {
|
||||||
|
'packages' :'encodings',
|
||||||
|
'includes' : 'cairo, pango, pangocairo, atk, gobject, PokerStarsToFpdb',
|
||||||
|
'excludes' : '_tkagg, _agg2, cocoaagg, fltkagg',
|
||||||
|
'dll_excludes': 'libglade-2.0-0.dll',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data_files = ['HUD_config.xml',
|
||||||
|
'Cards01.png'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user