Merge branch 'master' of git://git.assembla.com/fpdboz.git
This commit is contained in:
commit
9be7f308a6
116
pyfpdb/AlchemyFacilities.py
Normal file
116
pyfpdb/AlchemyFacilities.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import types
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
import Card
|
||||
|
||||
class CardColumn(types.TypeDecorator):
|
||||
"""Stores cards as smallints
|
||||
|
||||
Automatically converts values like '9h' to smallint
|
||||
|
||||
>>> CardColumn().process_bind_param( 'Td', '' )
|
||||
22
|
||||
>>> CardColumn().process_bind_param( u'Td', '' )
|
||||
22
|
||||
>>> CardColumn().process_bind_param( 22, '' )
|
||||
22
|
||||
>>> CardColumn().process_result_value( 22, '' )
|
||||
'Td'
|
||||
"""
|
||||
|
||||
impl = types.SmallInteger
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is None or isinstance(value, int):
|
||||
return value
|
||||
elif isinstance(value, basestring) and len(value) == 2:
|
||||
return Card.encodeCard(str(value))
|
||||
else:
|
||||
raise Exception, "Incorrect card value: " + repr(value)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
return Card.valueSuitFromCard( value )
|
||||
|
||||
|
||||
class MoneyColumn(types.TypeDecorator):
|
||||
"""Stores money: bets, pots, etc
|
||||
|
||||
Understands:
|
||||
Decimal as real amount
|
||||
int as amount mupliplied by 100
|
||||
string as decimal
|
||||
Returns Decimal
|
||||
>>> MoneyColumn().process_bind_param( 230, '' )
|
||||
230
|
||||
>>> MoneyColumn().process_bind_param( Decimal('2.30'), '' )
|
||||
230
|
||||
>>> MoneyColumn().process_bind_param( '2.30', '' )
|
||||
230
|
||||
>>> MoneyColumn().process_result_value( 230, '' )
|
||||
Decimal('2.3')
|
||||
"""
|
||||
|
||||
impl = types.Integer
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is None or isinstance(value, int):
|
||||
return value
|
||||
elif isinstance(value, basestring) or isinstance(value, Decimal):
|
||||
return int(Decimal(value)*100)
|
||||
else:
|
||||
raise Exception, "Incorrect amount:" + repr(value)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is None:
|
||||
return None
|
||||
return Decimal(value)/100
|
||||
|
||||
|
||||
class BigIntColumn(types.TypeDecorator, types.Integer):
|
||||
"""Representing db-independent big integer """
|
||||
# Integer inheritance required for auto_increment flag
|
||||
|
||||
impl = types.Integer
|
||||
|
||||
def load_dialect_impl(self, dialect):
|
||||
from sqlalchemy import databases
|
||||
if dialect.name == 'mysql':
|
||||
return databases.mysql.MSBigInteger()
|
||||
elif dialect.name == 'postgres':
|
||||
return databases.mysql.PGBigInteger()
|
||||
return types.Integer()
|
||||
|
||||
|
||||
class MappedBase(object):
|
||||
"""Provide dummy contrcutor"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(self, k, v)
|
||||
|
||||
def get_columns_names(self):
|
||||
return [i.name for i in self._sa_class_manager.mapper.c]
|
||||
|
||||
def get_or_create(klass, session, **kwargs):
|
||||
"""
|
||||
Looks up an object with the given kwargs, creating one if necessary.
|
||||
Returns a tuple of (object, created), where created is a boolean
|
||||
specifying whether an object was created.
|
||||
"""
|
||||
assert kwargs, \
|
||||
'get_or_create() must be passed at least one keyword argument'
|
||||
try:
|
||||
return session.query(klass).filter_by(**kwargs).one(), False
|
||||
except NoResultFound:
|
||||
try:
|
||||
obj = klass(**kwargs)
|
||||
session.add(obj)
|
||||
session.flush()
|
||||
return obj, True
|
||||
except IntegrityError:
|
||||
return session.query(klass).filter_by(**kwargs).one(), False
|
||||
|
464
pyfpdb/AlchemyMappings.py
Normal file
464
pyfpdb/AlchemyMappings.py
Normal file
|
@ -0,0 +1,464 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""@package AlchemyMappings
|
||||
This package contains all classes to be mapped and mappers themselves
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from decimal import Decimal
|
||||
from sqlalchemy.orm import mapper, relation, reconstructor
|
||||
from sqlalchemy.sql import select
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
from AlchemyTables import *
|
||||
from AlchemyFacilities import get_or_create, MappedBase
|
||||
from DerivedStats import DerivedStats
|
||||
from Exceptions import IncompleteHandError, FpdbError
|
||||
|
||||
|
||||
class Player(MappedBase):
|
||||
"""Class reflecting Players db table"""
|
||||
|
||||
@staticmethod
|
||||
def get_or_create(session, siteId, name):
|
||||
return get_or_create(Player, session, siteId=siteId, name=name)[0]
|
||||
|
||||
def __str__(self):
|
||||
return '<Player "%s" on %s>' % (self.name, self.site and self.site.name)
|
||||
|
||||
|
||||
class Gametype(MappedBase):
|
||||
"""Class reflecting Gametypes db table"""
|
||||
|
||||
@staticmethod
|
||||
def get_or_create(session, siteId, gametype):
|
||||
map = zip(
|
||||
['type', 'base', 'category', 'limitType', 'smallBlind', 'bigBlind', 'smallBet', 'bigBet'],
|
||||
['type', 'base', 'category', 'limitType', 'sb', 'bb', 'dummy', 'dummy', ])
|
||||
gametype = dict([(new, gametype.get(old)) for new, old in map ])
|
||||
|
||||
hilo = "h"
|
||||
if gametype['category'] in ('studhilo', 'omahahilo'):
|
||||
hilo = "s"
|
||||
elif gametype['category'] in ('razz','27_3draw','badugi'):
|
||||
hilo = "l"
|
||||
gametype['hiLo'] = hilo
|
||||
|
||||
for f in ['smallBlind', 'bigBlind', 'smallBet', 'bigBet']:
|
||||
if gametype[f] is None:
|
||||
gametype[f] = 0
|
||||
gametype[f] = int(Decimal(gametype[f])*100)
|
||||
|
||||
gametype['siteId'] = siteId
|
||||
return get_or_create(Gametype, session, **gametype)[0]
|
||||
|
||||
|
||||
class HandActions(object):
|
||||
"""Class reflecting HandsActions db table"""
|
||||
def initFromImportedHand(self, hand, actions):
|
||||
self.hand = hand
|
||||
self.actions = {}
|
||||
for street, street_actions in actions.iteritems():
|
||||
self.actions[street] = []
|
||||
for v in street_actions:
|
||||
hp = hand.handplayers_by_name[v[0]]
|
||||
self.actions[street].append({'street': street, 'pid': hp.id, 'seat': hp.seatNo, 'action':v})
|
||||
|
||||
@property
|
||||
def flat_actions(self):
|
||||
actions = []
|
||||
for street in self.hand.allStreets:
|
||||
actions += self.actions[street]
|
||||
return actions
|
||||
|
||||
|
||||
|
||||
class HandInternal(DerivedStats):
|
||||
"""Class reflecting Hands db table"""
|
||||
|
||||
def parseImportedHandStep1(self, hand):
|
||||
"""Extracts values to insert into from hand returned by HHC. No db is needed he"""
|
||||
hand.players = hand.getAlivePlayers()
|
||||
|
||||
# also save some data for step2. Those fields aren't in Hands table
|
||||
self.siteId = hand.siteId
|
||||
self.gametype_dict = hand.gametype
|
||||
|
||||
self.attachHandPlayers(hand)
|
||||
self.attachActions(hand)
|
||||
|
||||
self.assembleHands(hand)
|
||||
self.assembleHandsPlayers(hand)
|
||||
|
||||
def parseImportedHandStep2(self, session):
|
||||
"""Fetching ids for gametypes and players"""
|
||||
gametype = Gametype.get_or_create(session, self.siteId, self.gametype_dict)
|
||||
self.gametypeId = gametype.id
|
||||
for hp in self.handPlayers:
|
||||
hp.playerId = Player.get_or_create(session, self.siteId, hp.name).id
|
||||
|
||||
def getPlayerByName(self, name):
|
||||
if not hasattr(self, 'handplayers_by_name'):
|
||||
self.handplayers_by_name = {}
|
||||
for hp in self.handPlayers:
|
||||
pname = getattr(hp, 'name', None) or hp.player.name
|
||||
self.handplayers_by_name[pname] = hp
|
||||
return self.handplayers_by_name[name]
|
||||
|
||||
def attachHandPlayers(self, hand):
|
||||
"""Fill HandInternal.handPlayers list. Create self.handplayers_by_name"""
|
||||
hand.noSb = getattr(hand, 'noSb', None)
|
||||
if hand.noSb is None and self.gametype_dict['base']=='hold':
|
||||
saw_sb = False
|
||||
for action in hand.actions[hand.actionStreets[0]]: # blindsantes
|
||||
if action[1] == 'posts' and action[2] == 'small blind' and action[0] is not None:
|
||||
saw_sb = True
|
||||
hand.noSb = saw_sb
|
||||
|
||||
self.handplayers_by_name = {}
|
||||
for seat, name, chips in hand.players:
|
||||
p = HandPlayer(hand = self, imported_hand=hand, seatNo=seat,
|
||||
name=name, startCash=chips)
|
||||
self.handplayers_by_name[name] = p
|
||||
|
||||
def attachActions(self, hand):
|
||||
"""Create HandActions object"""
|
||||
a = HandActions()
|
||||
a.initFromImportedHand(self, hand.actions)
|
||||
|
||||
def parseImportedTournament(self, hand, session):
|
||||
"""Fetching tourney, its type and players
|
||||
|
||||
Must be called after Step2
|
||||
"""
|
||||
if self.gametype_dict['type'] != 'tour': return
|
||||
|
||||
# check for consistense
|
||||
for i in ('buyin', 'tourNo'):
|
||||
if not hasattr(hand, i):
|
||||
raise IncompleteHandError(
|
||||
"Field '%s' required for tournaments" % i, self.id, hand )
|
||||
|
||||
# repair old-style buyin value
|
||||
m = re.match('\$(\d+)\+\$(\d+)', hand.buyin)
|
||||
if m is not None:
|
||||
hand.buyin, self.fee = m.groups()
|
||||
|
||||
# fetch tourney type
|
||||
tour_type_hand2db = {
|
||||
'buyin': 'buyin',
|
||||
'fee': 'fee',
|
||||
'speed': 'speed',
|
||||
'maxSeats': 'maxseats',
|
||||
'knockout': 'isKO',
|
||||
'rebuyOrAddon': 'isRebuy',
|
||||
'headsUp': 'isHU',
|
||||
'shootout': 'isShootout',
|
||||
'matrix': 'isMatrix',
|
||||
'sng': 'isSNG',
|
||||
}
|
||||
tour_type_index = dict([
|
||||
( i_db, getattr(hand, i_hand, None) )
|
||||
for i_db, i_hand in tour_type_hand2db.iteritems()
|
||||
])
|
||||
tour_type_index['siteId'] = self.siteId
|
||||
tour_type = TourneyType.get_or_create(session, **tour_type_index)
|
||||
|
||||
# fetch and update tourney
|
||||
tour = Tourney.get_or_create(session, hand.tourNo, tour_type.id)
|
||||
cols = tour.get_columns_names()
|
||||
for col in cols:
|
||||
hand_val = getattr(hand, col, None)
|
||||
if col in ('id', 'tourneyTypeId', 'comment', 'commentTs') or hand_val is None:
|
||||
continue
|
||||
db_val = getattr(tour, col, None)
|
||||
if db_val is None:
|
||||
setattr(tour, col, hand_val)
|
||||
elif col == 'koBounty':
|
||||
setattr(tour, col, max(db_val, hand_val))
|
||||
elif col == 'tourStartTime' and hand.handStart:
|
||||
setattr(tour, col, min(db_val, hand.handStart))
|
||||
|
||||
if tour.entries is None and tour_type.sng:
|
||||
tour.entries = tour_type.maxSeats
|
||||
|
||||
# fetch and update tourney players
|
||||
for hp in self.handPlayers:
|
||||
tp = TourneyPlayer.get_or_create(session, tour.id, hp.playerId)
|
||||
# FIXME: other TourneysPlayers should be added here
|
||||
|
||||
session.flush()
|
||||
|
||||
def isDuplicate(self, session):
|
||||
"""Checks if current hand already exists in db
|
||||
|
||||
siteHandNo ans gameTypeId have to be setted
|
||||
"""
|
||||
return session.query(HandInternal).filter_by(
|
||||
siteHandNo=self.siteHandNo, gametypeId=self.gametypeId).count()!=0
|
||||
|
||||
def __str__(self):
|
||||
s = list()
|
||||
for i in self._sa_class_manager.mapper.c:
|
||||
s.append('%25s %s' % (i, getattr(self, i.name)))
|
||||
|
||||
s+=['', '']
|
||||
for i,p in enumerate(self.handPlayers):
|
||||
s.append('%d. %s' % (i, p.name or '???'))
|
||||
s.append(str(p))
|
||||
return '\n'.join(s)
|
||||
|
||||
@property
|
||||
def boardcards(self):
|
||||
cards = []
|
||||
for i in range(5):
|
||||
cards.append(getattr(self, 'boardcard%d' % (i+1), None))
|
||||
return filter(bool, cards)
|
||||
|
||||
@property
|
||||
def HandClass(self):
|
||||
"""Return HoldemOmahaHand or something like this"""
|
||||
import Hand
|
||||
if self.gametype.base == 'hold':
|
||||
return Hand.HoldemOmahaHand
|
||||
elif self.gametype.base == 'draw':
|
||||
return Hand.DrawHand
|
||||
elif self.gametype.base == 'stud':
|
||||
return Hand.StudHand
|
||||
raise Exception("Unknow gametype.base: '%s'" % self.gametype.base)
|
||||
|
||||
@property
|
||||
def allStreets(self):
|
||||
return self.HandClass.allStreets
|
||||
|
||||
@property
|
||||
def actionStreets(self):
|
||||
return self.HandClass.actionStreets
|
||||
|
||||
|
||||
|
||||
class HandPlayer(MappedBase):
|
||||
"""Class reflecting HandsPlayers db table"""
|
||||
def __init__(self, **kwargs):
|
||||
if 'imported_hand' in kwargs and 'seatNo' in kwargs:
|
||||
imported_hand = kwargs.pop('imported_hand')
|
||||
self.position = self.getPosition(imported_hand, kwargs['seatNo'])
|
||||
super(HandPlayer, self).__init__(**kwargs)
|
||||
|
||||
@reconstructor
|
||||
def init_on_load(self):
|
||||
self.name = self.player.name
|
||||
|
||||
@staticmethod
|
||||
def getPosition(hand, seat):
|
||||
"""Returns position value like 'B', 'S', '0', '1', ...
|
||||
|
||||
>>> class A(object): pass
|
||||
...
|
||||
>>> A.noSb = False
|
||||
>>> A.maxseats = 6
|
||||
>>> A.buttonpos = 2
|
||||
>>> A.gametype = {'base': 'hold'}
|
||||
>>> A.players = [(i, None, None) for i in (2, 4, 5, 6)]
|
||||
>>> HandPlayer.getPosition(A, 6) # cut off
|
||||
'1'
|
||||
>>> HandPlayer.getPosition(A, 2) # button
|
||||
'0'
|
||||
>>> HandPlayer.getPosition(A, 4) # SB
|
||||
'S'
|
||||
>>> HandPlayer.getPosition(A, 5) # BB
|
||||
'B'
|
||||
>>> A.noSb = True
|
||||
>>> HandPlayer.getPosition(A, 5) # MP3
|
||||
'2'
|
||||
>>> HandPlayer.getPosition(A, 6) # cut off
|
||||
'1'
|
||||
>>> HandPlayer.getPosition(A, 2) # button
|
||||
'0'
|
||||
>>> HandPlayer.getPosition(A, 4) # BB
|
||||
'B'
|
||||
"""
|
||||
from itertools import chain
|
||||
if hand.gametype['base'] == 'stud':
|
||||
# FIXME: i've never played stud so plz check & del comment \\grindi
|
||||
bringin = None
|
||||
for action in chain(*[self.actions[street] for street in hand.allStreets]):
|
||||
if action[1]=='bringin':
|
||||
bringin = action[0]
|
||||
break
|
||||
if bringin is None:
|
||||
raise Exception, "Cannot find bringin"
|
||||
# name -> seat
|
||||
bringin = int(filter(lambda p: p[1]==bringin, bringin)[0])
|
||||
seat = (int(seat) - int(bringin))%int(hand.maxseats)
|
||||
return str(seat)
|
||||
else:
|
||||
seats_occupied = sorted([seat_ for seat_, name, chips in hand.players], key=int)
|
||||
if hand.buttonpos not in seats_occupied:
|
||||
# i.e. something like
|
||||
# Seat 3: PlayerX ($0), is sitting out
|
||||
# The button is in seat #3
|
||||
hand.buttonpos = max(seats_occupied,
|
||||
key = lambda s: int(s)
|
||||
if int(s) <= int(hand.buttonpos)
|
||||
else int(s) - int(hand.maxseats)
|
||||
)
|
||||
seats_occupied = sorted(seats_occupied,
|
||||
key = lambda seat_: (
|
||||
- seats_occupied.index(seat_)
|
||||
+ seats_occupied.index(hand.buttonpos)
|
||||
+ 2) % len(seats_occupied)
|
||||
)
|
||||
# now (if SB presents) seats_occupied contains seats in order: BB, SB, BU, CO, MP3, ...
|
||||
if hand.noSb:
|
||||
# fix order in the case nosb
|
||||
seats_occupied = seats_occupied[1:] + seats_occupied[0:1]
|
||||
seats_occupied.insert(1, -1)
|
||||
seat = seats_occupied.index(seat)
|
||||
if seat == 0:
|
||||
return 'B'
|
||||
elif seat == 1:
|
||||
return 'S'
|
||||
else:
|
||||
return str(seat-2)
|
||||
|
||||
@property
|
||||
def cards(self):
|
||||
cards = []
|
||||
for i in range(7):
|
||||
cards.append(getattr(self, 'card%d' % (i+1), None))
|
||||
return filter(bool, cards)
|
||||
|
||||
def __str__(self):
|
||||
s = list()
|
||||
for i in self._sa_class_manager.mapper.c:
|
||||
s.append('%45s %s' % (i, getattr(self, i.name)))
|
||||
return '\n'.join(s)
|
||||
|
||||
|
||||
class Site(object):
|
||||
"""Class reflecting Players db table"""
|
||||
INITIAL_DATA = [
|
||||
(1 , 'Full Tilt Poker','USD'),
|
||||
(2 , 'PokerStars', 'USD'),
|
||||
(3 , 'Everleaf', 'USD'),
|
||||
(4 , 'Win2day', 'USD'),
|
||||
(5 , 'OnGame', 'USD'),
|
||||
(6 , 'UltimateBet', 'USD'),
|
||||
(7 , 'Betfair', 'USD'),
|
||||
(8 , 'Absolute', 'USD'),
|
||||
(9 , 'PartyPoker', 'USD'),
|
||||
(10, 'Partouche', 'EUR'),
|
||||
]
|
||||
INITIAL_DATA_KEYS = ('id', 'name', 'currency')
|
||||
|
||||
INITIAL_DATA_DICTS = [ dict(zip(INITIAL_DATA_KEYS, datum)) for datum in INITIAL_DATA ]
|
||||
|
||||
@classmethod
|
||||
def insert_initial(cls, connection):
|
||||
connection.execute(sites_table.insert(), cls.INITIAL_DATA_DICTS)
|
||||
|
||||
|
||||
class Tourney(MappedBase):
|
||||
"""Class reflecting Tourneys db table"""
|
||||
|
||||
@classmethod
|
||||
def get_or_create(cls, session, siteTourneyNo, tourneyTypeId):
|
||||
"""Fetch tourney by index or creates one if none. """
|
||||
return get_or_create(cls, session, siteTourneyNo=siteTourneyNo,
|
||||
tourneyTypeId=tourneyTypeId)[0]
|
||||
|
||||
|
||||
|
||||
class TourneyType(MappedBase):
|
||||
"""Class reflecting TourneysType db table"""
|
||||
|
||||
@classmethod
|
||||
def get_or_create(cls, session, **kwargs):
|
||||
"""Fetch tourney type by index or creates one if none
|
||||
|
||||
Required kwargs:
|
||||
buyin fee speed maxSeats knockout
|
||||
rebuyOrAddon headsUp shootout matrix sng
|
||||
"""
|
||||
return get_or_create(cls, session, **kwargs)[0]
|
||||
|
||||
|
||||
class TourneyPlayer(MappedBase):
|
||||
"""Class reflecting TourneysPlayers db table"""
|
||||
|
||||
@classmethod
|
||||
def get_or_create(cls, session, tourneyId, playerId):
|
||||
"""Fetch tourney player by index or creates one if none """
|
||||
return get_or_create(cls, session, tourneyId=tourneyId, playerId=playerId)
|
||||
|
||||
|
||||
class Version(object):
|
||||
"""Provides read/write access for version var"""
|
||||
CURRENT_VERSION = 120 # db version for current release
|
||||
# 119 - first alchemy version
|
||||
# 120 - add m_factor
|
||||
|
||||
conn = None
|
||||
ver = None
|
||||
def __init__(self, connection=None):
|
||||
if self.__class__.conn is None:
|
||||
self.__class__.conn = connection
|
||||
|
||||
@classmethod
|
||||
def is_wrong(cls):
|
||||
return cls.get() != cls.CURRENT_VERSION
|
||||
|
||||
@classmethod
|
||||
def get(cls):
|
||||
if cls.ver is None:
|
||||
try:
|
||||
cls.ver = cls.conn.execute(select(['version'], settings_table)).fetchone()[0]
|
||||
except:
|
||||
return None
|
||||
return cls.ver
|
||||
|
||||
@classmethod
|
||||
def set(cls, value):
|
||||
if cls.conn.execute(settings_table.select()).rowcount==0:
|
||||
cls.conn.execute(settings_table.insert(), version=value)
|
||||
else:
|
||||
cls.conn.execute(settings_table.update().values(version=value))
|
||||
cls.ver = value
|
||||
|
||||
@classmethod
|
||||
def set_initial(cls):
|
||||
cls.set(cls.CURRENT_VERSION)
|
||||
|
||||
|
||||
mapper (Gametype, gametypes_table, properties={
|
||||
'hands': relation(HandInternal, backref='gametype'),
|
||||
})
|
||||
mapper (Player, players_table, properties={
|
||||
'playerHands': relation(HandPlayer, backref='player'),
|
||||
'playerTourney': relation(TourneyPlayer, backref='player'),
|
||||
})
|
||||
mapper (Site, sites_table, properties={
|
||||
'gametypes': relation(Gametype, backref = 'site'),
|
||||
'players': relation(Player, backref = 'site'),
|
||||
'tourneyTypes': relation(TourneyType, backref = 'site'),
|
||||
})
|
||||
mapper (HandActions, hands_actions_table, properties={})
|
||||
mapper (HandInternal, hands_table, properties={
|
||||
'handPlayers': relation(HandPlayer, backref='hand'),
|
||||
'actions_all': relation(HandActions, backref='hand', uselist=False),
|
||||
})
|
||||
mapper (HandPlayer, hands_players_table, properties={})
|
||||
|
||||
mapper (Tourney, tourneys_table)
|
||||
mapper (TourneyType, tourney_types_table, properties={
|
||||
'tourneys': relation(Tourney, backref='type'),
|
||||
})
|
||||
mapper (TourneyPlayer, tourneys_players_table)
|
||||
|
||||
class LambdaKeyDict(defaultdict):
|
||||
"""Operates like defaultdict but passes key argument to the factory function"""
|
||||
def __missing__(key):
|
||||
return self.default_factory(key)
|
||||
|
438
pyfpdb/AlchemyTables.py
Normal file
438
pyfpdb/AlchemyTables.py
Normal file
|
@ -0,0 +1,438 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""@package AlchemyTables
|
||||
Contains all sqlalchemy tables
|
||||
"""
|
||||
|
||||
from sqlalchemy import Table, Float, Column, Integer, String, MetaData, \
|
||||
ForeignKey, Boolean, SmallInteger, DateTime, Text, Index, CHAR, \
|
||||
PickleType, Unicode
|
||||
|
||||
from AlchemyFacilities import CardColumn, MoneyColumn, BigIntColumn
|
||||
|
||||
|
||||
metadata = MetaData()
|
||||
|
||||
|
||||
autorates_table = Table('Autorates', metadata,
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False),
|
||||
Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False),
|
||||
Column('description', String(50), nullable=False),
|
||||
Column('shortDesc', CHAR(8), nullable=False),
|
||||
Column('ratingTime', DateTime, nullable=False),
|
||||
Column('handCount', Integer, nullable=False),
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
|
||||
|
||||
gametypes_table = Table('Gametypes', metadata,
|
||||
Column('id', SmallInteger, primary_key=True),
|
||||
Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT
|
||||
Column('type', String(4), nullable=False), # char(4) NOT NULL
|
||||
Column('base', String(4), nullable=False), # char(4) NOT NULL
|
||||
Column('category', String(9), nullable=False), # varchar(9) NOT NULL
|
||||
Column('limitType', CHAR(2), nullable=False), # char(2) NOT NULL
|
||||
Column('hiLo', CHAR(1), nullable=False), # char(1) NOT NULL
|
||||
Column('smallBlind', Integer(3)), # int
|
||||
Column('bigBlind', Integer(3)), # int
|
||||
Column('smallBet', Integer(3), nullable=False), # int NOT NULL
|
||||
Column('bigBet', Integer(3), nullable=False), # int NOT NULL
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
|
||||
|
||||
hands_table = Table('Hands', metadata,
|
||||
Column('id', BigIntColumn, primary_key=True),
|
||||
Column('tableName', String(30), nullable=False),
|
||||
Column('siteHandNo', BigIntColumn, nullable=False),
|
||||
Column('gametypeId', SmallInteger, ForeignKey('Gametypes.id'), nullable=False),
|
||||
Column('handStart', DateTime, nullable=False),
|
||||
Column('importTime', DateTime, nullable=False),
|
||||
Column('seats', SmallInteger, nullable=False),
|
||||
Column('maxSeats', SmallInteger, nullable=False),
|
||||
|
||||
Column('boardcard1', CardColumn),
|
||||
Column('boardcard2', CardColumn),
|
||||
Column('boardcard3', CardColumn),
|
||||
Column('boardcard4', CardColumn),
|
||||
Column('boardcard5', CardColumn),
|
||||
Column('texture', SmallInteger),
|
||||
Column('playersVpi', SmallInteger, nullable=False),
|
||||
Column('playersAtStreet1', SmallInteger, nullable=False, default=0),
|
||||
Column('playersAtStreet2', SmallInteger, nullable=False, default=0),
|
||||
Column('playersAtStreet3', SmallInteger, nullable=False, default=0),
|
||||
Column('playersAtStreet4', SmallInteger, nullable=False, default=0),
|
||||
Column('playersAtShowdown',SmallInteger, nullable=False),
|
||||
Column('street0Raises', SmallInteger, nullable=False),
|
||||
Column('street1Raises', SmallInteger, nullable=False),
|
||||
Column('street2Raises', SmallInteger, nullable=False),
|
||||
Column('street3Raises', SmallInteger, nullable=False),
|
||||
Column('street4Raises', SmallInteger, nullable=False),
|
||||
Column('street1Pot', MoneyColumn),
|
||||
Column('street2Pot', MoneyColumn),
|
||||
Column('street3Pot', MoneyColumn),
|
||||
Column('street4Pot', MoneyColumn),
|
||||
Column('showdownPot', MoneyColumn),
|
||||
Column('comment', Text),
|
||||
Column('commentTs', DateTime),
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
Index('siteHandNo', hands_table.c.siteHandNo, hands_table.c.gametypeId, unique=True)
|
||||
|
||||
|
||||
hands_actions_table = Table('HandsActions', metadata,
|
||||
Column('id', BigIntColumn, primary_key=True, nullable=False),
|
||||
Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False),
|
||||
Column('actions', PickleType, nullable=False),
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
|
||||
|
||||
hands_players_table = Table('HandsPlayers', metadata,
|
||||
Column('id', BigIntColumn, primary_key=True),
|
||||
Column('handId', BigIntColumn, ForeignKey("Hands.id"), nullable=False),
|
||||
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False),
|
||||
Column('startCash', MoneyColumn),
|
||||
Column('position', CHAR(1)), #CHAR(1)
|
||||
Column('seatNo', SmallInteger, nullable=False), #SMALLINT NOT NULL
|
||||
|
||||
Column('card1', CardColumn), #smallint NOT NULL,
|
||||
Column('card2', CardColumn), #smallint NOT NULL
|
||||
Column('card3', CardColumn), #smallint
|
||||
Column('card4', CardColumn), #smallint
|
||||
Column('card5', CardColumn), #smallint
|
||||
Column('card6', CardColumn), #smallint
|
||||
Column('card7', CardColumn), #smallint
|
||||
Column('startCards', SmallInteger), #smallint
|
||||
|
||||
Column('m_factor', Integer), # null for ring games
|
||||
Column('ante', MoneyColumn), #INT
|
||||
Column('winnings', MoneyColumn, nullable=False, default=0), #int NOT NULL
|
||||
Column('rake', MoneyColumn, nullable=False, default=0), #int NOT NULL
|
||||
Column('totalProfit', MoneyColumn), #INT
|
||||
Column('comment', Text), #text
|
||||
Column('commentTs', DateTime), #DATETIME
|
||||
Column('tourneysPlayersId', BigIntColumn, ForeignKey("TourneysPlayers.id"),), #BIGINT UNSIGNED
|
||||
Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"),), #SMALLINT UNSIGNED
|
||||
|
||||
Column('wonWhenSeenStreet1',Float), #FLOAT
|
||||
Column('wonWhenSeenStreet2',Float), #FLOAT
|
||||
Column('wonWhenSeenStreet3',Float), #FLOAT
|
||||
Column('wonWhenSeenStreet4',Float), #FLOAT
|
||||
Column('wonAtSD', Float), #FLOAT
|
||||
|
||||
Column('street0VPI', Boolean), #BOOLEAN
|
||||
Column('street0Aggr', Boolean), #BOOLEAN
|
||||
Column('street0_3BChance', Boolean), #BOOLEAN
|
||||
Column('street0_3BDone', Boolean), #BOOLEAN
|
||||
Column('street0_4BChance', Boolean), #BOOLEAN
|
||||
Column('street0_4BDone', Boolean), #BOOLEAN
|
||||
Column('other3BStreet0', Boolean), #BOOLEAN
|
||||
Column('other4BStreet0', Boolean), #BOOLEAN
|
||||
|
||||
Column('street1Seen', Boolean), #BOOLEAN
|
||||
Column('street2Seen', Boolean), #BOOLEAN
|
||||
Column('street3Seen', Boolean), #BOOLEAN
|
||||
Column('street4Seen', Boolean), #BOOLEAN
|
||||
Column('sawShowdown', Boolean), #BOOLEAN
|
||||
|
||||
Column('street1Aggr', Boolean), #BOOLEAN
|
||||
Column('street2Aggr', Boolean), #BOOLEAN
|
||||
Column('street3Aggr', Boolean), #BOOLEAN
|
||||
Column('street4Aggr', Boolean), #BOOLEAN
|
||||
|
||||
Column('otherRaisedStreet0',Boolean), #BOOLEAN
|
||||
Column('otherRaisedStreet1',Boolean), #BOOLEAN
|
||||
Column('otherRaisedStreet2',Boolean), #BOOLEAN
|
||||
Column('otherRaisedStreet3',Boolean), #BOOLEAN
|
||||
Column('otherRaisedStreet4',Boolean), #BOOLEAN
|
||||
Column('foldToOtherRaisedStreet0', Boolean), #BOOLEAN
|
||||
Column('foldToOtherRaisedStreet1', Boolean), #BOOLEAN
|
||||
Column('foldToOtherRaisedStreet2', Boolean), #BOOLEAN
|
||||
Column('foldToOtherRaisedStreet3', Boolean), #BOOLEAN
|
||||
Column('foldToOtherRaisedStreet4', Boolean), #BOOLEAN
|
||||
|
||||
Column('stealAttemptChance', Boolean), #BOOLEAN
|
||||
Column('stealAttempted', Boolean), #BOOLEAN
|
||||
Column('foldBbToStealChance', Boolean), #BOOLEAN
|
||||
Column('foldedBbToSteal', Boolean), #BOOLEAN
|
||||
Column('foldSbToStealChance', Boolean), #BOOLEAN
|
||||
Column('foldedSbToSteal', Boolean), #BOOLEAN
|
||||
|
||||
Column('street1CBChance', Boolean), #BOOLEAN
|
||||
Column('street1CBDone', Boolean), #BOOLEAN
|
||||
Column('street2CBChance', Boolean), #BOOLEAN
|
||||
Column('street2CBDone', Boolean), #BOOLEAN
|
||||
Column('street3CBChance', Boolean), #BOOLEAN
|
||||
Column('street3CBDone', Boolean), #BOOLEAN
|
||||
Column('street4CBChance', Boolean), #BOOLEAN
|
||||
Column('street4CBDone', Boolean), #BOOLEAN
|
||||
|
||||
Column('foldToStreet1CBChance', Boolean), #BOOLEAN
|
||||
Column('foldToStreet1CBDone', Boolean), #BOOLEAN
|
||||
Column('foldToStreet2CBChance', Boolean), #BOOLEAN
|
||||
Column('foldToStreet2CBDone', Boolean), #BOOLEAN
|
||||
Column('foldToStreet3CBChance', Boolean), #BOOLEAN
|
||||
Column('foldToStreet3CBDone', Boolean), #BOOLEAN
|
||||
Column('foldToStreet4CBChance', Boolean), #BOOLEAN
|
||||
Column('foldToStreet4CBDone', Boolean), #BOOLEAN
|
||||
|
||||
Column('street1CheckCallRaiseChance',Boolean), #BOOLEAN
|
||||
Column('street1CheckCallRaiseDone', Boolean), #BOOLEAN
|
||||
Column('street2CheckCallRaiseChance',Boolean), #BOOLEAN
|
||||
Column('street2CheckCallRaiseDone', Boolean), #BOOLEAN
|
||||
Column('street3CheckCallRaiseChance',Boolean), #BOOLEAN
|
||||
Column('street3CheckCallRaiseDone', Boolean), #BOOLEAN
|
||||
Column('street4CheckCallRaiseChance',Boolean), #BOOLEAN
|
||||
Column('street4CheckCallRaiseDone', Boolean), #BOOLEAN
|
||||
|
||||
Column('street0Calls', SmallInteger), #TINYINT
|
||||
Column('street1Calls', SmallInteger), #TINYINT
|
||||
Column('street2Calls', SmallInteger), #TINYINT
|
||||
Column('street3Calls', SmallInteger), #TINYINT
|
||||
Column('street4Calls', SmallInteger), #TINYINT
|
||||
Column('street0Bets', SmallInteger), #TINYINT
|
||||
Column('street1Bets', SmallInteger), #TINYINT
|
||||
Column('street2Bets', SmallInteger), #TINYINT
|
||||
Column('street3Bets', SmallInteger), #TINYINT
|
||||
Column('street4Bets', SmallInteger), #TINYINT
|
||||
Column('street0Raises', SmallInteger), #TINYINT
|
||||
Column('street1Raises', SmallInteger), #TINYINT
|
||||
Column('street2Raises', SmallInteger), #TINYINT
|
||||
Column('street3Raises', SmallInteger), #TINYINT
|
||||
Column('street4Raises', SmallInteger), #TINYINT
|
||||
|
||||
Column('actionString', String(15)), #VARCHAR(15)
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
|
||||
|
||||
hud_cache_table = Table('HudCache', metadata,
|
||||
Column('id', BigIntColumn, primary_key=True),
|
||||
Column('gametypeId', SmallInteger, ForeignKey("Gametypes.id"), nullable=False), # SMALLINT
|
||||
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False), # SMALLINT
|
||||
Column('activeSeats', SmallInteger, nullable=False), # SMALLINT NOT NULL
|
||||
Column('position', CHAR(1)), # CHAR(1)
|
||||
Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id") ), # SMALLINT
|
||||
Column('styleKey', CHAR(7), nullable=False), # CHAR(7) NOT NULL
|
||||
Column('m_factor', Integer),
|
||||
Column('HDs', Integer, nullable=False), # INT NOT NULL
|
||||
|
||||
Column('wonWhenSeenStreet1', Float), # FLOAT
|
||||
Column('wonWhenSeenStreet2', Float), # FLOAT
|
||||
Column('wonWhenSeenStreet3', Float), # FLOAT
|
||||
Column('wonWhenSeenStreet4', Float), # FLOAT
|
||||
Column('wonAtSD', Float), # FLOAT
|
||||
|
||||
Column('street0VPI', Integer), # INT
|
||||
Column('street0Aggr', Integer), # INT
|
||||
Column('street0_3BChance', Integer), # INT
|
||||
Column('street0_3BDone', Integer), # INT
|
||||
Column('street0_4BChance', Integer), # INT
|
||||
Column('street0_4BDone', Integer), # INT
|
||||
Column('other3BStreet0', Integer), # INT
|
||||
Column('other4BStreet0', Integer), # INT
|
||||
|
||||
Column('street1Seen', Integer), # INT
|
||||
Column('street2Seen', Integer), # INT
|
||||
Column('street3Seen', Integer), # INT
|
||||
Column('street4Seen', Integer), # INT
|
||||
Column('sawShowdown', Integer), # INT
|
||||
|
||||
Column('street1Aggr', Integer), # INT
|
||||
Column('street2Aggr', Integer), # INT
|
||||
Column('street3Aggr', Integer), # INT
|
||||
Column('street4Aggr', Integer), # INT
|
||||
|
||||
Column('otherRaisedStreet0', Integer), # INT
|
||||
Column('otherRaisedStreet1', Integer), # INT
|
||||
Column('otherRaisedStreet2', Integer), # INT
|
||||
Column('otherRaisedStreet3', Integer), # INT
|
||||
Column('otherRaisedStreet4', Integer), # INT
|
||||
Column('foldToOtherRaisedStreet0', Integer), # INT
|
||||
Column('foldToOtherRaisedStreet1', Integer), # INT
|
||||
Column('foldToOtherRaisedStreet2', Integer), # INT
|
||||
Column('foldToOtherRaisedStreet3', Integer), # INT
|
||||
Column('foldToOtherRaisedStreet4', Integer), # INT
|
||||
|
||||
Column('stealAttemptChance', Integer), # INT
|
||||
Column('stealAttempted', Integer), # INT
|
||||
Column('foldBbToStealChance', Integer), # INT
|
||||
Column('foldedBbToSteal', Integer), # INT
|
||||
Column('foldSbToStealChance', Integer), # INT
|
||||
Column('foldedSbToSteal', Integer), # INT
|
||||
|
||||
Column('street1CBChance', Integer), # INT
|
||||
Column('street1CBDone', Integer), # INT
|
||||
Column('street2CBChance', Integer), # INT
|
||||
Column('street2CBDone', Integer), # INT
|
||||
Column('street3CBChance', Integer), # INT
|
||||
Column('street3CBDone', Integer), # INT
|
||||
Column('street4CBChance', Integer), # INT
|
||||
Column('street4CBDone', Integer), # INT
|
||||
|
||||
Column('foldToStreet1CBChance', Integer), # INT
|
||||
Column('foldToStreet1CBDone', Integer), # INT
|
||||
Column('foldToStreet2CBChance', Integer), # INT
|
||||
Column('foldToStreet2CBDone', Integer), # INT
|
||||
Column('foldToStreet3CBChance', Integer), # INT
|
||||
Column('foldToStreet3CBDone', Integer), # INT
|
||||
Column('foldToStreet4CBChance', Integer), # INT
|
||||
Column('foldToStreet4CBDone', Integer), # INT
|
||||
|
||||
Column('totalProfit', Integer), # INT
|
||||
|
||||
Column('street1CheckCallRaiseChance', Integer), # INT
|
||||
Column('street1CheckCallRaiseDone', Integer), # INT
|
||||
Column('street2CheckCallRaiseChance', Integer), # INT
|
||||
Column('street2CheckCallRaiseDone', Integer), # INT
|
||||
Column('street3CheckCallRaiseChance', Integer), # INT
|
||||
Column('street3CheckCallRaiseDone', Integer), # INT
|
||||
Column('street4CheckCallRaiseChance', Integer), # INT
|
||||
Column('street4CheckCallRaiseDone', Integer), # INT
|
||||
|
||||
Column('street0Calls', Integer), # INT
|
||||
Column('street1Calls', Integer), # INT
|
||||
Column('street2Calls', Integer), # INT
|
||||
Column('street3Calls', Integer), # INT
|
||||
Column('street4Calls', Integer), # INT
|
||||
Column('street0Bets', Integer), # INT
|
||||
Column('street1Bets', Integer), # INT
|
||||
Column('street2Bets', Integer), # INT
|
||||
Column('street3Bets', Integer), # INT
|
||||
Column('street4Bets', Integer), # INT
|
||||
Column('street0Raises', Integer), # INT
|
||||
Column('street1Raises', Integer), # INT
|
||||
Column('street2Raises', Integer), # INT
|
||||
Column('street3Raises', Integer), # INT
|
||||
Column('street4Raises', Integer), # INT
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
|
||||
|
||||
players_table = Table('Players', metadata,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('name', Unicode(32), nullable=False), # VARCHAR(32) CHARACTER SET utf8 NOT NULL
|
||||
Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False), # SMALLINT
|
||||
Column('comment', Text), # text
|
||||
Column('commentTs', DateTime), # DATETIME
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
Index('name', players_table.c.name, players_table.c.siteId, unique=True)
|
||||
|
||||
|
||||
settings_table = Table('Settings', metadata,
|
||||
Column('version', SmallInteger, nullable=False),
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
|
||||
|
||||
sites_table = Table('Sites', metadata,
|
||||
Column('id', SmallInteger, primary_key=True),
|
||||
Column('name', String(32), nullable=False), # varchar(32) NOT NULL
|
||||
Column('currency', String(3), nullable=False), # char(3) NOT NULL
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
|
||||
|
||||
tourneys_table = Table('Tourneys', metadata,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('tourneyTypeId', Integer, ForeignKey("TourneyTypes.id"), nullable=False, default=1),
|
||||
Column('siteTourneyNo', BigIntColumn, nullable=False), # BIGINT NOT NULL
|
||||
Column('entries', Integer), # INT NOT NULL
|
||||
Column('prizepool', Integer), # INT NOT NULL
|
||||
Column('tourStartTime', DateTime), # DATETIME NOT NULL
|
||||
Column('tourEndTime', DateTime), # DATETIME
|
||||
Column('buyinChips', Integer), # INT
|
||||
Column('tourneyName', String(40)), # varchar(40)
|
||||
# Mask use : 1=Positionnal Winnings|2=Match1|4=Match2|...|pow(2,n)=Matchn
|
||||
Column('matrixIdProcessed',SmallInteger, default=0), # TINYINT UNSIGNED DEFAULT 0
|
||||
Column('rebuyChips', Integer, default=0), # INT DEFAULT 0
|
||||
Column('addonChips', Integer, default=0), # INT DEFAULT 0
|
||||
Column('rebuyAmount', MoneyColumn, default=0), # INT DEFAULT 0
|
||||
Column('addonAmount', MoneyColumn, default=0), # INT DEFAULT 0
|
||||
Column('totalRebuys', Integer, default=0), # INT DEFAULT 0
|
||||
Column('totalAddons', Integer, default=0), # INT DEFAULT 0
|
||||
Column('koBounty', Integer, default=0), # INT DEFAULT 0
|
||||
Column('comment', Text), # TEXT
|
||||
Column('commentTs', DateTime), # DATETIME
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
Index('siteTourneyNo', tourneys_table.c.siteTourneyNo, tourneys_table.c.tourneyTypeId, unique=True)
|
||||
|
||||
|
||||
tourney_types_table = Table('TourneyTypes', metadata,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('siteId', SmallInteger, ForeignKey("Sites.id"), nullable=False),
|
||||
Column('buyin', Integer, nullable=False), # INT NOT NULL
|
||||
Column('fee', Integer, nullable=False, default=0), # INT NOT NULL
|
||||
Column('maxSeats', Boolean, nullable=False, default=-1), # INT NOT NULL DEFAULT -1
|
||||
Column('knockout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
|
||||
Column('rebuyOrAddon', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
|
||||
Column('speed', String(10)), # varchar(10)
|
||||
Column('headsUp', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
|
||||
Column('shootout', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
|
||||
Column('matrix', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
|
||||
Column('sng', Boolean, nullable=False, default=False), # BOOLEAN NOT NULL DEFAULT False
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
Index('tourneyTypes_all',
|
||||
tourney_types_table.c.siteId, tourney_types_table.c.buyin, tourney_types_table.c.fee,
|
||||
tourney_types_table.c.maxSeats, tourney_types_table.c.knockout, tourney_types_table.c.rebuyOrAddon,
|
||||
tourney_types_table.c.speed, tourney_types_table.c.headsUp, tourney_types_table.c.shootout,
|
||||
tourney_types_table.c.matrix, tourney_types_table.c.sng)
|
||||
|
||||
|
||||
tourneys_players_table = Table('TourneysPlayers', metadata,
|
||||
Column('id', BigIntColumn, primary_key=True),
|
||||
Column('tourneyId', Integer, ForeignKey("Tourneys.id"), nullable=False),
|
||||
Column('playerId', Integer, ForeignKey("Players.id"), nullable=False),
|
||||
Column('payinAmount', Integer), # INT NOT NULL
|
||||
Column('rank', Integer), # INT NOT NULL
|
||||
Column('winnings', Integer), # INT NOT NULL
|
||||
Column('nbRebuys', Integer, default=0), # INT DEFAULT 0
|
||||
Column('nbAddons', Integer, default=0), # INT DEFAULT 0
|
||||
Column('nbKO', Integer, default=0), # INT DEFAULT 0
|
||||
Column('comment', Text), # TEXT
|
||||
Column('commentTs', DateTime), # DATETIME
|
||||
mysql_charset='utf8',
|
||||
mysql_engine='InnoDB',
|
||||
)
|
||||
Index('tourneyId', tourneys_players_table.c.tourneyId, tourneys_players_table.c.playerId, unique=True)
|
||||
|
||||
|
||||
def sss():
|
||||
"Debug function. Returns (config, sql, db)"
|
||||
|
||||
import Configuration, SQL, Database, os
|
||||
class Dummy(object):
|
||||
pass
|
||||
self = Dummy()
|
||||
self.config = Configuration.Config()
|
||||
self.settings = {}
|
||||
if (os.sep=="/"):
|
||||
self.settings['os']="linuxmac"
|
||||
else:
|
||||
self.settings['os']="windows"
|
||||
|
||||
self.settings.update(self.config.get_db_parameters())
|
||||
self.settings.update(self.config.get_tv_parameters())
|
||||
self.settings.update(self.config.get_import_parameters())
|
||||
self.settings.update(self.config.get_default_paths())
|
||||
|
||||
self.sql = SQL.Sql( db_server = self.settings['db-server'])
|
||||
self.db = Database.Database(self.config, sql = self.sql)
|
||||
|
||||
return self.config, self.sql, self.db
|
||||
|
|
@ -4,12 +4,12 @@
|
|||
#This program is free software: you can redistribute it and/or modify
|
||||
#it under the terms of the GNU Affero General Public License as published by
|
||||
#the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
#
|
||||
#This program is distributed in the hope that it will be useful,
|
||||
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
#You should have received a copy of the GNU Affero General Public License
|
||||
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#In the "official" distribution you can find the license in
|
||||
|
@ -39,24 +39,37 @@ def calcStartCards(hand, player):
|
|||
|
||||
def twoStartCards(value1, suit1, value2, suit2):
|
||||
""" Function to convert 2 value,suit pairs into a Holdem style starting hand e.g. AQo
|
||||
Hand is stored as an int 13 * x + y where (x+2) represents rank of 1st card and
|
||||
Incoming values should be ints 2-14 (2,3,...K,A), suits are 'd'/'h'/'c'/'s'
|
||||
Hand is stored as an int 13 * x + y + 1 where (x+2) represents rank of 1st card and
|
||||
(y+2) represents rank of second card (2=2 .. 14=Ace)
|
||||
If x > y then pair is suited, if x < y then unsuited"""
|
||||
if value1 < 2 or value2 < 2:
|
||||
If x > y then pair is suited, if x < y then unsuited
|
||||
Examples:
|
||||
0 Unknown / Illegal cards
|
||||
1 22
|
||||
2 32o
|
||||
3 42o
|
||||
...
|
||||
14 32s
|
||||
15 33
|
||||
16 42o
|
||||
...
|
||||
170 AA
|
||||
"""
|
||||
if value1 is None or value1 < 2 or value1 > 14 or value2 is None or value2 < 2 or value2 > 14:
|
||||
ret = 0
|
||||
if value1 == value2: # pairs
|
||||
ret = (13 * (value2-2) + (value2-2) )
|
||||
elif value1 == value2: # pairs
|
||||
ret = (13 * (value2-2) + (value2-2) ) + 1
|
||||
elif suit1 == suit2:
|
||||
if value1 > value2:
|
||||
ret = 13 * (value1-2) + (value2-2)
|
||||
ret = 13 * (value1-2) + (value2-2) + 1
|
||||
else:
|
||||
ret = 13 * (value2-2) + (value1-2)
|
||||
ret = 13 * (value2-2) + (value1-2) + 1
|
||||
else:
|
||||
if value1 > value2:
|
||||
ret = 13 * (value2-2) + (value1-2)
|
||||
ret = 13 * (value2-2) + (value1-2) + 1
|
||||
else:
|
||||
ret = 13 * (value1-2) + (value2-2)
|
||||
|
||||
ret = 13 * (value1-2) + (value2-2) + 1
|
||||
|
||||
# print "twoStartCards(", value1, suit1, value2, suit2, ")=", ret
|
||||
return ret
|
||||
|
||||
|
@ -66,8 +79,8 @@ def twoStartCardString(card):
|
|||
ret = 'xx'
|
||||
if card > 0:
|
||||
s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
|
||||
x = card / 13
|
||||
y = card - 13 * x
|
||||
x = (card-1) / 13
|
||||
y = (card-1) - 13 * x
|
||||
if x == y: ret = s[x] + s[y]
|
||||
elif x > y: ret = s[x] + s[y] + 's'
|
||||
else: ret = s[y] + s[x] + 'o'
|
||||
|
@ -95,7 +108,7 @@ def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4):
|
|||
# SSSS (K, J, 6, 3)
|
||||
# - 13C4 = 715 possibilities
|
||||
# SSSx (K, J, 6),(3)
|
||||
# - 13C3 * 13 = 3718 possibilities
|
||||
# - 13C3 * 13 = 3718 possibilities
|
||||
# SSxy (K, J),(6),(3)
|
||||
# - 13C2 * 13*13 = 13182 possibilities
|
||||
# SSHH (K, J),(6, 3)
|
||||
|
@ -118,7 +131,7 @@ suitFromCardList = ['', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', 'Th', 'J
|
|||
, '2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', 'Ts', 'Js', 'Qs', 'Ks', 'As'
|
||||
]
|
||||
def valueSuitFromCard(card):
|
||||
""" Function to convert a card stored in the database (int 0-52) into value
|
||||
""" Function to convert a card stored in the database (int 0-52) into value
|
||||
and suit like 9s, 4c etc """
|
||||
global suitFromCardList
|
||||
if card < 0 or card > 52 or not card:
|
||||
|
@ -145,5 +158,5 @@ if __name__ == '__main__':
|
|||
print "card %2d = %s card %2d = %s card %2d = %s card %2d = %s" % \
|
||||
(i, valueSuitFromCard(i), i+13, valueSuitFromCard(i+13), i+26, valueSuitFromCard(i+26), i+39, valueSuitFromCard(i+39))
|
||||
|
||||
print
|
||||
print
|
||||
print encodeCard('7c')
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
#Copyright 2008 Steffen Jobbagy-Felso
|
||||
#This program is free software: you can redistribute it and/or modify
|
||||
#it under the terms of the GNU Affero General Public License as published by
|
||||
#the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
#This program is distributed in the hope that it will be useful,
|
||||
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#GNU General Public License for more details.
|
||||
#
|
||||
#You should have received a copy of the GNU Affero General Public License
|
||||
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#In the "official" distribution you can find the license in
|
||||
#agpl-3.0.txt in the docs folder of the package.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import fpdb_simple
|
||||
from optparse import OptionParser
|
||||
|
||||
try:
|
||||
import MySQLdb
|
||||
except:
|
||||
diaSQLLibMissing = gtk.Dialog(title="Fatal Error - SQL interface library missing", parent=None, flags=0, buttons=(gtk.STOCK_QUIT,gtk.RESPONSE_OK))
|
||||
|
||||
print "Please note that the CLI importer only works with MySQL, if you use PostgreSQL this error is expected."
|
||||
|
||||
import fpdb_import
|
||||
import fpdb_db
|
||||
|
||||
if __name__ == "__main__":
|
||||
#process CLI parameters
|
||||
parser = OptionParser()
|
||||
parser.add_option("-c", "--handCount", default="0", type="int",
|
||||
help="Number of hands to import (default 0 means unlimited)")
|
||||
parser.add_option("-d", "--database", default="fpdb", help="The MySQL database to use (default fpdb)")
|
||||
parser.add_option("-e", "--errorFile", default="failed.txt",
|
||||
help="File to store failed hands into. (default: failed.txt) Not implemented.")
|
||||
parser.add_option("-f", "--inputFile", "--file", "--inputfile", default="stdin",
|
||||
help="The file you want to import (remember to use quotes if necessary)")
|
||||
parser.add_option("-m", "--minPrint", "--status", default="50", type="int",
|
||||
help="How often to print a one-line status report (0 means never, default is 50)")
|
||||
parser.add_option("-p", "--password", help="The password for the MySQL user")
|
||||
parser.add_option("-q", "--quiet", action="store_true",
|
||||
help="If this is passed it doesn't print a total at the end nor the opening line. Note that this purposely does NOT change --minPrint")
|
||||
parser.add_option("-s", "--server", default="localhost",
|
||||
help="Hostname/IP of the MySQL server (default localhost)")
|
||||
parser.add_option("-u", "--user", default="fpdb", help="The MySQL username (default fpdb)")
|
||||
parser.add_option("-x", "--failOnError", action="store_true",
|
||||
help="If this option is passed it quits when it encounters any error")
|
||||
|
||||
(options, argv) = parser.parse_args()
|
||||
|
||||
settings={'callFpdbHud':False, 'db-backend':2}
|
||||
settings['db-host']=options.server
|
||||
settings['db-user']=options.user
|
||||
settings['db-password']=options.password
|
||||
settings['db-databaseName']=options.database
|
||||
settings['handCount']=options.handCount
|
||||
settings['failOnError']=options.failOnError
|
||||
|
||||
importer = fpdb_import.Importer(options, settings)
|
||||
importer.addImportFile(options.inputFile)
|
||||
importer.runImport()
|
|
@ -31,6 +31,7 @@ import inspect
|
|||
import string
|
||||
import traceback
|
||||
import shutil
|
||||
import locale
|
||||
import xml.dom.minidom
|
||||
from xml.dom.minidom import Node
|
||||
|
||||
|
@ -125,7 +126,8 @@ DATABASE_TYPES = (
|
|||
DATABASE_TYPE_MYSQL,
|
||||
)
|
||||
|
||||
NEWIMPORT = False
|
||||
NEWIMPORT = True
|
||||
LOCALE_ENCODING = locale.getdefaultlocale()[1]
|
||||
|
||||
########################################################################
|
||||
def string_to_bool(string, default=True):
|
||||
|
|
1186
pyfpdb/Database.py
1186
pyfpdb/Database.py
File diff suppressed because it is too large
Load Diff
|
@ -48,18 +48,11 @@ class DerivedStats():
|
|||
self.handsplayers[player[1]]['sawShowdown'] = False
|
||||
self.handsplayers[player[1]]['wonAtSD'] = 0.0
|
||||
self.handsplayers[player[1]]['startCards'] = 0
|
||||
for i in range(5):
|
||||
self.handsplayers[player[1]]['street%dCalls' % i] = 0
|
||||
self.handsplayers[player[1]]['street%dBets' % i] = 0
|
||||
for i in range(1,5):
|
||||
self.handsplayers[player[1]]['street%dCBChance' %i] = False
|
||||
self.handsplayers[player[1]]['street%dCBDone' %i] = False
|
||||
|
||||
#FIXME - Everything below this point is incomplete.
|
||||
self.handsplayers[player[1]]['position'] = 2
|
||||
self.handsplayers[player[1]]['tourneyTypeId'] = 1
|
||||
self.handsplayers[player[1]]['street0_3BChance'] = False
|
||||
self.handsplayers[player[1]]['street0_3BDone'] = False
|
||||
self.handsplayers[player[1]]['street0_4BChance'] = False
|
||||
self.handsplayers[player[1]]['street0_4BDone'] = False
|
||||
self.handsplayers[player[1]]['stealAttemptChance'] = False
|
||||
self.handsplayers[player[1]]['stealAttempted'] = False
|
||||
self.handsplayers[player[1]]['foldBbToStealChance'] = False
|
||||
|
@ -67,13 +60,22 @@ class DerivedStats():
|
|||
self.handsplayers[player[1]]['foldSbToStealChance'] = False
|
||||
self.handsplayers[player[1]]['foldedSbToSteal'] = False
|
||||
self.handsplayers[player[1]]['foldedBbToSteal'] = False
|
||||
for i in range(5):
|
||||
self.handsplayers[player[1]]['street%dCalls' % i] = 0
|
||||
self.handsplayers[player[1]]['street%dBets' % i] = 0
|
||||
for i in range(1,5):
|
||||
self.handsplayers[player[1]]['street%dCBChance' %i] = False
|
||||
self.handsplayers[player[1]]['street%dCBDone' %i] = False
|
||||
self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False
|
||||
self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False
|
||||
|
||||
#FIXME - Everything below this point is incomplete.
|
||||
self.handsplayers[player[1]]['tourneyTypeId'] = 1
|
||||
for i in range(1,5):
|
||||
self.handsplayers[player[1]]['otherRaisedStreet%d' %i] = False
|
||||
self.handsplayers[player[1]]['foldToOtherRaisedStreet%d' %i] = False
|
||||
self.handsplayers[player[1]]['foldToStreet%dCBChance' %i] = False
|
||||
self.handsplayers[player[1]]['foldToStreet%dCBDone' %i] = False
|
||||
self.handsplayers[player[1]]['street%dCheckCallRaiseChance' %i] = False
|
||||
self.handsplayers[player[1]]['street%dCheckCallRaiseDone' %i] = False
|
||||
|
||||
self.assembleHands(self.hand)
|
||||
self.assembleHandsPlayers(self.hand)
|
||||
|
@ -174,33 +176,47 @@ class DerivedStats():
|
|||
self.handsplayers[player[1]]['card%s' % (i+1)] = Card.encodeCard(card)
|
||||
self.handsplayers[player[1]]['startCards'] = Card.calcStartCards(hand, player[1])
|
||||
|
||||
# position,
|
||||
#Stud 3rd street card test
|
||||
# denny501: brings in for $0.02
|
||||
# s0rrow: calls $0.02
|
||||
# TomSludge: folds
|
||||
# Soroka69: calls $0.02
|
||||
# rdiezchang: calls $0.02 (Seat 8)
|
||||
# u.pressure: folds (Seat 1)
|
||||
# 123smoothie: calls $0.02
|
||||
# gashpor: calls $0.02
|
||||
|
||||
self.setPositions(hand)
|
||||
self.calcCheckCallRaise(hand)
|
||||
self.calc34BetStreet0(hand)
|
||||
self.calcSteals(hand)
|
||||
# Additional stats
|
||||
# 3betSB, 3betBB
|
||||
# Squeeze, Ratchet?
|
||||
|
||||
|
||||
def getPosition(hand, seat):
|
||||
"""Returns position value like 'B', 'S', 0, 1, ..."""
|
||||
# Flop/Draw games with blinds
|
||||
# Need a better system???
|
||||
# -2 BB - B (all)
|
||||
# -1 SB - S (all)
|
||||
# 0 Button
|
||||
# 1 Cutoff
|
||||
# 2 Hijack
|
||||
def setPositions(self, hand):
|
||||
"""Sets the position for each player in HandsPlayers
|
||||
any blinds are negative values, and the last person to act on the
|
||||
first betting round is 0
|
||||
NOTE: HU, both values are negative for non-stud games
|
||||
NOTE2: I've never seen a HU stud match"""
|
||||
# The position calculation must be done differently for Stud and other games as
|
||||
# Stud the 'blind' acts first - in all other games they act last.
|
||||
#
|
||||
#This function is going to get it wrong when there in situations where there
|
||||
# is no small blind. I can live with that.
|
||||
positions = [7, 6, 5, 4, 3, 2, 1, 0, 'S', 'B']
|
||||
actions = hand.actions[hand.holeStreets[0]]
|
||||
players = self.pfbao(actions)
|
||||
seats = len(players)
|
||||
map = []
|
||||
if hand.gametype['base'] == 'stud':
|
||||
# Could posibly change this to be either -2 or -1 depending if they complete or bring-in
|
||||
# First player to act is -1, last player is 0 for 6 players it should look like:
|
||||
# ['S', 4, 3, 2, 1, 0]
|
||||
map = positions[-seats-1:-1] # Copy required positions from postions array anding in -1
|
||||
map = map[-1:] + map[0:-1] # and move the -1 to the start of that array
|
||||
else:
|
||||
# For 6 players is should look like:
|
||||
# [3, 2, 1, 0, 'S', 'B']
|
||||
map = positions[-seats:] # Copy required positions from array ending in -2
|
||||
|
||||
for i, player in enumerate(players):
|
||||
self.handsplayers[player]['position'] = map[i]
|
||||
|
||||
def assembleHudCache(self, hand):
|
||||
# No real work to be done - HandsPlayers data already contains the correct info
|
||||
pass
|
||||
|
||||
def vpip(self, hand):
|
||||
|
@ -262,13 +278,59 @@ class DerivedStats():
|
|||
for (i, street) in enumerate(hand.actionStreets[1:]):
|
||||
self.hands['street%dRaises' % i] = len(filter( lambda action: action[1] in ('raises','bets'), hand.actions[street]))
|
||||
|
||||
def calcCBets(self, hand):
|
||||
# Continuation Bet chance, action:
|
||||
# Had the last bet (initiative) on previous street, got called, close street action
|
||||
# Then no bets before the player with initiatives first action on current street
|
||||
# ie. if player on street-1 had initiative
|
||||
# and no donkbets occurred
|
||||
def calcSteals(self, hand):
|
||||
"""Fills stealAttempt(Chance|ed, fold(Bb|Sb)ToSteal(Chance|)
|
||||
|
||||
Steal attemp - open raise on positions 2 1 0 S - i.e. MP3, CO, BU, SB
|
||||
Fold to steal - folding blind after steal attemp wo any other callers or raisers
|
||||
"""
|
||||
steal_attemp = False
|
||||
steal_positions = ('2', '1', '0', 'S')
|
||||
if hand.gametype['base'] == 'stud':
|
||||
steal_positions = ('2', '1', '0')
|
||||
for action in hand.actions[hand.actionStreets[1]]:
|
||||
pname, act = action[0], action[1]
|
||||
#print action[0], hp.position, steal_attemp, act
|
||||
if self.handsplayers[pname]['position'] == 'B':
|
||||
#NOTE: Stud games will never hit this section
|
||||
self.handsplayers[pname]['foldBbToStealChance'] = steal_attemp
|
||||
self.handsplayers[pname]['foldBbToSteal'] = self.handsplayers[pname]['foldBbToStealChance'] and act == 'folds'
|
||||
break
|
||||
elif self.handsplayers[pname]['position'] == 'S':
|
||||
self.handsplayers[pname]['foldSbToStealChance'] = steal_attemp
|
||||
self.handsplayers[pname]['foldSbToSteal'] = self.handsplayers[pname]['foldSbToStealChance'] and act == 'folds'
|
||||
|
||||
if steal_attemp and act != 'folds':
|
||||
break
|
||||
|
||||
if self.handsplayers[pname]['position'] in steal_positions and not steal_attemp:
|
||||
self.handsplayers[pname]['stealAttemptChance'] = True
|
||||
if act in ('bets', 'raises'):
|
||||
self.handsplayers[pname]['stealAttempted'] = True
|
||||
steal_attemp = True
|
||||
|
||||
def calc34BetStreet0(self, hand):
|
||||
"""Fills street0_(3|4)B(Chance|Done), other(3|4)BStreet0"""
|
||||
bet_level = 1 # bet_level after 3-bet is equal to 3
|
||||
for action in hand.actions[hand.actionStreets[1]]:
|
||||
# FIXME: fill other(3|4)BStreet0 - i have no idea what does it mean
|
||||
pname, aggr = action[0], action[1] in ('raises', 'bets')
|
||||
self.handsplayers[pname]['street0_3BChance'] = bet_level == 2
|
||||
self.handsplayers[pname]['street0_4BChance'] = bet_level == 3
|
||||
self.handsplayers[pname]['street0_3BDone'] = aggr and (self.handsplayers[pname]['street0_3BChance'])
|
||||
self.handsplayers[pname]['street0_4BDone'] = aggr and (self.handsplayers[pname]['street0_4BChance'])
|
||||
if aggr:
|
||||
bet_level += 1
|
||||
|
||||
|
||||
def calcCBets(self, hand):
|
||||
"""Fill streetXCBChance, streetXCBDone, foldToStreetXCBDone, foldToStreetXCBChance
|
||||
|
||||
Continuation Bet chance, action:
|
||||
Had the last bet (initiative) on previous street, got called, close street action
|
||||
Then no bets before the player with initiatives first action on current street
|
||||
ie. if player on street-1 had initiative and no donkbets occurred
|
||||
"""
|
||||
# XXX: enumerate(list, start=x) is python 2.6 syntax; 'start'
|
||||
# came there
|
||||
#for i, street in enumerate(hand.actionStreets[2:], start=1):
|
||||
|
@ -280,6 +342,29 @@ class DerivedStats():
|
|||
if chance == True:
|
||||
self.handsplayers[name]['street%dCBDone' % (i+1)] = self.betStreet(hand.actionStreets[i+2], name)
|
||||
|
||||
def calcCheckCallRaise(self, hand):
|
||||
"""Fill streetXCheckCallRaiseChance, streetXCheckCallRaiseDone
|
||||
|
||||
streetXCheckCallRaiseChance = got raise/bet after check
|
||||
streetXCheckCallRaiseDone = checked. got raise/bet. didn't fold
|
||||
|
||||
CG: CheckCall would be a much better name for this.
|
||||
"""
|
||||
#for i, street in enumerate(hand.actionStreets[2:], start=1):
|
||||
for i, street in enumerate(hand.actionStreets[2:]):
|
||||
actions = hand.actions[hand.actionStreets[i+1]]
|
||||
checkers = set()
|
||||
initial_raiser = None
|
||||
for action in actions:
|
||||
pname, act = action[0], action[1]
|
||||
if act in ('bets', 'raises') and initial_raiser is None:
|
||||
initial_raiser = pname
|
||||
elif act == 'checks' and initial_raiser is None:
|
||||
checkers.add(pname)
|
||||
elif initial_raiser is not None and pname in checkers:
|
||||
self.handsplayers[pname]['street%dCheckCallRaiseChance' % (i+1)] = True
|
||||
self.handsplayers[pname]['street%dCheckCallRaiseDone' % (i+1)] = act!='folds'
|
||||
|
||||
def seen(self, hand, i):
|
||||
pas = set()
|
||||
for act in hand.actions[hand.actionStreets[i+1]]:
|
||||
|
@ -293,11 +378,13 @@ class DerivedStats():
|
|||
|
||||
def aggr(self, hand, i):
|
||||
aggrers = set()
|
||||
for act in hand.actions[hand.actionStreets[i]]:
|
||||
if act[1] in ('completes', 'raises'):
|
||||
# Growl - actionStreets contains 'BLINDSANTES', which isn't actually an action street
|
||||
for act in hand.actions[hand.actionStreets[i+1]]:
|
||||
if act[1] in ('completes', 'bets', 'raises'):
|
||||
aggrers.add(act[0])
|
||||
|
||||
for player in hand.players:
|
||||
#print "DEBUG: actionStreet[%s]: %s" %(hand.actionStreets[i+1], i)
|
||||
if player[1] in aggrers:
|
||||
self.handsplayers[player[1]]['street%sAggr' % i] = True
|
||||
else:
|
||||
|
@ -333,6 +420,44 @@ class DerivedStats():
|
|||
players.add(action[0])
|
||||
return players
|
||||
|
||||
def pfbao(self, actions, f=None, l=None, unique=True):
|
||||
"""Helper method. Returns set of PlayersFilteredByActionsOrdered
|
||||
|
||||
f - forbidden actions
|
||||
l - limited to actions
|
||||
"""
|
||||
# Note, this is an adaptation of function 5 from:
|
||||
# http://www.peterbe.com/plog/uniqifiers-benchmark
|
||||
seen = {}
|
||||
players = []
|
||||
for action in actions:
|
||||
if l is not None and action[1] not in l: continue
|
||||
if f is not None and action[1] in f: continue
|
||||
if action[0] in seen and unique: continue
|
||||
seen[action[0]] = 1
|
||||
players.append(action[0])
|
||||
return players
|
||||
|
||||
def firstsBetOrRaiser(self, actions):
|
||||
"""Returns player name that placed the first bet or raise.
|
||||
|
||||
None if there were no bets or raises on that street
|
||||
"""
|
||||
for act in actions:
|
||||
if act[1] in ('bets', 'raises'):
|
||||
return act[0]
|
||||
return None
|
||||
|
||||
def lastBetOrRaiser(self, street):
|
||||
"""Returns player name that placed the last bet or raise for that street.
|
||||
None if there were no bets or raises on that street"""
|
||||
lastbet = None
|
||||
for act in self.hand.actions[street]:
|
||||
if act[1] in ('bets', 'raises'):
|
||||
lastbet = act[0]
|
||||
return lastbet
|
||||
|
||||
|
||||
def noBetsBefore(self, street, player):
|
||||
"""Returns true if there were no bets before the specified players turn, false otherwise"""
|
||||
betOrRaise = False
|
||||
|
@ -345,6 +470,7 @@ class DerivedStats():
|
|||
break
|
||||
return betOrRaise
|
||||
|
||||
|
||||
def betStreet(self, street, player):
|
||||
"""Returns true if player bet/raised the street as their first action"""
|
||||
betOrRaise = False
|
||||
|
@ -355,12 +481,3 @@ class DerivedStats():
|
|||
break
|
||||
return betOrRaise
|
||||
|
||||
|
||||
def lastBetOrRaiser(self, street):
|
||||
"""Returns player name that placed the last bet or raise for that street.
|
||||
None if there were no bets or raises on that street"""
|
||||
lastbet = None
|
||||
for act in self.hand.actions[street]:
|
||||
if act[1] in ('bets', 'raises'):
|
||||
lastbet = act[0]
|
||||
return lastbet
|
||||
|
|
|
@ -56,7 +56,7 @@ class Filters(threading.Thread):
|
|||
,'limitstitle':'Limits:', 'seatstitle':'Number of Players:'
|
||||
,'groupstitle':'Grouping:', 'posnshow':'Show Position Stats:'
|
||||
,'groupsall':'All Players'
|
||||
,'limitsFL':'FL', 'limitsNL':'NL', 'ring':'Ring', 'tour':'Tourney'
|
||||
,'limitsFL':'FL', 'limitsNL':'NL', 'limitsPL':'PL', 'ring':'Ring', 'tour':'Tourney'
|
||||
}
|
||||
|
||||
# For use in date ranges.
|
||||
|
@ -107,6 +107,7 @@ class Filters(threading.Thread):
|
|||
self.cbAllLimits = None
|
||||
self.cbFL = None
|
||||
self.cbNL = None
|
||||
self.cbPL = None
|
||||
self.rb = {} # radio buttons for ring/tour
|
||||
self.type = None # ring/tour
|
||||
self.types = {} # list of all ring/tour values
|
||||
|
@ -191,6 +192,9 @@ class Filters(threading.Thread):
|
|||
def getSites(self):
|
||||
return self.sites
|
||||
|
||||
def getGames(self):
|
||||
return self.games
|
||||
|
||||
def getSiteIds(self):
|
||||
return self.siteid
|
||||
|
||||
|
@ -303,7 +307,7 @@ class Filters(threading.Thread):
|
|||
#print w.get_active()
|
||||
self.limits[limit] = w.get_active()
|
||||
print "self.limit[%s] set to %s" %(limit, self.limits[limit])
|
||||
if limit.isdigit() or (len(limit) > 2 and limit[-2:] == 'nl'):
|
||||
if limit.isdigit() or (len(limit) > 2 and (limit[-2:] == 'nl' or limit[-2:] == 'fl' or limit[-2:] == 'pl')):
|
||||
if self.limits[limit]:
|
||||
if self.cbNoLimits is not None:
|
||||
self.cbNoLimits.set_active(False)
|
||||
|
@ -314,9 +318,12 @@ class Filters(threading.Thread):
|
|||
if limit.isdigit():
|
||||
if self.cbFL is not None:
|
||||
self.cbFL.set_active(False)
|
||||
else:
|
||||
elif (len(limit) > 2 and (limit[-2:] == 'nl')):
|
||||
if self.cbNL is not None:
|
||||
self.cbNL.set_active(False)
|
||||
else:
|
||||
if self.cbPL is not None:
|
||||
self.cbPL.set_active(False)
|
||||
elif limit == "all":
|
||||
if self.limits[limit]:
|
||||
#for cb in self.cbLimits.values():
|
||||
|
@ -325,6 +332,8 @@ class Filters(threading.Thread):
|
|||
self.cbFL.set_active(True)
|
||||
if self.cbNL is not None:
|
||||
self.cbNL.set_active(True)
|
||||
if self.cbPL is not None:
|
||||
self.cbPL.set_active(True)
|
||||
elif limit == "none":
|
||||
if self.limits[limit]:
|
||||
for cb in self.cbLimits.values():
|
||||
|
@ -333,6 +342,8 @@ class Filters(threading.Thread):
|
|||
self.cbNL.set_active(False)
|
||||
if self.cbFL is not None:
|
||||
self.cbFL.set_active(False)
|
||||
if self.cbPL is not None:
|
||||
self.cbPL.set_active(False)
|
||||
elif limit == "fl":
|
||||
if not self.limits[limit]:
|
||||
# only toggle all fl limits off if they are all currently on
|
||||
|
@ -384,6 +395,30 @@ class Filters(threading.Thread):
|
|||
self.rb['tour'].set_active(True)
|
||||
elif self.type == 'tour':
|
||||
self.rb['ring'].set_active(True)
|
||||
elif limit == "pl":
|
||||
if not self.limits[limit]:
|
||||
# only toggle all nl limits off if they are all currently on
|
||||
# this stops turning one off from cascading into 'nl' box off
|
||||
# and then all nl limits being turned off
|
||||
all_nl_on = True
|
||||
for cb in self.cbLimits.values():
|
||||
t = cb.get_children()[0].get_text()
|
||||
if "pl" in t and len(t) > 2:
|
||||
if not cb.get_active():
|
||||
all_nl_on = False
|
||||
found = {'ring':False, 'tour':False}
|
||||
for cb in self.cbLimits.values():
|
||||
t = cb.get_children()[0].get_text()
|
||||
if "pl" in t and len(t) > 2:
|
||||
if self.limits[limit] or all_nl_on:
|
||||
cb.set_active(self.limits[limit])
|
||||
found[self.types[t]] = True
|
||||
if self.limits[limit]:
|
||||
if not found[self.type]:
|
||||
if self.type == 'ring':
|
||||
self.rb['tour'].set_active(True)
|
||||
elif self.type == 'tour':
|
||||
self.rb['ring'].set_active(True)
|
||||
elif limit == "ring":
|
||||
print "set", limit, "to", self.limits[limit]
|
||||
if self.limits[limit]:
|
||||
|
@ -479,7 +514,7 @@ class Filters(threading.Thread):
|
|||
self.cursor.execute(self.sql.query['getLimits2'])
|
||||
# selects limitType, bigBlind
|
||||
result = self.db.cursor.fetchall()
|
||||
found = {'nl':False, 'fl':False, 'ring':False, 'tour':False}
|
||||
found = {'nl':False, 'fl':False, 'pl':False, 'ring':False, 'tour':False}
|
||||
|
||||
if len(result) >= 1:
|
||||
hbox = gtk.HBox(True, 0)
|
||||
|
@ -497,14 +532,18 @@ class Filters(threading.Thread):
|
|||
vbox2.pack_start(hbox, False, False, 0)
|
||||
else:
|
||||
vbox3.pack_start(hbox, False, False, 0)
|
||||
if line[1] == 'fl':
|
||||
name = str(line[2])
|
||||
found['fl'] = True
|
||||
else:
|
||||
name = str(line[2])+line[1]
|
||||
found['nl'] = True
|
||||
self.cbLimits[name] = self.createLimitLine(hbox, name, name)
|
||||
self.types[name] = line[0]
|
||||
if line[0] == 'ring':
|
||||
if line[1] == 'fl':
|
||||
name = str(line[2])
|
||||
found['fl'] = True
|
||||
elif line[1] == 'pl':
|
||||
name = str(line[2])+line[1]
|
||||
found['pl'] = True
|
||||
else:
|
||||
name = str(line[2])+line[1]
|
||||
found['nl'] = True
|
||||
self.cbLimits[name] = self.createLimitLine(hbox, name, name)
|
||||
self.types[name] = line[0]
|
||||
found[line[0]] = True # type is ring/tour
|
||||
self.type = line[0] # if only one type, set it now
|
||||
if "LimitSep" in display and display["LimitSep"] == True and len(result) >= 2:
|
||||
|
@ -532,6 +571,9 @@ class Filters(threading.Thread):
|
|||
hbox = gtk.HBox(False, 0)
|
||||
vbox3.pack_start(hbox, False, False, 0)
|
||||
self.cbNL = self.createLimitLine(hbox, 'nl', self.filterText['limitsNL'])
|
||||
hbox = gtk.HBox(False, 0)
|
||||
vbox3.pack_start(hbox, False, False, 0)
|
||||
self.cbPL = self.createLimitLine(hbox, 'pl', self.filterText['limitsPL'])
|
||||
dest = vbox2 # for ring/tour buttons
|
||||
else:
|
||||
print "INFO: No games returned from database"
|
||||
|
|
|
@ -30,7 +30,6 @@ import gtk
|
|||
import gobject
|
||||
|
||||
# fpdb/FreePokerTools modules
|
||||
import fpdb_simple
|
||||
import fpdb_import
|
||||
import Configuration
|
||||
import Exceptions
|
||||
|
|
|
@ -64,7 +64,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
|
||||
filters_display = { "Heroes" : True,
|
||||
"Sites" : True,
|
||||
"Games" : False,
|
||||
"Games" : True,
|
||||
"Limits" : True,
|
||||
"LimitSep" : True,
|
||||
"LimitType" : True,
|
||||
|
@ -180,6 +180,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
seats = self.filters.getSeats()
|
||||
groups = self.filters.getGroups()
|
||||
dates = self.filters.getDates()
|
||||
games = self.filters.getGames()
|
||||
sitenos = []
|
||||
playerids = []
|
||||
|
||||
|
@ -205,9 +206,9 @@ class GuiPlayerStats (threading.Thread):
|
|||
print "No limits found"
|
||||
return
|
||||
|
||||
self.createStatsTable(vbox, playerids, sitenos, limits, type, seats, groups, dates)
|
||||
self.createStatsTable(vbox, playerids, sitenos, limits, type, seats, groups, dates, games)
|
||||
|
||||
def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates):
|
||||
def createStatsTable(self, vbox, playerids, sitenos, limits, type, seats, groups, dates, games):
|
||||
starttime = time()
|
||||
|
||||
# Scrolled window for summary table
|
||||
|
@ -223,7 +224,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
# gridnum - index for grid data structures
|
||||
flags = [False, self.filters.getNumHands(), 0]
|
||||
self.addGrid(swin, 'playerDetailedStats', flags, playerids
|
||||
,sitenos, limits, type, seats, groups, dates)
|
||||
,sitenos, limits, type, seats, groups, dates, games)
|
||||
|
||||
# Separator
|
||||
vbox2 = gtk.VBox(False, 0)
|
||||
|
@ -243,7 +244,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
flags[0] = True
|
||||
flags[2] = 1
|
||||
self.addGrid(swin, 'playerDetailedStats', flags, playerids
|
||||
,sitenos, limits, type, seats, groups, dates)
|
||||
,sitenos, limits, type, seats, groups, dates, games)
|
||||
|
||||
self.db.rollback()
|
||||
print "Stats page displayed in %4.2f seconds" % (time() - starttime)
|
||||
|
@ -317,7 +318,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
print "***sortcols error: " + str(sys.exc_info()[1])
|
||||
print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] )
|
||||
|
||||
def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates):
|
||||
def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games):
|
||||
counter = 0
|
||||
row = 0
|
||||
sqlrow = 0
|
||||
|
@ -325,7 +326,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
else: holecards,grid = flags[0],flags[2]
|
||||
|
||||
tmp = self.sql.query[query]
|
||||
tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates)
|
||||
tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates, games)
|
||||
self.cursor.execute(tmp)
|
||||
result = self.cursor.fetchall()
|
||||
colnames = [desc[0].lower() for desc in self.cursor.description]
|
||||
|
@ -428,7 +429,7 @@ class GuiPlayerStats (threading.Thread):
|
|||
|
||||
#end def addGrid(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates):
|
||||
|
||||
def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates):
|
||||
def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates, games):
|
||||
having = ''
|
||||
if not flags:
|
||||
holecards = False
|
||||
|
@ -466,6 +467,20 @@ class GuiPlayerStats (threading.Thread):
|
|||
query = query.replace("<playerName>", pname)
|
||||
query = query.replace("<havingclause>", having)
|
||||
|
||||
gametest = ""
|
||||
q = []
|
||||
for m in self.filters.display.items():
|
||||
if m[0] == 'Games' and m[1]:
|
||||
for n in games:
|
||||
if games[n]:
|
||||
q.append(n)
|
||||
gametest = str(tuple(q))
|
||||
gametest = gametest.replace("L", "")
|
||||
gametest = gametest.replace(",)",")")
|
||||
gametest = gametest.replace("u'","'")
|
||||
gametest = "and gt.category in %s" % gametest
|
||||
query = query.replace("<game_test>", gametest)
|
||||
|
||||
if seats:
|
||||
query = query.replace('<seats_test>', 'between ' + str(seats['from']) + ' and ' + str(seats['to']))
|
||||
if 'show' in seats and seats['show']:
|
||||
|
@ -516,8 +531,8 @@ class GuiPlayerStats (threading.Thread):
|
|||
if holecards: # re-use level variables for hole card query
|
||||
query = query.replace("<hgameTypeId>", "hp.startcards")
|
||||
query = query.replace("<orderbyhgameTypeId>"
|
||||
, ",case when floor(hp.startcards/13) >= mod(hp.startcards,13) then hp.startcards + 0.1 "
|
||||
+ " else 13*mod(hp.startcards,13) + floor(hp.startcards/13) "
|
||||
, ",case when floor((hp.startcards-1)/13) >= mod((hp.startcards-1),13) then hp.startcards + 0.1 "
|
||||
+ " else 13*mod((hp.startcards-1),13) + floor((hp.startcards-1)/13) + 1 "
|
||||
+ " end desc ")
|
||||
else:
|
||||
query = query.replace("<orderbyhgameTypeId>", "")
|
||||
|
|
|
@ -20,7 +20,6 @@ import pygtk
|
|||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import os
|
||||
import fpdb_simple
|
||||
|
||||
import fpdb_import
|
||||
import fpdb_db
|
||||
|
|
|
@ -232,6 +232,9 @@ db: a connected fpdb_db object"""
|
|||
#Raise Duplicate exception?
|
||||
pass
|
||||
|
||||
def updateHudCache(self, db):
|
||||
db.storeHudCache(self.dbid_gt, self.dbid_pids, self.starttime, self.stats.getHandsPlayers())
|
||||
|
||||
def select(self, handId):
|
||||
""" Function to create Hand object from database """
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ follow : whether to tail -f the input"""
|
|||
|
||||
log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) )
|
||||
|
||||
self.index = 0
|
||||
self.index = index
|
||||
self.starsArchive = starsArchive
|
||||
|
||||
self.in_path = in_path
|
||||
|
|
|
@ -606,6 +606,7 @@ class Hud:
|
|||
if self.update_table_position() == False: # we got killed by finding our table was gone
|
||||
return
|
||||
|
||||
self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
|
||||
for s in self.stat_dict:
|
||||
try:
|
||||
statd = self.stat_dict[s]
|
||||
|
@ -629,20 +630,16 @@ class Hud:
|
|||
window = self.stat_windows[statd['seat']]
|
||||
|
||||
if this_stat.hudcolor != "":
|
||||
self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
|
||||
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor))
|
||||
else:
|
||||
self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
|
||||
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#FFFFFF"))
|
||||
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
|
||||
|
||||
if this_stat.stat_loth != "":
|
||||
if number[0] < (float(this_stat.stat_loth)/100):
|
||||
self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
|
||||
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_locolor))
|
||||
|
||||
if this_stat.stat_hith != "":
|
||||
if number[0] > (float(this_stat.stat_hith)/100):
|
||||
self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
|
||||
window.label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.stat_hicolor))
|
||||
|
||||
window.label[r][c].set_text(statstring)
|
||||
|
|
|
@ -81,6 +81,7 @@ class PokerStars(HandHistoryConverter):
|
|||
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
|
||||
# self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')
|
||||
|
||||
re_DateTime = re.compile("""(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)""", re.MULTILINE)
|
||||
|
||||
def compilePlayerRegexs(self, hand):
|
||||
players = set([player[1] for player in hand.players])
|
||||
|
@ -97,7 +98,7 @@ class PokerStars(HandHistoryConverter):
|
|||
self.re_PostBB = re.compile(r"^%(PLYR)s: posts big blind %(CUR)s(?P<BB>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P<ANTE>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for %(CUR)s(?P<BRINGIN>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(r"^%(PLYR)s: posts small \& big blinds \[%(CUR)s (?P<SBBB>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_PostBoth = re.compile(r"^%(PLYR)s: posts small \& big blinds %(CUR)s(?P<SBBB>[.0-9]+)" % subst, re.MULTILINE)
|
||||
self.re_HeroCards = re.compile(r"^Dealt to %(PLYR)s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % subst, re.MULTILINE)
|
||||
self.re_Action = re.compile(r"""
|
||||
^%(PLYR)s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat)
|
||||
|
@ -105,7 +106,7 @@ class PokerStars(HandHistoryConverter):
|
|||
(\scards?(\s\[(?P<DISCARDED>.+?)\])?)?"""
|
||||
% subst, re.MULTILINE|re.VERBOSE)
|
||||
self.re_ShowdownAction = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" % player_re, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): %(PLYR)s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(%(CUR)s(?P<POT>[.\d]+)\)(, mucked| with.*|)" % subst, re.MULTILINE)
|
||||
self.re_CollectPot = re.compile(r"Seat (?P<SEAT>[0-9]+): %(PLYR)s (\(button\) |\(small blind\) |\(big blind\) |\(button\) \(small blind\) )?(collected|showed \[.*\] and won) \(%(CUR)s(?P<POT>[.\d]+)\)(, mucked| with.*|)" % subst, re.MULTILINE)
|
||||
self.re_sitsOut = re.compile("^%s sits out" % player_re, re.MULTILINE)
|
||||
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" % player_re, re.MULTILINE)
|
||||
|
||||
|
@ -194,12 +195,13 @@ class PokerStars(HandHistoryConverter):
|
|||
#2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]
|
||||
#2008/08/17 - 01:14:43 (ET)
|
||||
#2008/09/07 06:23:14 ET
|
||||
m2 = re.search("(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)", info[key])
|
||||
datetimestr = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'),m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S'))
|
||||
m1 = self.re_DateTime.finditer(info[key])
|
||||
# m2 = re.search("(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)", info[key])
|
||||
for a in m1:
|
||||
datetimestr = "%s/%s/%s %s:%s:%s" % (a.group('Y'), a.group('M'),a.group('D'),a.group('H'),a.group('MIN'),a.group('S'))
|
||||
hand.starttime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
|
||||
if key == 'HID':
|
||||
hand.handid = info[key]
|
||||
|
||||
if key == 'TOURNO':
|
||||
hand.tourNo = info[key]
|
||||
if key == 'BUYIN':
|
||||
|
|
144
pyfpdb/SQL.py
144
pyfpdb/SQL.py
|
@ -1881,6 +1881,7 @@ class Sql:
|
|||
inner join Sites s on (s.Id = gt.siteId)
|
||||
inner join Players p on (p.Id = hp.playerId)
|
||||
where hp.playerId in <player_test>
|
||||
<game_test>
|
||||
/*and hp.tourneysPlayersId IS NULL*/
|
||||
and h.seats <seats_test>
|
||||
<flagtest>
|
||||
|
@ -1964,6 +1965,7 @@ class Sql:
|
|||
inner join Sites s on (s.Id = gt.siteId)
|
||||
inner join Players p on (p.Id = hp.playerId)
|
||||
where hp.playerId in <player_test>
|
||||
<game_test>
|
||||
/*and hp.tourneysPlayersId IS NULL*/
|
||||
and h.seats <seats_test>
|
||||
<flagtest>
|
||||
|
@ -2047,6 +2049,7 @@ class Sql:
|
|||
inner join Gametypes gt on (gt.Id = h.gameTypeId)
|
||||
inner join Sites s on (s.Id = gt.siteId)
|
||||
where hp.playerId in <player_test>
|
||||
<game_test>
|
||||
/*and hp.tourneysPlayersId IS NULL*/
|
||||
and h.seats <seats_test>
|
||||
<flagtest>
|
||||
|
@ -3088,6 +3091,147 @@ class Sql:
|
|||
,'d' || substr(strftime('%Y%m%d', h.handStart),3,7)
|
||||
"""
|
||||
|
||||
self.query['insert_hudcache'] = """
|
||||
INSERT INTO HudCache (
|
||||
gametypeId,
|
||||
playerId,
|
||||
activeSeats,
|
||||
position,
|
||||
tourneyTypeId,
|
||||
styleKey,
|
||||
HDs,
|
||||
street0VPI,
|
||||
street0Aggr,
|
||||
street0_3BChance,
|
||||
street0_3BDone,
|
||||
street1Seen,
|
||||
street2Seen,
|
||||
street3Seen,
|
||||
street4Seen,
|
||||
sawShowdown,
|
||||
street1Aggr,
|
||||
street2Aggr,
|
||||
street3Aggr,
|
||||
street4Aggr,
|
||||
otherRaisedStreet1,
|
||||
otherRaisedStreet2,
|
||||
otherRaisedStreet3,
|
||||
otherRaisedStreet4,
|
||||
foldToOtherRaisedStreet1,
|
||||
foldToOtherRaisedStreet2,
|
||||
foldToOtherRaisedStreet3,
|
||||
foldToOtherRaisedStreet4,
|
||||
wonWhenSeenStreet1,
|
||||
wonAtSD,
|
||||
stealAttemptChance,
|
||||
stealAttempted,
|
||||
foldBbToStealChance,
|
||||
foldedBbToSteal,
|
||||
foldSbToStealChance,
|
||||
foldedSbToSteal,
|
||||
street1CBChance,
|
||||
street1CBDone,
|
||||
street2CBChance,
|
||||
street2CBDone,
|
||||
street3CBChance,
|
||||
street3CBDone,
|
||||
street4CBChance,
|
||||
street4CBDone,
|
||||
foldToStreet1CBChance,
|
||||
foldToStreet1CBDone,
|
||||
foldToStreet2CBChance,
|
||||
foldToStreet2CBDone,
|
||||
foldToStreet3CBChance,
|
||||
foldToStreet3CBDone,
|
||||
foldToStreet4CBChance,
|
||||
foldToStreet4CBDone,
|
||||
totalProfit,
|
||||
street1CheckCallRaiseChance,
|
||||
street1CheckCallRaiseDone,
|
||||
street2CheckCallRaiseChance,
|
||||
street2CheckCallRaiseDone,
|
||||
street3CheckCallRaiseChance,
|
||||
street3CheckCallRaiseDone,
|
||||
street4CheckCallRaiseChance,
|
||||
street4CheckCallRaiseDone)
|
||||
VALUES (%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s,
|
||||
%s)"""
|
||||
|
||||
self.query['update_hudcache'] = """
|
||||
UPDATE HudCache SET
|
||||
HDs=HDs+%s,
|
||||
street0VPI=street0VPI+%s,
|
||||
street0Aggr=street0Aggr+%s,
|
||||
street0_3BChance=street0_3BChance+%s,
|
||||
street0_3BDone=street0_3BDone+%s,
|
||||
street1Seen=street1Seen+%s,
|
||||
street2Seen=street2Seen+%s,
|
||||
street3Seen=street3Seen+%s,
|
||||
street4Seen=street4Seen+%s,
|
||||
sawShowdown=sawShowdown+%s,
|
||||
street1Aggr=street1Aggr+%s,
|
||||
street2Aggr=street2Aggr+%s,
|
||||
street3Aggr=street3Aggr+%s,
|
||||
street4Aggr=street4Aggr+%s,
|
||||
otherRaisedStreet1=otherRaisedStreet1+%s,
|
||||
otherRaisedStreet2=otherRaisedStreet2+%s,
|
||||
otherRaisedStreet3=otherRaisedStreet3+%s,
|
||||
otherRaisedStreet4=otherRaisedStreet4+%s,
|
||||
foldToOtherRaisedStreet1=foldToOtherRaisedStreet1+%s,
|
||||
foldToOtherRaisedStreet2=foldToOtherRaisedStreet2+%s,
|
||||
foldToOtherRaisedStreet3=foldToOtherRaisedStreet3+%s,
|
||||
foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s,
|
||||
wonWhenSeenStreet1=wonWhenSeenStreet1+%s,
|
||||
wonAtSD=wonAtSD+%s,
|
||||
stealAttemptChance=stealAttemptChance+%s,
|
||||
stealAttempted=stealAttempted+%s,
|
||||
foldBbToStealChance=foldBbToStealChance+%s,
|
||||
foldedBbToSteal=foldedBbToSteal+%s,
|
||||
foldSbToStealChance=foldSbToStealChance+%s,
|
||||
foldedSbToSteal=foldedSbToSteal+%s,
|
||||
street1CBChance=street1CBChance+%s,
|
||||
street1CBDone=street1CBDone+%s,
|
||||
street2CBChance=street2CBChance+%s,
|
||||
street2CBDone=street2CBDone+%s,
|
||||
street3CBChance=street3CBChance+%s,
|
||||
street3CBDone=street3CBDone+%s,
|
||||
street4CBChance=street4CBChance+%s,
|
||||
street4CBDone=street4CBDone+%s,
|
||||
foldToStreet1CBChance=foldToStreet1CBChance+%s,
|
||||
foldToStreet1CBDone=foldToStreet1CBDone+%s,
|
||||
foldToStreet2CBChance=foldToStreet2CBChance+%s,
|
||||
foldToStreet2CBDone=foldToStreet2CBDone+%s,
|
||||
foldToStreet3CBChance=foldToStreet3CBChance+%s,
|
||||
foldToStreet3CBDone=foldToStreet3CBDone+%s,
|
||||
foldToStreet4CBChance=foldToStreet4CBChance+%s,
|
||||
foldToStreet4CBDone=foldToStreet4CBDone+%s,
|
||||
totalProfit=totalProfit+%s,
|
||||
street1CheckCallRaiseChance=street1CheckCallRaiseChance+%s,
|
||||
street1CheckCallRaiseDone=street1CheckCallRaiseDone+%s,
|
||||
street2CheckCallRaiseChance=street2CheckCallRaiseChance+%s,
|
||||
street2CheckCallRaiseDone=street2CheckCallRaiseDone+%s,
|
||||
street3CheckCallRaiseChance=street3CheckCallRaiseChance+%s,
|
||||
street3CheckCallRaiseDone=street3CheckCallRaiseDone+%s,
|
||||
street4CheckCallRaiseChance=street4CheckCallRaiseChance+%s,
|
||||
street4CheckCallRaiseDone=street4CheckCallRaiseDone+%s
|
||||
WHERE gametypeId+0=%s
|
||||
AND playerId=%s
|
||||
AND activeSeats=%s
|
||||
AND position=%s
|
||||
AND tourneyTypeId+0=%s
|
||||
AND styleKey=%s"""
|
||||
|
||||
self.query['get_hero_hudcache_start'] = """select min(hc.styleKey)
|
||||
from HudCache hc
|
||||
where hc.playerId in <playerid_list>
|
||||
|
|
|
@ -62,9 +62,13 @@ import Database
|
|||
re_Places = re.compile("_[0-9]$")
|
||||
re_Percent = re.compile("%$")
|
||||
|
||||
# String manipulation
|
||||
import codecs
|
||||
encoder = codecs.lookup(Configuration.LOCALE_ENCODING)
|
||||
|
||||
def do_tip(widget, tip):
|
||||
widget.set_tooltip_text(tip)
|
||||
(_tip, _len) = encoder.encode(tip)
|
||||
widget.set_tooltip_text(_tip)
|
||||
|
||||
def do_stat(stat_dict, player = 24, stat = 'vpip'):
|
||||
match = re_Places.search(stat)
|
||||
|
|
|
@ -39,7 +39,6 @@ if os.name == 'nt':
|
|||
|
||||
# FreePokerTools modules
|
||||
import Configuration
|
||||
from fpdb_simple import LOCALE_ENCODING
|
||||
|
||||
# Each TableWindow object must have the following attributes correctly populated:
|
||||
# tw.name = the table name from the title bar, which must to match the table name
|
||||
|
@ -238,7 +237,7 @@ def discover_nt_by_name(c, tablename):
|
|||
try:
|
||||
# maybe it's better to make global titles[hwnd] decoding?
|
||||
# this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html
|
||||
if not tablename.lower() in titles[hwnd].decode(LOCALE_ENCODING).lower():
|
||||
if not tablename.lower() in titles[hwnd].decode(Configuration.LOCALE_ENCODING).lower():
|
||||
continue
|
||||
except:
|
||||
continue
|
||||
|
|
|
@ -38,7 +38,6 @@ except ImportError:
|
|||
logging.info("Not using numpy to define variance in sqlite.")
|
||||
use_numpy = False
|
||||
|
||||
import fpdb_simple
|
||||
import FpdbSQLQueries
|
||||
import Configuration
|
||||
|
||||
|
|
|
@ -35,10 +35,8 @@ import gtk
|
|||
|
||||
# fpdb/FreePokerTools modules
|
||||
|
||||
import fpdb_simple
|
||||
import fpdb_db
|
||||
import Database
|
||||
import fpdb_parse_logic
|
||||
import Configuration
|
||||
import Exceptions
|
||||
|
||||
|
@ -409,7 +407,7 @@ class Importer:
|
|||
conv = None
|
||||
(stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0)
|
||||
|
||||
file = file.decode(fpdb_simple.LOCALE_ENCODING)
|
||||
file = file.decode(Configuration.LOCALE_ENCODING)
|
||||
|
||||
# Load filter, process file, pass returned filename to import_fpdb_file
|
||||
if self.settings['threads'] > 0 and self.writeq is not None:
|
||||
|
@ -429,11 +427,13 @@ class Importer:
|
|||
mod = __import__(filter)
|
||||
obj = getattr(mod, filter_name, None)
|
||||
if callable(obj):
|
||||
hhc = obj(in_path = file, out_path = out_path, index = 0, starsArchive = self.settings['starsArchive']) # Index into file 0 until changeover
|
||||
if hhc.getStatus() and self.NEWIMPORT == False:
|
||||
(stored, duplicates, partial, errors, ttime) = self.import_fpdb_file(db, out_path, site, q)
|
||||
elif hhc.getStatus() and self.NEWIMPORT == True:
|
||||
#This code doesn't do anything yet
|
||||
idx = 0
|
||||
if file in self.pos_in_file:
|
||||
idx = self.pos_in_file[file]
|
||||
else:
|
||||
self.pos_in_file[file] = 0
|
||||
hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive'])
|
||||
if hhc.getStatus() and self.NEWIMPORT == True:
|
||||
handlist = hhc.getProcessedHands()
|
||||
self.pos_in_file[file] = hhc.getLastCharacterRead()
|
||||
to_hud = []
|
||||
|
@ -448,6 +448,11 @@ class Importer:
|
|||
else:
|
||||
log.error("Hand processed but empty")
|
||||
self.database.commit()
|
||||
# Call hudcache update if not in bulk import mode
|
||||
# FIXME: Need to test for bulk import that isn't rebuilding the cache
|
||||
if self.callHud:
|
||||
hand.updateHudCache(self.database)
|
||||
self.database.commit()
|
||||
|
||||
#pipe the Hands.id out to the HUD
|
||||
for hid in to_hud:
|
||||
|
@ -468,162 +473,6 @@ class Importer:
|
|||
return (stored, duplicates, partial, errors, ttime)
|
||||
|
||||
|
||||
def import_fpdb_file(self, db, file, site, q):
|
||||
starttime = time()
|
||||
last_read_hand = 0
|
||||
loc = 0
|
||||
(stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0)
|
||||
# print "file =", file
|
||||
if file == "stdin":
|
||||
inputFile = sys.stdin
|
||||
else:
|
||||
if os.path.exists(file):
|
||||
inputFile = open(file, "rU")
|
||||
else:
|
||||
self.removeFromFileList[file] = True
|
||||
return (0, 0, 0, 1, 0)
|
||||
try:
|
||||
loc = self.pos_in_file[file]
|
||||
#size = os.path.getsize(file)
|
||||
#print "loc =", loc, 'size =', size
|
||||
except KeyError:
|
||||
pass
|
||||
# Read input file into class and close file
|
||||
inputFile.seek(loc)
|
||||
#tmplines = inputFile.readlines()
|
||||
#if tmplines == None or tmplines == []:
|
||||
# print "tmplines = ", tmplines
|
||||
#else:
|
||||
# print "tmplines[0] =", tmplines[0]
|
||||
self.lines = fpdb_simple.removeTrailingEOL(inputFile.readlines())
|
||||
self.pos_in_file[file] = inputFile.tell()
|
||||
inputFile.close()
|
||||
|
||||
x = clock()
|
||||
(stored, duplicates, partial, errors, ttime, handsId) = self.import_fpdb_lines(db, self.lines, starttime, file, site, q)
|
||||
|
||||
db.commit()
|
||||
y = clock()
|
||||
ttime = y - x
|
||||
#ttime = time() - starttime
|
||||
if q is None:
|
||||
log.info("Total stored: %(stored)d\tduplicates:%(duplicates)d\terrors:%(errors)d\ttime:%(ttime)s" % locals())
|
||||
|
||||
if not stored:
|
||||
if duplicates:
|
||||
for line_no in xrange(len(self.lines)):
|
||||
if self.lines[line_no].find("Game #") != -1:
|
||||
final_game_line = self.lines[line_no]
|
||||
handsId=fpdb_simple.parseSiteHandNo(final_game_line)
|
||||
else:
|
||||
print "failed to read a single hand from file:", inputFile
|
||||
handsId = 0
|
||||
#todo: this will cause return of an unstored hand number if the last hand was error
|
||||
self.handsId = handsId
|
||||
|
||||
return (stored, duplicates, partial, errors, ttime)
|
||||
# end def import_fpdb_file
|
||||
|
||||
|
||||
def import_fpdb_lines(self, db, lines, starttime, file, site, q = None):
|
||||
"""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??
|
||||
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.
|
||||
firstline = lines[0]
|
||||
except:
|
||||
# just skip the debug message and return silently:
|
||||
#print "DEBUG: import_fpdb_file: failed on lines[0]: '%s' '%s' '%s' '%s' " %( file, site, lines, loc)
|
||||
return (0,0,0,1,0,0)
|
||||
|
||||
if "Tournament Summary" in firstline:
|
||||
print "TODO: implement importing tournament summaries"
|
||||
#self.faobs = readfile(inputFile)
|
||||
#self.parseTourneyHistory()
|
||||
return (0,0,0,1,0,0)
|
||||
|
||||
category = fpdb_simple.recogniseCategory(firstline)
|
||||
|
||||
startpos = 0
|
||||
stored = 0 #counter
|
||||
duplicates = 0 #counter
|
||||
partial = 0 #counter
|
||||
errors = 0 #counter
|
||||
ttime = 0
|
||||
handsId = 0
|
||||
|
||||
for i in xrange(len(lines)):
|
||||
if len(lines[i]) < 2: #Wierd way to detect for '\r\n' or '\n'
|
||||
endpos = i
|
||||
hand = lines[startpos:endpos]
|
||||
|
||||
if len(hand[0]) < 2:
|
||||
hand=hand[1:]
|
||||
|
||||
if len(hand) < 3:
|
||||
pass
|
||||
#TODO: This is ugly - we didn't actually find the start of the
|
||||
# hand with the outer loop so we test again...
|
||||
else:
|
||||
isTourney = fpdb_simple.isTourney(hand[0])
|
||||
if not isTourney:
|
||||
hand = fpdb_simple.filterAnteBlindFold(hand)
|
||||
self.hand = hand
|
||||
|
||||
try:
|
||||
handsId = fpdb_parse_logic.mainParser( self.settings, self.siteIds[site]
|
||||
, category, hand, self.config
|
||||
, db, q )
|
||||
db.commit()
|
||||
|
||||
stored += 1
|
||||
if self.callHud:
|
||||
#print "call to HUD here. handsId:",handsId
|
||||
#pipe the Hands.id out to the HUD
|
||||
# print "fpdb_import: sending hand to hud", handsId, "pipe =", self.caller.pipe_to_hud
|
||||
try:
|
||||
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
|
||||
except IOError: # hud closed
|
||||
self.callHud = False
|
||||
pass # continue import without hud
|
||||
except Exceptions.DuplicateError:
|
||||
duplicates += 1
|
||||
db.rollback()
|
||||
except (ValueError), fe:
|
||||
errors += 1
|
||||
self.printEmailErrorMessage(errors, file, hand)
|
||||
|
||||
if (self.settings['failOnError']):
|
||||
db.commit() #dont remove this, in case hand processing was cancelled.
|
||||
raise
|
||||
else:
|
||||
db.rollback()
|
||||
except (fpdb_simple.FpdbError), fe:
|
||||
errors += 1
|
||||
self.printEmailErrorMessage(errors, file, hand)
|
||||
db.rollback()
|
||||
|
||||
if self.settings['failOnError']:
|
||||
db.commit() #dont remove this, in case hand processing was cancelled.
|
||||
raise
|
||||
|
||||
if self.settings['minPrint']:
|
||||
if not ((stored+duplicates+errors) % self.settings['minPrint']):
|
||||
print "stored:", stored, " duplicates:", duplicates, "errors:", errors
|
||||
|
||||
if self.settings['handCount']:
|
||||
if ((stored+duplicates+errors) >= self.settings['handCount']):
|
||||
if not self.settings['quiet']:
|
||||
print "quitting due to reaching the amount of hands to be imported"
|
||||
print "Total stored:", stored, "duplicates:", duplicates, "errors:", errors, " time:", (time() - starttime)
|
||||
sys.exit(0)
|
||||
startpos = endpos
|
||||
return (stored, duplicates, partial, errors, ttime, handsId)
|
||||
# end def import_fpdb_lines
|
||||
|
||||
def printEmailErrorMessage(self, errors, filename, line):
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it."
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
#Copyright 2008 Steffen Jobbagy-Felso
|
||||
#This program is free software: you can redistribute it and/or modify
|
||||
#it under the terms of the GNU Affero General Public License as published by
|
||||
#the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
#This program is distributed in the hope that it will be useful,
|
||||
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#GNU General Public License for more details.
|
||||
#
|
||||
#You should have received a copy of the GNU Affero General Public License
|
||||
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#In the "official" distribution you can find the license in
|
||||
#agpl-3.0.txt in the docs folder of the package.
|
||||
|
||||
#parses an in-memory fpdb hand history and calls db routine to store it
|
||||
|
||||
import sys
|
||||
from time import time, strftime
|
||||
from Exceptions import *
|
||||
|
||||
import fpdb_simple
|
||||
import Database
|
||||
|
||||
def mainParser(settings, siteID, category, hand, config, db = None, writeq = None):
|
||||
""" mainParser for Holdem Hands """
|
||||
t0 = time()
|
||||
backend = settings['db-backend']
|
||||
# Ideally db connection is passed in, if not use sql list if passed in,
|
||||
# otherwise start from scratch
|
||||
if db is None:
|
||||
db = Database.Database(c = config, sql = None)
|
||||
category = fpdb_simple.recogniseCategory(hand[0])
|
||||
|
||||
base = "hold" if (category == "holdem" or category == "omahahi" or
|
||||
category == "omahahilo") else "stud"
|
||||
|
||||
#part 0: create the empty arrays
|
||||
# lineTypes valid values: header, name, cards, action, win, rake, ignore
|
||||
# lineStreets valid values: predeal, preflop, flop, turn, river
|
||||
lineTypes = []
|
||||
lineStreets = []
|
||||
cardValues = []
|
||||
cardSuits = []
|
||||
boardValues = []
|
||||
boardSuits = []
|
||||
antes = []
|
||||
allIns = []
|
||||
actionAmounts = []
|
||||
actionNos = []
|
||||
actionTypes = []
|
||||
actionTypeByNo = []
|
||||
seatLines = []
|
||||
winnings = []
|
||||
rakes = []
|
||||
|
||||
#part 1: read hand no and check for duplicate
|
||||
siteHandNo = fpdb_simple.parseSiteHandNo(hand[0])
|
||||
handStartTime = fpdb_simple.parseHandStartTime(hand[0])
|
||||
isTourney = fpdb_simple.isTourney(hand[0])
|
||||
|
||||
smallBlindLine = None
|
||||
for i, line in enumerate(hand):
|
||||
if 'posts small blind' in line or 'posts the small blind' in line:
|
||||
if line[-2:] == "$0": continue
|
||||
smallBlindLine = i
|
||||
break
|
||||
else:
|
||||
smallBlindLine = 0
|
||||
# If we did not find a small blind line, what happens?
|
||||
# if we leave it at None, it errors two lines down.
|
||||
|
||||
gametypeID = fpdb_simple.recogniseGametypeID(backend, db, db.get_cursor(),
|
||||
hand[0], hand[smallBlindLine],
|
||||
siteID, category, isTourney)
|
||||
if isTourney:
|
||||
siteTourneyNo = fpdb_simple.parseTourneyNo(hand[0])
|
||||
buyin = fpdb_simple.parseBuyin(hand[0])
|
||||
fee = fpdb_simple.parseFee(hand[0])
|
||||
entries = -1 #todo: parse this
|
||||
prizepool = -1 #todo: parse this
|
||||
knockout = False
|
||||
tourneyStartTime= handStartTime #todo: read tourney start time
|
||||
rebuyOrAddon = fpdb_simple.isRebuyOrAddon(hand[0])
|
||||
|
||||
# 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:
|
||||
siteTourneyNo = -1
|
||||
buyin = -1
|
||||
fee = -1
|
||||
entries = -1
|
||||
prizepool = -1
|
||||
knockout = 0
|
||||
tourneyStartTime= None
|
||||
rebuyOrAddon = -1
|
||||
|
||||
tourneyTypeId = 1
|
||||
fpdb_simple.isAlreadyInDB(db, gametypeID, siteHandNo)
|
||||
|
||||
hand = fpdb_simple.filterCrap(hand, isTourney)
|
||||
|
||||
#part 2: classify lines by type (e.g. cards, action, win, sectionchange) and street
|
||||
fpdb_simple.classifyLines(hand, category, lineTypes, lineStreets)
|
||||
|
||||
#part 3: read basic player info
|
||||
#3a read player names, startcashes
|
||||
for i, line in enumerate(hand):
|
||||
if lineTypes[i] == "name":
|
||||
seatLines.append(line)
|
||||
|
||||
names = fpdb_simple.parseNames(seatLines)
|
||||
playerIDs = db.recognisePlayerIDs(names, siteID) # inserts players as needed
|
||||
tmp = fpdb_simple.parseCashesAndSeatNos(seatLines)
|
||||
startCashes = tmp['startCashes']
|
||||
seatNos = tmp['seatNos']
|
||||
|
||||
fpdb_simple.createArrays(category, len(names), cardValues, cardSuits, antes,
|
||||
winnings, rakes, actionTypes, allIns,
|
||||
actionAmounts, actionNos, actionTypeByNo)
|
||||
|
||||
#3b read positions
|
||||
if base == "hold":
|
||||
positions = fpdb_simple.parsePositions(hand, names)
|
||||
|
||||
#part 4: take appropriate action for each line based on linetype
|
||||
for i, line in enumerate(hand):
|
||||
if lineTypes[i] == "cards":
|
||||
fpdb_simple.parseCardLine(category, lineStreets[i], line, names,
|
||||
cardValues, cardSuits, boardValues,
|
||||
boardSuits)
|
||||
#if category=="studhilo":
|
||||
# print "hand[i]:", hand[i]
|
||||
# print "cardValues:", cardValues
|
||||
# print "cardSuits:", cardSuits
|
||||
elif lineTypes[i] == "action":
|
||||
fpdb_simple.parseActionLine(base, isTourney, line, lineStreets[i],
|
||||
playerIDs, names, actionTypes, allIns,
|
||||
actionAmounts, actionNos, actionTypeByNo)
|
||||
elif lineTypes[i] == "win":
|
||||
fpdb_simple.parseWinLine(line, names, winnings, isTourney)
|
||||
elif lineTypes[i] == "rake":
|
||||
totalRake = 0 if isTourney else fpdb_simple.parseRake(line)
|
||||
fpdb_simple.splitRake(winnings, rakes, totalRake)
|
||||
elif (lineTypes[i] == "header" or lineTypes[i] == "rake" or
|
||||
lineTypes[i] == "name" or lineTypes[i] == "ignore"):
|
||||
pass
|
||||
elif lineTypes[i] == "ante":
|
||||
fpdb_simple.parseAnteLine(line, isTourney, names, antes)
|
||||
elif lineTypes[i] == "table":
|
||||
tableResult=fpdb_simple.parseTableLine(base, line)
|
||||
else:
|
||||
raise FpdbError("unrecognised lineType:" + lineTypes[i])
|
||||
|
||||
maxSeats = tableResult['maxSeats']
|
||||
tableName = tableResult['tableName']
|
||||
#print "before part5, antes:", antes
|
||||
|
||||
#part 5: final preparations, then call Database.* with
|
||||
# the arrays as they are - that file will fill them.
|
||||
fpdb_simple.convertCardValues(cardValues)
|
||||
if base == "hold":
|
||||
fpdb_simple.convertCardValuesBoard(boardValues)
|
||||
fpdb_simple.convertBlindBet(actionTypes, actionAmounts)
|
||||
fpdb_simple.checkPositions(positions)
|
||||
|
||||
c = db.get_cursor()
|
||||
c.execute("SELECT limitType FROM Gametypes WHERE id=%s" % (db.sql.query['placeholder'],), (gametypeID, ))
|
||||
limit_type = c.fetchone()[0]
|
||||
fpdb_simple.convert3B4B(category, limit_type, actionTypes, actionAmounts)
|
||||
|
||||
totalWinnings = sum(winnings)
|
||||
|
||||
# if hold'em, use positions and not antes, if stud do not use positions, use antes
|
||||
# this is used for handsplayers inserts, so still needed even if hudcache update is being skipped
|
||||
if base == "hold":
|
||||
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base,
|
||||
category, actionTypes,
|
||||
allIns, actionTypeByNo,
|
||||
winnings,
|
||||
totalWinnings,
|
||||
positions, actionTypes,
|
||||
actionAmounts, None)
|
||||
else:
|
||||
hudImportData = fpdb_simple.generateHudCacheData(playerIDs, base,
|
||||
category, actionTypes,
|
||||
allIns, actionTypeByNo,
|
||||
winnings,
|
||||
totalWinnings, None,
|
||||
actionTypes,
|
||||
actionAmounts, antes)
|
||||
|
||||
try:
|
||||
db.commit() # need to commit new players as different db connection used
|
||||
# for other writes. maybe this will change maybe not ...
|
||||
except: # TODO: this really needs to be narrowed down
|
||||
print "parse: error during commit: " + str(sys.exc_value)
|
||||
|
||||
# HERE's an ugly kludge to keep from failing when positions is undef
|
||||
# We'll fix this by getting rid of the legacy importer. REB
|
||||
try:
|
||||
if positions:
|
||||
pass
|
||||
except NameError:
|
||||
positions = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
# save data structures in a HandToWrite instance and then insert into database:
|
||||
htw = Database.HandToWrite()
|
||||
htw.set_all( config, settings, base, category, siteTourneyNo, buyin
|
||||
, fee, knockout, entries, prizepool, tourneyStartTime
|
||||
, isTourney, tourneyTypeId, siteID, siteHandNo
|
||||
, gametypeID, handStartTime, names, playerIDs, startCashes
|
||||
, positions, antes, cardValues, cardSuits, boardValues, boardSuits
|
||||
, winnings, rakes, actionTypes, allIns, actionAmounts
|
||||
, actionNos, hudImportData, maxSeats, tableName, seatNos)
|
||||
|
||||
# save hand in db via direct call or via q if in a thread
|
||||
if writeq is None:
|
||||
result = db.store_the_hand(htw)
|
||||
else:
|
||||
writeq.put(htw)
|
||||
result = -999 # meaning unknown
|
||||
|
||||
t9 = time()
|
||||
#print "parse and save=(%4.3f)" % (t9-t0)
|
||||
return result
|
||||
#end def mainParser
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -89,13 +89,14 @@ def testFlopImport():
|
|||
print "DEBUG: stored: %s dups: %s partial: %s errs: %s ttime: %s" %(stored, dups, partial, errs, ttime)
|
||||
importer.clearFileList()
|
||||
|
||||
col = { 'sawShowdown': 2
|
||||
col = { 'sawShowdown': 2, 'street0Aggr':3
|
||||
}
|
||||
|
||||
q = """SELECT
|
||||
s.name,
|
||||
p.name,
|
||||
hp.sawShowdown
|
||||
hp.sawShowdown,
|
||||
hp.street0Aggr
|
||||
FROM
|
||||
Hands as h,
|
||||
Sites as s,
|
||||
|
@ -119,7 +120,8 @@ and s.id = p.siteid"""
|
|||
q = """SELECT
|
||||
s.name,
|
||||
p.name,
|
||||
hp.sawShowdown
|
||||
hp.sawShowdown,
|
||||
hp.street0Aggr
|
||||
FROM
|
||||
Hands as h,
|
||||
Sites as s,
|
||||
|
@ -135,10 +137,10 @@ and s.id = p.siteid"""
|
|||
c = db.get_cursor()
|
||||
c.execute(q)
|
||||
result = c.fetchall()
|
||||
pstats = { u'Kinewma':0, u'Arbaz':0, u's0rrow':1, u'bys7':0, u'AAALISAAAA':1, u'Bl\xe5veis':0 }
|
||||
for row, data in enumerate(result):
|
||||
print "DEBUG: result[%s]: %s" %(row, result[row])
|
||||
# Assert if any sawShowdown = True
|
||||
assert result[row][col['sawShowdown']] == 1
|
||||
print "DEBUG: result[%s]: %s == %s" %(row, result[row], pstats[data[1]])
|
||||
assert result[row][col['sawShowdown']] == pstats[data[1]]
|
||||
|
||||
assert 0 == 1
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import fpdb_simple
|
||||
import datetime
|
||||
import py
|
||||
|
||||
def checkDateParse(header, site, result):
|
||||
assert fpdb_simple.parseHandStartTime(header, site) == result
|
||||
|
||||
def testPokerStarsHHDate():
|
||||
tuples = (
|
||||
("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET]", "ps",
|
||||
datetime.datetime(2008,11,12,15,00,48)),
|
||||
("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/08/17 - 01:14:43 (ET)", "ps",
|
||||
datetime.datetime(2008,8,17,6,14,43)),
|
||||
("PokerStars Game #21969660557: Hold'em No Limit ($0.50/$1.00) - 2008/09/07 06:23:14 ET", "ps",
|
||||
datetime.datetime(2008,9,7,11,23,14))
|
||||
)
|
||||
|
||||
#def testTableDetection():
|
||||
# result = Tables.clean_title("French (deep)")
|
||||
# assert result == "French"
|
||||
# result = Tables.clean_title("French (deep) - $0.25/$0.50 - No Limit Hold'em - Logged In As xxxx")
|
||||
# assert result == "French"
|
||||
#
|
||||
# for (header, site, result) in tuples:
|
||||
# yield checkDateParse, header, site, result
|
||||
|
Loading…
Reference in New Issue
Block a user