diff --git a/pyfpdb/AlchemyFacilities.py b/pyfpdb/AlchemyFacilities.py new file mode 100644 index 00000000..c8284efb --- /dev/null +++ b/pyfpdb/AlchemyFacilities.py @@ -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 + diff --git a/pyfpdb/AlchemyMappings.py b/pyfpdb/AlchemyMappings.py new file mode 100644 index 00000000..c2e088a9 --- /dev/null +++ b/pyfpdb/AlchemyMappings.py @@ -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 '' % (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) + diff --git a/pyfpdb/AlchemyTables.py b/pyfpdb/AlchemyTables.py new file mode 100644 index 00000000..3165a480 --- /dev/null +++ b/pyfpdb/AlchemyTables.py @@ -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 + diff --git a/pyfpdb/CliFpdb.py b/pyfpdb/CliFpdb.py deleted file mode 100755 index abdddb45..00000000 --- a/pyfpdb/CliFpdb.py +++ /dev/null @@ -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 . -#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() diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 117fd0c7..39bf5921 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -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): diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 72b41336..c7b3e3b8 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -38,12 +38,12 @@ from decimal import Decimal import string import re import Queue +import codecs # pyGTK modules # FreePokerTools modules import fpdb_db -import fpdb_simple import Configuration import SQL import Card @@ -51,6 +51,7 @@ import Tourney from Exceptions import * log = Configuration.get_logger("logging.conf") +encoder = codecs.lookup('utf-8') class Database: @@ -587,6 +588,7 @@ class Database: elif not name.lower() in stat_dict[playerid]: stat_dict[playerid][name.lower()] = val elif name.lower() not in ('hand_id', 'player_id', 'seat', 'screen_name', 'seats'): + #print "DEBUG: stat_dict[%s][%s]: %s" %(playerid, name.lower(), val) stat_dict[playerid][name.lower()] += val n += 1 if n >= 10000: break # todo: don't think this is needed so set nice and high @@ -619,69 +621,6 @@ class Database: rows = c.fetchall() return rows - #returns the SQL ids of the names given in an array - # TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict - # { playername: id } instead of depending on it's relation to the positions list - # then this can be reduced in complexity a bit - - #def recognisePlayerIDs(cursor, names, site_id): - # result = [] - # for i in xrange(len(names)): - # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - # tmp=cursor.fetchall() - # if (len(tmp)==0): #new player - # cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) - # #print "Number of players rows inserted: %d" % cursor.rowcount - # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) - # tmp=cursor.fetchall() - # #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp - # result.append(tmp[0][0]) - # return result - - def recognisePlayerIDs(self, names, site_id): - c = self.get_cursor() - q = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" %(site_id, " OR name=".join([self.sql.query['placeholder'] for n in names])) - c.execute(q, names) # get all playerids by the names passed in - ids = dict(c.fetchall()) # convert to dict - if len(ids) != len(names): - notfound = [n for n in names if n not in ids] # make list of names not in database - if notfound: # insert them into database - q_ins = "INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")" - q_ins = q_ins.replace('%s', self.sql.query['placeholder']) - c.executemany(q_ins, [(n,) for n in notfound]) - q2 = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" % (site_id, " OR name=".join(["%s" for n in notfound])) - q2 = q2.replace('%s', self.sql.query['placeholder']) - c.execute(q2, notfound) # get their new ids - tmp = c.fetchall() - for n,id in tmp: # put them all into the same dict - ids[n] = id - # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB - return [ids[n] for n in names] - #end def recognisePlayerIDs - - # Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input - # this version could also be improved upon using list comprehensions, etc - - #def recognisePlayerIDs(cursor, names, site_id): - # result = [] - # notfound = [] - # cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) - # tmp = dict(cursor.fetchall()) - # for n in names: - # if n not in tmp: - # notfound.append(n) - # else: - # result.append(tmp[n]) - # if notfound: - # cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) - # cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) - # tmp = cursor.fetchall() - # for n in tmp: - # result.append(n[0]) - # - # return result - - def get_site_id(self, site): c = self.get_cursor() c.execute(self.sql.query['getSiteId'], (site,)) @@ -724,120 +663,6 @@ class Database: return ret - #stores a stud/razz hand into the database - def ring_stud(self, config, settings, base, category, site_hand_no, gametype_id, hand_start_time - ,names, player_ids, start_cashes, antes, card_values, card_suits, winnings, rakes - ,action_types, allIns, action_amounts, actionNos, hudImportData, maxSeats, tableName - ,seatNos): - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudImportData - ,(None, None, None, None, None), (None, None, None, None, None)) - - #print "before calling store_hands_players_stud, antes:", antes - hands_players_ids = self.store_hands_players_stud(self.backend, hands_id, player_ids - ,start_cashes, antes, card_values - ,card_suits, winnings, rakes, seatNos) - - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - return hands_id - #end def ring_stud - - def ring_holdem_omaha(self, config, settings, base, category, site_hand_no, gametype_id - ,hand_start_time, names, player_ids, start_cashes, positions, card_values - ,card_suits, board_values, board_suits, winnings, rakes, action_types, allIns - ,action_amounts, actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a holdem/omaha hand into the database""" - - t0 = time() - #print "in ring_holdem_omaha" - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - t1 = time() - fpdb_simple.fill_board_cards(board_values, board_suits) - t2 = time() - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats - ,hudImportData, board_values, board_suits) - #TEMPORARY CALL! - Just until all functions are migrated - t3 = time() - hands_players_ids = self.store_hands_players_holdem_omaha( - self.backend, category, hands_id, player_ids, start_cashes - , positions, card_values, card_suits, winnings, rakes, seatNos, hudImportData) - t4 = time() - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - t5 = time() - #print "fills=(%4.3f) saves=(%4.3f,%4.3f,%4.3f)" % (t2-t0, t3-t2, t4-t3, t5-t4) - return hands_id - #end def ring_holdem_omaha - - def tourney_holdem_omaha(self, config, settings, base, category, siteTourneyNo, buyin, fee, knockout - ,entries, prizepool, tourney_start, payin_amounts, ranks, tourneyTypeId - ,siteId #end of tourney specific params - ,site_hand_no, gametype_id, hand_start_time, names, player_ids - ,start_cashes, positions, card_values, card_suits, board_values - ,board_suits, winnings, rakes, action_types, allIns, action_amounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): - """stores a tourney holdem/omaha hand into the database""" - - fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) - fpdb_simple.fill_board_cards(board_values, board_suits) - - tourney_id = self.store_tourneys(tourneyTypeId, siteTourneyNo, entries, prizepool, tourney_start) - tourneys_players_ids = self.store_tourneys_players(tourney_id, player_ids, payin_amounts, ranks, winnings) - - hands_id = self.storeHands(self.backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats - ,hudImportData, board_values, board_suits) - - hands_players_ids = self.store_hands_players_holdem_omaha_tourney( - self.backend, category, hands_id, player_ids, start_cashes, positions - , card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids - , hudImportData, tourneyTypeId) - - #print "tourney holdem, backend=%d" % backend - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametype_id, hand_start_time, player_ids, hudImportData) - - return hands_id - #end def tourney_holdem_omaha - - def tourney_stud(self, config, settings, base, category, siteTourneyNo, buyin, fee, knockout, entries - ,prizepool, tourneyStartTime, payin_amounts, ranks, tourneyTypeId, siteId - ,siteHandNo, gametypeId, handStartTime, names, playerIds, startCashes, antes - ,cardValues, cardSuits, winnings, rakes, actionTypes, allIns, actionAmounts - ,actionNos, hudImportData, maxSeats, tableName, seatNos): - #stores a tourney stud/razz hand into the database - - fpdb_simple.fillCardArrays(len(names), base, category, cardValues, cardSuits) - - tourney_id = self.store_tourneys(tourneyTypeId, siteTourneyNo, entries, prizepool, tourneyStartTime) - - tourneys_players_ids = self.store_tourneys_players(tourney_id, playerIds, payin_amounts, ranks, winnings) - - hands_id = self.storeHands( self.backend, siteHandNo, gametypeId - , handStartTime, names, tableName, maxSeats - , hudImportData, (None, None, None, None, None), (None, None, None, None, None) ) - # changed board_values and board_suits to arrays of None, just like the - # cash game version of this function does - i don't believe this to be - # the correct thing to do (tell me if i'm wrong) but it should keep the - # importer from crashing - - hands_players_ids = self.store_hands_players_stud_tourney(self.backend, hands_id - , playerIds, startCashes, antes, cardValues, cardSuits - , winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId) - - if 'dropHudCache' not in settings or settings['dropHudCache'] != 'drop': - self.storeHudCache(self.backend, base, category, gametypeId, handStartTime, playerIds, hudImportData) - - return hands_id - #end def tourney_stud - def prepareBulkImport(self): """Drop some indexes/foreign keys to prepare for bulk import. Currently keeping the standalone indexes as needed to import quickly""" @@ -1465,64 +1290,6 @@ class Database: print "Error during fdb.lock_for_insert:", str(sys.exc_value) #end def lock_for_insert - def store_the_hand(self, h): - """Take a HandToWrite object and store it in the db""" - - # Following code writes hands to database and commits (or rolls back if there is an error) - try: - result = None - if h.isTourney: - ranks = map(lambda x: 0, h.names) # create an array of 0's equal to the length of names - payin_amounts = fpdb_simple.calcPayin(len(h.names), h.buyin, h.fee) - - if h.base == "hold": - result = self.tourney_holdem_omaha( - h.config, h.settings, h.base, h.category, h.siteTourneyNo, h.buyin - , h.fee, h.knockout, h.entries, h.prizepool, h.tourneyStartTime - , payin_amounts, ranks, h.tourneyTypeId, h.siteID, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs, h.startCashes - , h.positions, h.cardValues, h.cardSuits, h.boardValues, h.boardSuits - , h.winnings, h.rakes, h.actionTypes, h.allIns, h.actionAmounts - , h.actionNos, h.hudImportData, h.maxSeats, h.tableName, h.seatNos) - elif h.base == "stud": - result = self.tourney_stud( - h.config, h.settings, h.base, h.category, h.siteTourneyNo - , h.buyin, h.fee, h.knockout, h.entries, h.prizepool, h.tourneyStartTime - , payin_amounts, ranks, h.tourneyTypeId, h.siteID, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs, h.startCashes - , h.antes, h.cardValues, h.cardSuits, h.winnings, h.rakes, h.actionTypes - , h.allIns, h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats - , h.tableName, h.seatNos) - else: - raise FpdbError("unrecognised category") - else: - if h.base == "hold": - result = self.ring_holdem_omaha( - h.config, h.settings, h.base, h.category, h.siteHandNo - , h.gametypeID, h.handStartTime, h.names, h.playerIDs - , h.startCashes, h.positions, h.cardValues, h.cardSuits - , h.boardValues, h.boardSuits, h.winnings, h.rakes - , h.actionTypes, h.allIns, h.actionAmounts, h.actionNos - , h.hudImportData, h.maxSeats, h.tableName, h.seatNos) - elif h.base == "stud": - result = self.ring_stud( - h.config, h.settings, h.base, h.category, h.siteHandNo, h.gametypeID - , h.handStartTime, h.names, h.playerIDs, h.startCashes, h.antes - , h.cardValues, h.cardSuits, h.winnings, h.rakes, h.actionTypes, h.allIns - , h.actionAmounts, h.actionNos, h.hudImportData, h.maxSeats, h.tableName - , h.seatNos) - else: - raise FpdbError("unrecognised category") - except: - print "Error storing hand: " + str(sys.exc_value) - self.rollback() - # re-raise the exception so that the calling routine can decide what to do: - # (e.g. a write thread might try again) - raise - - return result - #end def store_the_hand - ########################### # NEWIMPORT CODE ########################### @@ -1663,145 +1430,111 @@ class Database: c = self.get_cursor() c.executemany(q, inserts) - def storeHudCacheNew(self, gid, pid, hc): - q = """INSERT INTO HudCache ( - gametypeId, - playerId - ) - VALUES ( - %s, %s - )""" + def storeHudCache(self, gid, pids, starttime, pdata): + """Update cached statistics. If update fails because no record exists, do an insert.""" -# 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) + if self.use_date_in_hudcache: + styleKey = datetime.strftime(starttime, 'd%y%m%d') + #styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) + else: + # hard-code styleKey as 'A000000' (all-time cache, no key) for now + styleKey = 'A000000' - q = q.replace('%s', self.sql.query['placeholder']) + update_hudcache = self.sql.query['update_hudcache'] + update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder']) + insert_hudcache = self.sql.query['insert_hudcache'] + insert_hudcache = insert_hudcache.replace('%s', self.sql.query['placeholder']) + + #print "DEBUG: %s %s %s" %(hid, pids, pdata) + inserts = [] + for p in pdata: + line = [0]*61 + + line[0] = 1 # HDs + if pdata[p]['street0VPI']: line[1] = 1 + if pdata[p]['street0Aggr']: line[2] = 1 + if pdata[p]['street0_3BChance']: line[3] = 1 + if pdata[p]['street0_3BDone']: line[4] = 1 + if pdata[p]['street1Seen']: line[5] = 1 + if pdata[p]['street2Seen']: line[6] = 1 + if pdata[p]['street3Seen']: line[7] = 1 + if pdata[p]['street4Seen']: line[8] = 1 + if pdata[p]['sawShowdown']: line[9] = 1 + if pdata[p]['street1Aggr']: line[10] = 1 + if pdata[p]['street2Aggr']: line[11] = 1 + if pdata[p]['street3Aggr']: line[12] = 1 + if pdata[p]['street4Aggr']: line[13] = 1 + if pdata[p]['otherRaisedStreet1']: line[14] = 1 + if pdata[p]['otherRaisedStreet2']: line[15] = 1 + if pdata[p]['otherRaisedStreet3']: line[16] = 1 + if pdata[p]['otherRaisedStreet4']: line[17] = 1 + if pdata[p]['foldToOtherRaisedStreet1']: line[18] = 1 + if pdata[p]['foldToOtherRaisedStreet2']: line[19] = 1 + if pdata[p]['foldToOtherRaisedStreet3']: line[20] = 1 + if pdata[p]['foldToOtherRaisedStreet4']: line[21] = 1 + line[22] = pdata[p]['wonWhenSeenStreet1'] + line[23] = pdata[p]['wonAtSD'] + if pdata[p]['stealAttemptChance']: line[24] = 1 + if pdata[p]['stealAttempted']: line[25] = 1 + if pdata[p]['foldBbToStealChance']: line[26] = 1 + if pdata[p]['foldedBbToSteal']: line[27] = 1 + if pdata[p]['foldSbToStealChance']: line[28] = 1 + if pdata[p]['foldedSbToSteal']: line[29] = 1 + if pdata[p]['street1CBChance']: line[30] = 1 + if pdata[p]['street1CBDone']: line[31] = 1 + if pdata[p]['street2CBChance']: line[32] = 1 + if pdata[p]['street2CBDone']: line[33] = 1 + if pdata[p]['street3CBChance']: line[34] = 1 + if pdata[p]['street3CBDone']: line[35] = 1 + if pdata[p]['street4CBChance']: line[36] = 1 + if pdata[p]['street4CBDone']: line[37] = 1 + if pdata[p]['foldToStreet1CBChance']: line[38] = 1 + if pdata[p]['foldToStreet1CBDone']: line[39] = 1 + if pdata[p]['foldToStreet2CBChance']: line[40] = 1 + if pdata[p]['foldToStreet2CBDone']: line[41] = 1 + if pdata[p]['foldToStreet3CBChance']: line[42] = 1 + if pdata[p]['foldToStreet3CBDone']: line[43] = 1 + if pdata[p]['foldToStreet4CBChance']: line[44] = 1 + if pdata[p]['foldToStreet4CBDone']: line[45] = 1 + line[46] = pdata[p]['totalProfit'] + if pdata[p]['street1CheckCallRaiseChance']: line[47] = 1 + if pdata[p]['street1CheckCallRaiseDone']: line[48] = 1 + if pdata[p]['street2CheckCallRaiseChance']: line[49] = 1 + if pdata[p]['street2CheckCallRaiseDone']: line[50] = 1 + if pdata[p]['street3CheckCallRaiseChance']: line[51] = 1 + if pdata[p]['street3CheckCallRaiseDone']: line[52] = 1 + if pdata[p]['street4CheckCallRaiseChance']: line[53] = 1 + if pdata[p]['street4CheckCallRaiseDone']: line[54] = 1 + line[55] = gid # gametypeId + line[56] = pids[p] # playerId + line[57] = len(pids) # activeSeats + pos = {'B':'B', 'S':'S', 0:'D', 1:'C', 2:'M', 3:'M', 4:'M', 5:'E', 6:'E', 7:'E', 8:'E', 9:'E' } + line[58] = pos[pdata[p]['position']] + line[59] = pdata[p]['tourneyTypeId'] + line[60] = styleKey # styleKey + inserts.append(line) - self.cursor.execute(q, ( - gid, - pid - )) -# 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) + cursor = self.get_cursor() + + for row in inserts: + # Try to do the update first: + num = cursor.execute(update_hudcache, row) + #print "DEBUG: values: %s" % row[-6:] + # Test statusmessage to see if update worked, do insert if not + # num is a cursor in sqlite + if ((self.backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") + or (self.backend == self.MYSQL_INNODB and num == 0) + or (self.backend == self.SQLITE and num.rowcount == 0)): + #move the last 6 items in WHERE clause of row from the end of the array + # to the beginning for the INSERT statement + #print "DEBUG: using INSERT: %s" % num + row = row[-6:] + row[:-6] + num = cursor.execute(insert_hudcache, row) + #print "DEBUG: Successfully(?: %s) updated HudCacho using INSERT" % num + else: + #print "DEBUG: Successfully updated HudCacho using UPDATE" + pass def isDuplicate(self, gametypeID, siteHandNo): dup = False @@ -1847,6 +1580,7 @@ class Database: def insertPlayer(self, name, site_id): result = None + (_name, _len) = encoder.encode(unicode(name)) c = self.get_cursor() q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" q = q.replace('%s', self.sql.query['placeholder']) @@ -1860,12 +1594,12 @@ class Database: #print "DEBUG: name: %s site: %s" %(name, site_id) - c.execute (q, (site_id, name)) + c.execute (q, (site_id, _name)) tmp = c.fetchone() if (tmp == None): #new player c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder']) - ,(name, site_id)) + ,(_name, site_id)) #Get last id might be faster here. #c.execute ("SELECT id FROM Players WHERE name=%s", (name,)) result = self.get_last_insert_id(c) @@ -1886,535 +1620,6 @@ class Database: - def storeHands(self, backend, site_hand_no, gametype_id - ,hand_start_time, names, tableName, maxSeats, hudCache - ,board_values, board_suits): - - cards = [Card.cardFromValueSuit(v,s) for v,s in zip(board_values,board_suits)] - #stores into table hands: - try: - c = self.get_cursor() - c.execute ("""INSERT INTO Hands - (siteHandNo, gametypeId, handStart, seats, tableName, importTime, maxSeats - ,boardcard1,boardcard2,boardcard3,boardcard4,boardcard5 - ,playersVpi, playersAtStreet1, playersAtStreet2 - ,playersAtStreet3, playersAtStreet4, playersAtShowdown - ,street0Raises, street1Raises, street2Raises - ,street3Raises, street4Raises, street1Pot - ,street2Pot, street3Pot, street4Pot - ,showdownPot - ) - VALUES - (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) - """.replace('%s', self.sql.query['placeholder']) - , (site_hand_no, gametype_id, hand_start_time, len(names), tableName, datetime.today(), maxSeats - ,cards[0], cards[1], cards[2], cards[3], cards[4] - ,hudCache['playersVpi'], hudCache['playersAtStreet1'], hudCache['playersAtStreet2'] - ,hudCache['playersAtStreet3'], hudCache['playersAtStreet4'], hudCache['playersAtShowdown'] - ,hudCache['street0Raises'], hudCache['street1Raises'], hudCache['street2Raises'] - ,hudCache['street3Raises'], hudCache['street4Raises'], hudCache['street1Pot'] - ,hudCache['street2Pot'], hudCache['street3Pot'], hudCache['street4Pot'] - ,hudCache['showdownPot'] - )) - ret = self.get_last_insert_id(c) - except: - ret = -1 - raise FpdbError( "storeHands error: " + str(sys.exc_value) ) - - return ret - #end def storeHands - - def store_hands_players_holdem_omaha(self, backend, category, hands_id, player_ids, start_cashes - ,positions, card_values, card_suits, winnings, rakes, seatNos, hudCache): - result=[] - - # postgres (and others?) needs the booleans converted to ints before saving: - # (or we could just save them as boolean ... but then we can't sum them so easily in sql ???) - # NO - storing booleans for now so don't need this - #hudCacheInt = {} - #for k,v in hudCache.iteritems(): - # if k in ('wonWhenSeenStreet1', 'wonAtSD', 'totalProfit'): - # hudCacheInt[k] = v - # else: - # hudCacheInt[k] = map(lambda x: 1 if x else 0, v) - - try: - inserts = [] - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - - if (category=="holdem"): - startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) - card3 = None - card4 = None - elif (category=="omahahi" or category=="omahahilo"): - startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1] - ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - else: - raise FpdbError("invalid category") - - inserts.append( ( - hands_id, player_ids[i], start_cashes[i], positions[i], 1, # tourneytypeid - needed for hudcache - card1, card2, card3, card4, startCards, - winnings[i], rakes[i], seatNos[i], hudCache['totalProfit'][i], - hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], - hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], - hudCache['street4Seen'][i], hudCache['sawShowdown'][i], - hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], - hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], - hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], - hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], - hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], - hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], - hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], - hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], - hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], - hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], - hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], - hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], - hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], - hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], - hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], - hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], - hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], - hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], hudCache['street3Calls'][i], hudCache['street4Calls'][i], - hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], hudCache['street3Bets'][i], hudCache['street4Bets'][i] - ) ) - c = self.get_cursor() - c.executemany (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, tourneyTypeId, - card1, card2, card3, card4, startCards, winnings, rake, seatNo, totalProfit, - 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, - street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, - street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, - street0Bets, street1Bets, street2Bets, street3Bets, street4Bets - ) - 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, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,inserts ) - result.append( self.get_last_insert_id(c) ) # wrong? not used currently - except: - raise FpdbError( "store_hands_players_holdem_omaha error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_holdem_omaha - - def store_hands_players_stud(self, backend, hands_id, player_ids, start_cashes, antes, - card_values, card_suits, winnings, rakes, seatNos): - #stores hands_players rows for stud/razz games. returns an array of the resulting IDs - - try: - result=[] - #print "before inserts in store_hands_players_stud, antes:", antes - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - card5 = Card.cardFromValueSuit(card_values[i][4], card_suits[i][4]) - card6 = Card.cardFromValueSuit(card_values[i][5], card_suits[i][5]) - card7 = Card.cardFromValueSuit(card_values[i][6], card_suits[i][6]) - - c = self.get_cursor() - c.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, tourneyTypeId, - card1, card2, - card3, card4, - card5, card6, - card7, winnings, rake, seatNo) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']), - (hands_id, player_ids[i], start_cashes[i], antes[i], 1, - card1, card2, - card3, card4, - card5, card6, - card7, winnings[i], rakes[i], seatNos[i])) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - result.append( self.get_last_insert_id(c) ) - except: - raise FpdbError( "store_hands_players_stud error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_stud - - def store_hands_players_holdem_omaha_tourney(self, backend, category, hands_id, player_ids - ,start_cashes, positions, card_values, card_suits - ,winnings, rakes, seatNos, tourneys_players_ids - ,hudCache, tourneyTypeId): - #stores hands_players for tourney holdem/omaha hands - - try: - result=[] - inserts = [] - for i in xrange(len(player_ids)): - card1 = Card.cardFromValueSuit(card_values[i][0], card_suits[i][0]) - card2 = Card.cardFromValueSuit(card_values[i][1], card_suits[i][1]) - - if len(card_values[0])==2: - startCards = Card.twoStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1]) - card3 = None - card4 = None - elif len(card_values[0])==4: - startCards = Card.fourStartCards(card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1] - ,card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3]) - card3 = Card.cardFromValueSuit(card_values[i][2], card_suits[i][2]) - card4 = Card.cardFromValueSuit(card_values[i][3], card_suits[i][3]) - else: - raise FpdbError ("invalid card_values length:"+str(len(card_values[0]))) - - inserts.append( (hands_id, player_ids[i], start_cashes[i], positions[i], tourneyTypeId, - card1, card2, card3, card4, startCards, - winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], hudCache['totalProfit'][i], - hudCache['street0VPI'][i], hudCache['street0Aggr'][i], - hudCache['street0_3BChance'][i], hudCache['street0_3BDone'][i], - hudCache['street1Seen'][i], hudCache['street2Seen'][i], hudCache['street3Seen'][i], - hudCache['street4Seen'][i], hudCache['sawShowdown'][i], - hudCache['street1Aggr'][i], hudCache['street2Aggr'][i], hudCache['street3Aggr'][i], hudCache['street4Aggr'][i], - hudCache['otherRaisedStreet1'][i], hudCache['otherRaisedStreet2'][i], - hudCache['otherRaisedStreet3'][i], hudCache['otherRaisedStreet4'][i], - hudCache['foldToOtherRaisedStreet1'][i], hudCache['foldToOtherRaisedStreet2'][i], - hudCache['foldToOtherRaisedStreet3'][i], hudCache['foldToOtherRaisedStreet4'][i], - hudCache['wonWhenSeenStreet1'][i], hudCache['wonAtSD'][i], - hudCache['stealAttemptChance'][i], hudCache['stealAttempted'][i], hudCache['foldBbToStealChance'][i], - hudCache['foldedBbToSteal'][i], hudCache['foldSbToStealChance'][i], hudCache['foldedSbToSteal'][i], - hudCache['street1CBChance'][i], hudCache['street1CBDone'][i], hudCache['street2CBChance'][i], hudCache['street2CBDone'][i], - hudCache['street3CBChance'][i], hudCache['street3CBDone'][i], hudCache['street4CBChance'][i], hudCache['street4CBDone'][i], - hudCache['foldToStreet1CBChance'][i], hudCache['foldToStreet1CBDone'][i], - hudCache['foldToStreet2CBChance'][i], hudCache['foldToStreet2CBDone'][i], - hudCache['foldToStreet3CBChance'][i], hudCache['foldToStreet3CBDone'][i], - hudCache['foldToStreet4CBChance'][i], hudCache['foldToStreet4CBDone'][i], - hudCache['street1CheckCallRaiseChance'][i], hudCache['street1CheckCallRaiseDone'][i], - hudCache['street2CheckCallRaiseChance'][i], hudCache['street2CheckCallRaiseDone'][i], - hudCache['street3CheckCallRaiseChance'][i], hudCache['street3CheckCallRaiseDone'][i], - hudCache['street4CheckCallRaiseChance'][i], hudCache['street4CheckCallRaiseDone'][i], - hudCache['street0Calls'][i], hudCache['street1Calls'][i], hudCache['street2Calls'][i], - hudCache['street3Calls'][i], hudCache['street4Calls'][i], - hudCache['street0Bets'][i], hudCache['street1Bets'][i], hudCache['street2Bets'][i], - hudCache['street3Bets'][i], hudCache['street4Bets'][i] - ) ) - - c = self.get_cursor() - c.executemany (""" - INSERT INTO HandsPlayers - (handId, playerId, startCash, position, tourneyTypeId, - card1, card2, card3, card4, startCards, winnings, rake, tourneysPlayersId, seatNo, totalProfit, - 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, - street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, street2CheckCallRaiseDone, - street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone, - street0Calls, street1Calls, street2Calls, street3Calls, street4Calls, - street0Bets, street1Bets, street2Bets, street3Bets, street4Bets - ) - 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, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,inserts ) - - result.append( self.get_last_insert_id(c) ) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - except: - err = traceback.extract_tb(sys.exc_info()[2])[-1] - print "***Error storing hand: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) - raise FpdbError( "store_hands_players_holdem_omaha_tourney error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_holdem_omaha_tourney - - def store_hands_players_stud_tourney(self, backend, hands_id, player_ids, start_cashes, - antes, card_values, card_suits, winnings, rakes, seatNos, tourneys_players_ids, tourneyTypeId): - #stores hands_players for tourney stud/razz hands - return # TODO: stubbed out until someone updates it for current database structuring - try: - result=[] - for i in xrange(len(player_ids)): - c = self.get_cursor() - c.execute ("""INSERT INTO HandsPlayers - (handId, playerId, startCash, ante, - card1Value, card1Suit, card2Value, card2Suit, - card3Value, card3Suit, card4Value, card4Suit, - card5Value, card5Suit, card6Value, card6Suit, - card7Value, card7Suit, winnings, rake, tourneysPlayersId, seatNo, tourneyTypeId) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']), - (hands_id, player_ids[i], start_cashes[i], antes[i], - card_values[i][0], card_suits[i][0], card_values[i][1], card_suits[i][1], - card_values[i][2], card_suits[i][2], card_values[i][3], card_suits[i][3], - card_values[i][4], card_suits[i][4], card_values[i][5], card_suits[i][5], - card_values[i][6], card_suits[i][6], winnings[i], rakes[i], tourneys_players_ids[i], seatNos[i], tourneyTypeId)) - #cursor.execute("SELECT id FROM HandsPlayers WHERE handId=%s AND playerId+0=%s", (hands_id, player_ids[i])) - #result.append(cursor.fetchall()[0][0]) - result.append( self.get_last_insert_id(c) ) - except: - raise FpdbError( "store_hands_players_stud_tourney error: " + str(sys.exc_value) ) - - return result - #end def store_hands_players_stud_tourney - - def storeHudCache(self, backend, base, category, gametypeId, hand_start_time, playerIds, hudImportData): - """Update cached statistics. If update fails because no record exists, do an insert. - Can't use array updates here (not easily anyway) because we need to insert any rows - that don't get updated.""" - - # if (category=="holdem" or category=="omahahi" or category=="omahahilo"): - try: - if self.use_date_in_hudcache: - #print "key =", "d%02d%02d%02d " % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) - else: - # hard-code styleKey as 'A000000' (all-time cache, no key) for now - styleKey = 'A000000' - - #print "storeHudCache, len(playerIds)=", len(playerIds), " len(vpip)=" \ - #, len(hudImportData['street0VPI']), " len(totprof)=", len(hudImportData['totalProfit']) - for player in xrange(len(playerIds)): - - # Set up a clean row - row=[] - row.append(0)#blank for id - row.append(gametypeId) - row.append(playerIds[player]) - row.append(len(playerIds))#seats - for i in xrange(len(hudImportData)+2): - row.append(0) - - if base=="hold": - row[4]=hudImportData['position'][player] - else: - row[4]=0 - row[5]=1 #tourneysGametypeId - row[6]+=1 #HDs - if hudImportData['street0VPI'][player]: row[7]+=1 - if hudImportData['street0Aggr'][player]: row[8]+=1 - if hudImportData['street0_3BChance'][player]: row[9]+=1 - if hudImportData['street0_3BDone'][player]: row[10]+=1 - if hudImportData['street1Seen'][player]: row[11]+=1 - if hudImportData['street2Seen'][player]: row[12]+=1 - if hudImportData['street3Seen'][player]: row[13]+=1 - if hudImportData['street4Seen'][player]: row[14]+=1 - if hudImportData['sawShowdown'][player]: row[15]+=1 - if hudImportData['street1Aggr'][player]: row[16]+=1 - if hudImportData['street2Aggr'][player]: row[17]+=1 - if hudImportData['street3Aggr'][player]: row[18]+=1 - if hudImportData['street4Aggr'][player]: row[19]+=1 - if hudImportData['otherRaisedStreet1'][player]: row[20]+=1 - if hudImportData['otherRaisedStreet2'][player]: row[21]+=1 - if hudImportData['otherRaisedStreet3'][player]: row[22]+=1 - if hudImportData['otherRaisedStreet4'][player]: row[23]+=1 - if hudImportData['foldToOtherRaisedStreet1'][player]: row[24]+=1 - if hudImportData['foldToOtherRaisedStreet2'][player]: row[25]+=1 - if hudImportData['foldToOtherRaisedStreet3'][player]: row[26]+=1 - if hudImportData['foldToOtherRaisedStreet4'][player]: row[27]+=1 - if hudImportData['wonWhenSeenStreet1'][player]!=0.0: row[28]+=hudImportData['wonWhenSeenStreet1'][player] - if hudImportData['wonAtSD'][player]!=0.0: row[29]+=hudImportData['wonAtSD'][player] - if hudImportData['stealAttemptChance'][player]: row[30]+=1 - if hudImportData['stealAttempted'][player]: row[31]+=1 - if hudImportData['foldBbToStealChance'][player]: row[32]+=1 - if hudImportData['foldedBbToSteal'][player]: row[33]+=1 - if hudImportData['foldSbToStealChance'][player]: row[34]+=1 - if hudImportData['foldedSbToSteal'][player]: row[35]+=1 - - if hudImportData['street1CBChance'][player]: row[36]+=1 - if hudImportData['street1CBDone'][player]: row[37]+=1 - if hudImportData['street2CBChance'][player]: row[38]+=1 - if hudImportData['street2CBDone'][player]: row[39]+=1 - if hudImportData['street3CBChance'][player]: row[40]+=1 - if hudImportData['street3CBDone'][player]: row[41]+=1 - if hudImportData['street4CBChance'][player]: row[42]+=1 - if hudImportData['street4CBDone'][player]: row[43]+=1 - - if hudImportData['foldToStreet1CBChance'][player]: row[44]+=1 - if hudImportData['foldToStreet1CBDone'][player]: row[45]+=1 - if hudImportData['foldToStreet2CBChance'][player]: row[46]+=1 - if hudImportData['foldToStreet2CBDone'][player]: row[47]+=1 - if hudImportData['foldToStreet3CBChance'][player]: row[48]+=1 - if hudImportData['foldToStreet3CBDone'][player]: row[49]+=1 - if hudImportData['foldToStreet4CBChance'][player]: row[50]+=1 - if hudImportData['foldToStreet4CBDone'][player]: row[51]+=1 - - #print "player=", player - #print "len(totalProfit)=", len(hudImportData['totalProfit']) - if hudImportData['totalProfit'][player]: - row[52]+=hudImportData['totalProfit'][player] - - if hudImportData['street1CheckCallRaiseChance'][player]: row[53]+=1 - if hudImportData['street1CheckCallRaiseDone'][player]: row[54]+=1 - if hudImportData['street2CheckCallRaiseChance'][player]: row[55]+=1 - if hudImportData['street2CheckCallRaiseDone'][player]: row[56]+=1 - if hudImportData['street3CheckCallRaiseChance'][player]: row[57]+=1 - if hudImportData['street3CheckCallRaiseDone'][player]: row[58]+=1 - if hudImportData['street4CheckCallRaiseChance'][player]: row[59]+=1 - if hudImportData['street4CheckCallRaiseDone'][player]: row[60]+=1 - - # Try to do the update first: - cursor = self.get_cursor() - num = cursor.execute("""UPDATE HudCache - SET HDs=HDs+%s, street0VPI=street0VPI+%s, street0Aggr=street0Aggr+%s, - street0_3BChance=street0_3BChance+%s, street0_3BDone=street0_3BDone+%s, - street1Seen=street1Seen+%s, street2Seen=street2Seen+%s, street3Seen=street3Seen+%s, - street4Seen=street4Seen+%s, sawShowdown=sawShowdown+%s, - street1Aggr=street1Aggr+%s, street2Aggr=street2Aggr+%s, street3Aggr=street3Aggr+%s, - street4Aggr=street4Aggr+%s, otherRaisedStreet1=otherRaisedStreet1+%s, - otherRaisedStreet2=otherRaisedStreet2+%s, otherRaisedStreet3=otherRaisedStreet3+%s, - otherRaisedStreet4=otherRaisedStreet4+%s, - foldToOtherRaisedStreet1=foldToOtherRaisedStreet1+%s, foldToOtherRaisedStreet2=foldToOtherRaisedStreet2+%s, - foldToOtherRaisedStreet3=foldToOtherRaisedStreet3+%s, foldToOtherRaisedStreet4=foldToOtherRaisedStreet4+%s, - wonWhenSeenStreet1=wonWhenSeenStreet1+%s, wonAtSD=wonAtSD+%s, stealAttemptChance=stealAttemptChance+%s, - stealAttempted=stealAttempted+%s, foldBbToStealChance=foldBbToStealChance+%s, - foldedBbToSteal=foldedBbToSteal+%s, - foldSbToStealChance=foldSbToStealChance+%s, foldedSbToSteal=foldedSbToSteal+%s, - street1CBChance=street1CBChance+%s, street1CBDone=street1CBDone+%s, street2CBChance=street2CBChance+%s, - street2CBDone=street2CBDone+%s, street3CBChance=street3CBChance+%s, - street3CBDone=street3CBDone+%s, street4CBChance=street4CBChance+%s, street4CBDone=street4CBDone+%s, - foldToStreet1CBChance=foldToStreet1CBChance+%s, foldToStreet1CBDone=foldToStreet1CBDone+%s, - foldToStreet2CBChance=foldToStreet2CBChance+%s, foldToStreet2CBDone=foldToStreet2CBDone+%s, - foldToStreet3CBChance=foldToStreet3CBChance+%s, - foldToStreet3CBDone=foldToStreet3CBDone+%s, foldToStreet4CBChance=foldToStreet4CBChance+%s, - foldToStreet4CBDone=foldToStreet4CBDone+%s, totalProfit=totalProfit+%s, - street1CheckCallRaiseChance=street1CheckCallRaiseChance+%s, - street1CheckCallRaiseDone=street1CheckCallRaiseDone+%s, street2CheckCallRaiseChance=street2CheckCallRaiseChance+%s, - street2CheckCallRaiseDone=street2CheckCallRaiseDone+%s, street3CheckCallRaiseChance=street3CheckCallRaiseChance+%s, - street3CheckCallRaiseDone=street3CheckCallRaiseDone+%s, street4CheckCallRaiseChance=street4CheckCallRaiseChance+%s, - street4CheckCallRaiseDone=street4CheckCallRaiseDone+%s - WHERE gametypeId+0=%s - AND playerId=%s - AND activeSeats=%s - AND position=%s - AND tourneyTypeId+0=%s - AND styleKey=%s - """.replace('%s', self.sql.query['placeholder']) - ,(row[6], row[7], row[8], row[9], row[10], - row[11], row[12], row[13], row[14], row[15], - row[16], row[17], row[18], row[19], row[20], - row[21], row[22], row[23], row[24], row[25], - row[26], row[27], row[28], row[29], row[30], - row[31], row[32], row[33], row[34], row[35], - row[36], row[37], row[38], row[39], row[40], - row[41], row[42], row[43], row[44], row[45], - row[46], row[47], row[48], row[49], row[50], - row[51], row[52], row[53], row[54], row[55], - row[56], row[57], row[58], row[59], row[60], - row[1], row[2], row[3], str(row[4]), row[5], styleKey)) - # Test statusmessage to see if update worked, do insert if not - #print "storehud2, upd num =", num.rowcount - # num is a cursor in sqlite - if ( (backend == self.PGSQL and cursor.statusmessage != "UPDATE 1") - or (backend == self.MYSQL_INNODB and num == 0) - or (backend == self.SQLITE and num.rowcount == 0) - ): - #print "playerid before insert:",row[2]," num = ", num - num = cursor.execute("""INSERT INTO HudCache - (gametypeId, playerId, activeSeats, position, tourneyTypeId, styleKey, - HDs, street0VPI, street0Aggr, street0_3BChance, street0_3BDone, - street1Seen, street2Seen, street3Seen, street4Seen, sawShowdown, - street1Aggr, street2Aggr, street3Aggr, street4Aggr, otherRaisedStreet1, - otherRaisedStreet2, otherRaisedStreet3, otherRaisedStreet4, foldToOtherRaisedStreet1, foldToOtherRaisedStreet2, - foldToOtherRaisedStreet3, foldToOtherRaisedStreet4, wonWhenSeenStreet1, wonAtSD, stealAttemptChance, - stealAttempted, foldBbToStealChance, foldedBbToSteal, foldSbToStealChance, foldedSbToSteal, - street1CBChance, street1CBDone, street2CBChance, street2CBDone, street3CBChance, - street3CBDone, street4CBChance, street4CBDone, foldToStreet1CBChance, foldToStreet1CBDone, - foldToStreet2CBChance, foldToStreet2CBDone, foldToStreet3CBChance, foldToStreet3CBDone, foldToStreet4CBChance, - foldToStreet4CBDone, totalProfit, street1CheckCallRaiseChance, street1CheckCallRaiseDone, street2CheckCallRaiseChance, - street2CheckCallRaiseDone, street3CheckCallRaiseChance, street3CheckCallRaiseDone, street4CheckCallRaiseChance, street4CheckCallRaiseDone) - VALUES (%s, %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s, - %s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - , (row[1], row[2], row[3], row[4], row[5], styleKey, row[6], row[7], row[8], row[9], row[10] - ,row[11], row[12], row[13], row[14], row[15], row[16], row[17], row[18], row[19], row[20] - ,row[21], row[22], row[23], row[24], row[25], row[26], row[27], row[28], row[29], row[30] - ,row[31], row[32], row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40] - ,row[41], row[42], row[43], row[44], row[45], row[46], row[47], row[48], row[49], row[50] - ,row[51], row[52], row[53], row[54], row[55], row[56], row[57], row[58], row[59], row[60]) ) - #print "hopefully inserted hud data line: ", cursor.rowcount - # message seems to be "INSERT 0 1" - else: - #print "updated(2) hud data line" - pass - # else: - # print "todo: implement storeHudCache for stud base" - - except: - raise FpdbError( "storeHudCache error: " + str(sys.exc_value) ) - - #end def storeHudCache - - def store_tourneys(self, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): - ret = -1 - try: - # try and create tourney record, fetch id if it already exists - # avoids race condition when doing the select first - cursor = self.get_cursor() - cursor.execute("savepoint ins_tourney") - cursor.execute("""INSERT INTO Tourneys - (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) - VALUES (%s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) - ret = self.get_last_insert_id(cursor) - #print "created new tourneys.id:",ret - except: - #if str(sys.exc_value) contains 'sitetourneyno': - # raise FpdbError( "store_tourneys error: " + str(sys.exc_value) ) - #else: - #print "error insert tourney (%s) trying select ..." % (str(sys.exc_value),) - cursor.execute("rollback to savepoint ins_tourney") - try: - cursor.execute( "SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s".replace('%s', self.sql.query['placeholder']) - , (siteTourneyNo, tourneyTypeId) ) - rec = cursor.fetchone() - #print "select tourney result: ", rec - try: - len(rec) - ret = rec[0] - except: - print "Tourney id not found" - except: - print "Error selecting tourney id:", str(sys.exc_info()[1]) - - cursor.execute("release savepoint ins_tourney") - #print "store_tourneys returning", ret - return ret - #end def store_tourneys - def store_tourneys_players(self, tourney_id, player_ids, payin_amounts, ranks, winnings): try: result=[] @@ -2583,183 +1788,6 @@ class Database: #end def tRecogniseTourneyType - def tRecognizeTourney(self, tourney, dbTourneyTypeId): - logging.debug("Database.tRecognizeTourney") - tourneyID = 1 - # Check if tourney exists in db (based on tourney.siteId and tourney.tourNo) - # If so retrieve all data to check for consistency - cursor = self.get_cursor() - cursor.execute (self.sql.query['getTourney'].replace('%s', self.sql.query['placeholder']), - (tourney.tourNo, tourney.siteId) - ) - result=cursor.fetchone() - - expectedValuesDecimal = { 2 : "entries", 3 : "prizepool", 6 : "buyInChips", 9 : "rebuyChips", - 10 : "addOnChips", 11 : "rebuyAmount", 12 : "addOnAmount", 13 : "totalRebuys", - 14 : "totalAddOns", 15 : "koBounty" } - expectedValues = { 7 : "tourneyName", 16 : "tourneyComment" } - - tourneyDataMatch = True - tCommentTs = None - starttime = None - endtime = None - - try: - len(result) - tourneyID = result[0] - logging.debug("Tourney found in db with TourneyID = %d" % tourneyID) - if result[1] <> dbTourneyTypeId: - tourneyDataMatch = False - logging.debug("Tourney has wrong type ID (expected : %s - found : %s)" % (dbTourneyTypeId, result[1])) - if (tourney.starttime is None and result[4] is not None) or ( tourney.starttime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) <> result[4]) : - tourneyDataMatch = False - logging.debug("Tourney data mismatch : wrong starttime : Tourney=%s / db=%s" % (tourney.starttime, result[4])) - if (tourney.endtime is None and result[5] is not None) or ( tourney.endtime is not None and fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) <> result[5]) : - tourneyDataMatch = False - logging.debug("Tourney data mismatch : wrong endtime : Tourney=%s / db=%s" % (tourney.endtime, result[5])) - - for ev in expectedValues : - if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ): - logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) ) - tourneyDataMatch = False - #break - for evD in expectedValuesDecimal : - if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD)) ) <> result[evD] ): - logging.debug("Tourney data mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD)), result[evD]) ) - tourneyDataMatch = False - #break - - # TO DO : Deal with matrix summary mutliple parsings - - except: - # Tourney not found : create - logging.debug("Tourney is not found : create") - if tourney.tourneyComment is not None : - tCommentTs = datetime.today() - if tourney.starttime is not None : - starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) - if tourney.endtime is not None : - endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) - # TODO : deal with matrix Id processed - cursor.execute (self.sql.query['insertTourney'].replace('%s', self.sql.query['placeholder']), - (dbTourneyTypeId, tourney.tourNo, tourney.entries, tourney.prizepool, starttime, - endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips, - tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty, - tourney.tourneyComment, tCommentTs) - ) - tourneyID = self.get_last_insert_id(cursor) - - - # Deal with inconsistent tourney in db - if tourneyDataMatch == False : - # Update Tourney - if result[16] <> tourney.tourneyComment : - tCommentTs = datetime.today() - if tourney.starttime is not None : - starttime = fpdb_simple.parseHandStartTime("- %s" % tourney.starttime) - if tourney.endtime is not None : - endtime = fpdb_simple.parseHandStartTime("- %s" % tourney.endtime) - - cursor.execute (self.sql.query['updateTourney'].replace('%s', self.sql.query['placeholder']), - (dbTourneyTypeId, tourney.entries, tourney.prizepool, starttime, - endtime, tourney.buyInChips, tourney.tourneyName, 0, tourney.rebuyChips, tourney.addOnChips, - tourney.rebuyAmount, tourney.addOnAmount, tourney.totalRebuys, tourney.totalAddOns, tourney.koBounty, - tourney.tourneyComment, tCommentTs, tourneyID) - ) - - return tourneyID - #end def tRecognizeTourney - - def tStoreTourneyPlayers(self, tourney, dbTourneyId): - logging.debug("Database.tStoreTourneyPlayers") - # First, get playerids for the players and specifically the one for hero : - playersIds = self.recognisePlayerIDs(tourney.players, tourney.siteId) - # hero may be None for matrix tourneys summaries -# hero = [ tourney.hero ] -# heroId = self.recognisePlayerIDs(hero , tourney.siteId) -# logging.debug("hero Id = %s - playersId = %s" % (heroId , playersIds)) - - tourneyPlayersIds=[] - try: - cursor = self.get_cursor() - - for i in xrange(len(playersIds)): - cursor.execute(self.sql.query['getTourneysPlayers'].replace('%s', self.sql.query['placeholder']) - ,(dbTourneyId, playersIds[i])) - result=cursor.fetchone() - #print "tried SELECTing tourneys_players.id:",tmp - - try: - len(result) - # checking data - logging.debug("TourneysPlayers found : checking data") - expectedValuesDecimal = { 1 : "payinAmounts", 2 : "finishPositions", 3 : "winnings", 4 : "countRebuys", - 5 : "countAddOns", 6 : "countKO" } - - tourneyPlayersIds.append(result[0]); - - tourneysPlayersDataMatch = True - for evD in expectedValuesDecimal : - if ( Decimal(getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]] ) <> result[evD] ): - logging.debug("TourneysPlayers data mismatch for TourneysPlayer id=%d, name=%s : wrong %s : Tourney=%s / db=%s" % (result[0], tourney.players[i], expectedValuesDecimal.get(evD), getattr( tourney, expectedValuesDecimal.get(evD))[tourney.players[i]], result[evD]) ) - tourneysPlayersDataMatch = False - #break - - if tourneysPlayersDataMatch == False: - logging.debug("TourneysPlayers data update needed") - cursor.execute (self.sql.query['updateTourneysPlayers'].replace('%s', self.sql.query['placeholder']), - (tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]], - tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]], - tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]], - result[7], result[8], result[0]) - ) - - except TypeError: - logging.debug("TourneysPlayers not found : need insert") - cursor.execute (self.sql.query['insertTourneysPlayers'].replace('%s', self.sql.query['placeholder']), - (dbTourneyId, playersIds[i], - tourney.payinAmounts[tourney.players[i]], tourney.finishPositions[tourney.players[i]], - tourney.winnings[tourney.players[i]] , tourney.countRebuys[tourney.players[i]], - tourney.countAddOns[tourney.players[i]] , tourney.countKO[tourney.players[i]], - None, None) - ) - tourneyPlayersIds.append(self.get_last_insert_id(cursor)) - - except: - raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) ) - - return tourneyPlayersIds - #end def tStoreTourneyPlayers - - def tUpdateTourneysHandsPlayers(self, tourney, dbTourneysPlayersIds, dbTourneyTypeId): - logging.debug("Database.tCheckTourneysHandsPlayers") - try: - # Massive update seems to take quite some time ... -# query = self.sql.query['updateHandsPlayersForTTypeId2'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) ) -# cursor = self.get_cursor() -# cursor.execute (query, dbTourneysPlayersIds) - - query = self.sql.query['selectHandsPlayersWithWrongTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner'].join([self.sql.query['placeholder'] for id in dbTourneysPlayersIds]) ) - #print "query : %s" % query - cursor = self.get_cursor() - cursor.execute (query, dbTourneysPlayersIds) - result=cursor.fetchall() - - if (len(result) > 0): - logging.debug("%d lines need update : %s" % (len(result), result) ) - listIds = [] - for i in result: - listIds.append(i[0]) - - query2 = self.sql.query['updateHandsPlayersForTTypeId'] % (dbTourneyTypeId, self.sql.query['handsPlayersTTypeId_joiner_id'].join([self.sql.query['placeholder'] for id in listIds]) ) - cursor.execute (query2, listIds) - else: - logging.debug("No need to update, HandsPlayers are correct") - - except: - raise fpdb_simple.FpdbError( "tStoreTourneyPlayers error: " + str(sys.exc_value) ) - #end def tUpdateTourneysHandsPlayers - # Class used to hold all the data needed to write a hand to the db # mainParser() in fpdb_parse_logic.py creates one of these and then passes it to diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index f96b6af7..88bb6407 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -216,6 +216,7 @@ class DerivedStats(): 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): @@ -349,8 +350,9 @@ class DerivedStats(): CG: CheckCall would be a much better name for this. """ - for i, street in enumerate(hand.actionStreets[2:], start=1): - actions = hand.actions[hand.actionStreets[i]] + #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: @@ -360,8 +362,8 @@ class DerivedStats(): 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] = True - self.handsplayers[pname]['street%dCheckCallRaiseDone' % i] = act!='folds' + self.handsplayers[pname]['street%dCheckCallRaiseChance' % (i+1)] = True + self.handsplayers[pname]['street%dCheckCallRaiseDone' % (i+1)] = act!='folds' def seen(self, hand, i): pas = set() @@ -468,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 diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py index 16131ab2..a64a9425 100755 --- a/pyfpdb/GuiBulkImport.py +++ b/pyfpdb/GuiBulkImport.py @@ -30,7 +30,6 @@ import gtk import gobject # fpdb/FreePokerTools modules -import fpdb_simple import fpdb_import import Configuration import Exceptions diff --git a/pyfpdb/GuiTableViewer.py b/pyfpdb/GuiTableViewer.py index c730f962..57fc772d 100644 --- a/pyfpdb/GuiTableViewer.py +++ b/pyfpdb/GuiTableViewer.py @@ -20,7 +20,6 @@ import pygtk pygtk.require('2.0') import gtk import os -import fpdb_simple import fpdb_import import fpdb_db diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 3467216a..a660b56d 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -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 """ diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index 1ea0d203..47cfd302 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -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 diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 56c1f388..2b19b04a 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -3088,6 +3088,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 diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index 28bd313a..ce99b274 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -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 diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 2d7f2e0c..9f6993b9 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -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 diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 8921d9d8..7c240cbe 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -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." diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py deleted file mode 100644 index 6fac3669..00000000 --- a/pyfpdb/fpdb_parse_logic.py +++ /dev/null @@ -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 . -#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 - diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py deleted file mode 100644 index 5f0c6507..00000000 --- a/pyfpdb/fpdb_simple.py +++ /dev/null @@ -1,1728 +0,0 @@ -#!/usr/bin/python -# -*- coding: iso-8859-15 -*- - -#Copyright 2008 Steffen Jobbagy-Felso -#This program is free software: you can redistribute it and/or modify -#it under the terms of the GNU Affero General Public License as published by -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - -#This file contains simple functions for fpdb - -#Aiming to eventually remove this module, functions will move to, eg: -#fpdb_db db create/re-create/management/etc -#Hands or related files for saving hands to db, etc - -import datetime -import time -import re -import sys -from Exceptions import * -import locale - -import Card - -PS = 1 -FTP = 2 - -# TODO: these constants are also used in fpdb_save_to_db and others, is there a way to do like C #define, and #include ? -# answer - yes. These are defined in fpdb_db so are accessible through that class. -MYSQL_INNODB = 2 -PGSQL = 3 -SQLITE = 4 - -LOCALE_ENCODING = locale.getdefaultlocale()[1] - -#returns an array of the total money paid. intending to add rebuys/addons here -def calcPayin(count, buyin, fee): - return [buyin + fee for i in xrange(count)] -#end def calcPayin - -def checkPositions(positions): - """ verify positions are valid """ - if any(not (p == "B" or p == "S" or (p >= 0 and p <= 9)) for p in positions): - raise FpdbError("invalid position '"+p+"' found in checkPositions") - ### RHH modified to allow for "position 9" here (pos==9 is when you're a dead hand before the BB - ### eric - position 8 could be valid - if only one blind is posted, but there's still 10 people, ie a sitout is present, and the small is dead... - -def classifyLines(hand, category, lineTypes, lineStreets): - """ makes a list of classifications for each line for further processing - manipulates passed arrays """ - currentStreet = "predeal" - done = False #set this to true once we reach the last relevant line (the summary, except rake, is all repeats) - for i, line in enumerate(hand): - if done: - if "[" not in line or "mucked [" not in line: - lineTypes.append("ignore") - else: - lineTypes.append("cards") - elif line.startswith("Dealt to"): - lineTypes.append("cards") - elif i == 0: - lineTypes.append("header") - elif line.startswith("Table '"): - lineTypes.append("table") - elif line.startswith("Seat ") and ( ("in chips" in line) or "($" in line): - lineTypes.append("name") - elif isActionLine(line): - lineTypes.append("action") - if " posts " in line or " posts the " in line: - currentStreet="preflop" - elif " antes " in line or " posts the ante " in line: - lineTypes.append("ante") - elif line.startswith("*** FLOP *** ["): - lineTypes.append("cards") - currentStreet="flop" - elif line.startswith("*** TURN *** ["): - lineTypes.append("cards") - currentStreet="turn" - elif line.startswith("*** RIVER *** ["): - lineTypes.append("cards") - currentStreet="river" - elif line.startswith("*** 3"): - lineTypes.append("ignore") - currentStreet=0 - elif line.startswith("*** 4"): - lineTypes.append("ignore") - currentStreet=1 - elif line.startswith("*** 5"): - lineTypes.append("ignore") - currentStreet=2 - elif line.startswith("*** 6"): - lineTypes.append("ignore") - currentStreet=3 - elif line.startswith("*** 7") or line == "*** RIVER ***": - lineTypes.append("ignore") - currentStreet=4 - elif isWinLine(line): - lineTypes.append("win") - elif line.startswith("Total pot ") and "Rake" in line: - lineTypes.append("rake") - done=True - elif "*** SHOW DOWN ***" in line or "*** SUMMARY ***" in line: - lineTypes.append("ignore") - #print "in classifyLine, showdown or summary" - elif " shows [" in line: - lineTypes.append("cards") - else: - raise FpdbError("unrecognised linetype in:"+hand[i]) - lineStreets.append(currentStreet) - -def convert3B4B(category, limit_type, actionTypes, actionAmounts): - """calculates the actual bet amounts in the given amount array and changes it accordingly.""" - for i in xrange(len(actionTypes)): - for j in xrange(len(actionTypes[i])): - bets = [] - for k in xrange(len(actionTypes[i][j])): - if (actionTypes[i][j][k] == "bet"): - bets.append((i,j,k)) - if (len(bets)>=2): - #print "len(bets) 2 or higher, need to correct it. bets:",bets,"len:",len(bets) - for betNo in reversed(xrange (1,len(bets))): - amount2 = actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] - amount1 = actionAmounts[bets[betNo-1][0]][bets[betNo-1][1]][bets[betNo-1][2]] - actionAmounts[bets[betNo][0]][bets[betNo][1]][bets[betNo][2]] = amount2 - amount1 - -def convertBlindBet(actionTypes, actionAmounts): - """ Corrects the bet amount if the player had to pay blinds """ - i = 0#setting street to pre-flop - for j in xrange(len(actionTypes[i])):#playerloop - blinds = [] - bets = [] - for k in xrange(len(actionTypes[i][j])): - if actionTypes[i][j][k] == "blind": - blinds.append((i,j,k)) - - if blinds and actionTypes[i][j][k] == "bet": - bets.append((i,j,k)) - if len(bets) == 1: - blind_amount=actionAmounts[blinds[0][0]][blinds[0][1]][blinds[0][2]] - bet_amount=actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] - actionAmounts[bets[0][0]][bets[0][1]][bets[0][2]] = bet_amount - blind_amount - -#converts the strings in the given array to ints (changes the passed array, no returning). see table design for conversion details -#todo: make this use convertCardValuesBoard -def convertCardValues(arr): - map(convertCardValuesBoard, arr) - -# a 0-card is one in a stud game that we did not see or was not shown -card_map = { 0: 0, "2": 2, "3" : 3, "4" : 4, "5" : 5, "6" : 6, "7" : 7, "8" : 8, - "9" : 9, "T" : 10, "J" : 11, "Q" : 12, "K" : 13, "A" : 14} - -def convertCardValuesBoard(arr): - """ converts the strings in the given array to ints - (changes the passed array, no returning). see table design for - conversion details """ - for i in xrange(len(arr)): - arr[i] = card_map[arr[i]] - -def createArrays(category, seats, card_values, card_suits, antes, winnings, - rakes, action_types, allIns, action_amounts, actionNos, - actionTypeByNo): - """ this creates the 2D/3D arrays. manipulates the passed arrays instead of returning. """ - for i in xrange(seats):#create second dimension arrays - card_values.append( [] ) - card_suits.append( [] ) - antes.append(0) - winnings.append(0) - rakes.append(0) - - streetCount = 4 if (category == "holdem" or category == "omahahi" or - category == "omahahilo") else 5 - - for i in xrange(streetCount): #build the first dimension array, for streets - action_types.append([]) - allIns.append([]) - action_amounts.append([]) - actionNos.append([]) - actionTypeByNo.append([]) - for j in xrange(seats): # second dimension arrays: players - action_types[i].append([]) - allIns[i].append([]) - action_amounts[i].append([]) - actionNos[i].append([]) -# if (category=="holdem" or category=="omahahi" or category=="omahahilo"): -# pass - if category == "razz" or category == "studhi" or category == "studhilo": #need to fill card arrays. - for i in xrange(seats): - for j in xrange(7): - card_values[i].append(0) - card_suits[i].append("x") -# else: -# raise FpdbError("invalid category") -#end def createArrays - -def fill_board_cards(board_values, board_suits): - """ fill up the two board card arrays """ - while len(board_values) < 5: - board_values.append(0) - board_suits.append("x") - -def fillCardArrays(player_count, base, category, card_values, card_suits): - """fills up the two card arrays""" - if category == "holdem": - cardCount = 2 - elif category == "omahahi" or category == "omahahilo": - cardCount = 4 - elif base == "stud": - cardCount = 7 - else: - raise FpdbError("invalid category:", category) - - for i in xrange(player_count): - while len(card_values[i]) < cardCount: - card_values[i].append(0) - card_suits[i].append("x") -#end def fillCardArrays - -#filters out a player that folded before paying ante or blinds. This should be called -#before calling the actual hand parser. manipulates hand, no return. -def filterAnteBlindFold(hand): - #todo: this'll only get rid of one ante folder, not multiple ones - #todo: in tourneys this should not be removed but - #print "start of filterAnteBlindFold" - pre3rd = [] - for i, line in enumerate(hand): - if line.startswith("*** 3") or line.startswith("*** HOLE"): - pre3rd = hand[0:i] - - foldeeName = None - for line in pre3rd: - if line.endswith("folds") or line.endswith("is sitting out") or line.endswith(" stands up"): #found ante fold or timeout - pos = line.find(" folds") - foldeeName = line[0:pos] - if pos == -1 and " in chips)" not in line: - pos = line.find(" is sitting out") - foldeeName = line[0:pos] - if pos == -1: - pos = line.find(" stands up") - foldeeName = line[0:pos] - if pos == -1: - pos1 = line.find(": ") + 2 - pos2 = line.find(" (") - foldeeName = line[pos1:pos2] - - if foldeeName is not None: - #print "filterAnteBlindFold, foldeeName:",foldeeName - for i, line in enumerate(hand): - if foldeeName in line: - hand[i] = None - - return [line for line in hand if line] - -def stripEOLspaces(str): - return str.rstrip() - -def filterCrap(hand, isTourney): - """ removes useless lines as well as trailing spaces """ - - #remove trailing spaces at end of line - hand = [line.rstrip() for line in hand] - - #general variable position word filter/string filter - for i in xrange(len(hand)): - if hand[i].startswith("Board ["): - hand[i] = False - elif hand[i].find(" out of hand ")!=-1: - hand[i]=hand[i][:-56] - elif "($0 in chips)" in hand[i]: - hand[i] = False - elif hand[i]=="*** HOLE CARDS ***": - hand[i] = False - elif hand[i].endswith("has been disconnected"): - hand[i] = False - elif hand[i].endswith("has requested TIME"): - hand[i] = False - elif hand[i].endswith("has returned"): - hand[i] = False - elif hand[i].endswith("will be allowed to play after the button"): - hand[i] = False - elif hand[i].endswith("has timed out"): - hand[i] = False - elif hand[i].endswith("has timed out while disconnected"): - hand[i] = False - elif hand[i].endswith("has timed out while being disconnected"): - hand[i] = False - elif hand[i].endswith("is connected"): - hand[i] = False - elif hand[i].endswith("is disconnected"): - hand[i] = False - elif hand[i].find(" is low with [")!=-1: - hand[i] = False - elif hand[i].endswith(" mucks"): - hand[i] = False - elif hand[i].endswith(": mucks hand"): - hand[i] = False - elif hand[i] == "No low hand qualified": - hand[i] = False - elif hand[i] == "Pair on board - a double bet is allowed": - hand[i] = False - elif " shows " in hand[i] and "[" not in hand[i]: - hand[i] = False - elif hand[i].startswith("The button is in seat #"): - hand[i] = False - #above is alphabetic, reorder below if bored - elif hand[i].startswith("Time has expired"): - hand[i] = False - elif hand[i].endswith("has reconnected"): - hand[i] = False - elif hand[i].endswith("seconds left to act"): - hand[i] = False - elif hand[i].endswith("seconds to reconnect"): - hand[i] = False - elif hand[i].endswith("was removed from the table for failing to post"): - hand[i] = False - elif "joins the table at seat " in hand[i]: - hand[i] = False - elif (hand[i].endswith("leaves the table")): - hand[i] = False - elif "is high with " in hand[i]: - hand[i] = False - elif hand[i].endswith("doesn't show hand"): - hand[i] = False - elif hand[i].endswith("is being treated as all-in"): - hand[i] = False - elif " adds $" in hand[i]: - hand[i] = False - elif hand[i] == "Betting is capped": - hand[i] = False - elif (hand[i].find(" said, \"")!=-1): - hand[i] = False - - if isTourney and not hand[i] == False: - if (hand[i].endswith(" is sitting out") and (not hand[i].startswith("Seat "))): - hand[i] = False - elif hand[i]: - if (hand[i].endswith(": sits out")): - hand[i] = False - elif (hand[i].endswith(" is sitting out")): - hand[i] = False - # python docs say this is identical to filter(None, list) - # which removes all false items from the passed list (hand) - hand = [line for line in hand if line] - - return hand - -def float2int(string): - """ takes a poker float (including , for thousand seperator) and - converts it to an int """ - # Note that this automagically assumes US style currency formatters - pos = string.find(",") - if pos != -1: #remove , the thousand seperator - string = "%s%s" % (string[0:pos], string[pos+1:]) - - pos = string.find(".") - if pos != -1: #remove decimal point - string = "%s%s" % (string[0:pos], string[pos+1:]) - - result = int(string) - if pos == -1: #no decimal point - was in full dollars - need to multiply with 100 - result *= 100 - return result - -ActionLines = ( "calls $", ": calls ", "brings in for", "completes it to", - "posts small blind", "posts the small blind", "posts big blind", - "posts the big blind", "posts small & big blinds", "posts $", - "posts a dead", "bets $", ": bets ", " raises") - -def isActionLine(line): - if line.endswith("folds"): - return True - elif line.endswith("checks"): - return True - elif line.startswith("Uncalled bet"): - return True - - # searches for each member of ActionLines being in line, returns true - # on first match .. neat func - return any(x for x in ActionLines if x in line) - -def isAlreadyInDB(db, gametypeID, siteHandNo): - c = db.get_cursor() - c.execute(db.sql.query['isAlreadyInDB'], (gametypeID, siteHandNo)) - result = c.fetchall() - if len(result) >= 1: - raise DuplicateError ("dupl") - -def isRebuyOrAddon(topline): - """isRebuyOrAddon not implemented yet""" - return False - -#returns whether the passed topline indicates a tournament or not -def isTourney(topline): - return "Tournament" in topline - -WinLines = ( "wins the pot", "ties for the ", "wins side pot", "wins the low main pot", "wins the high main pot", - "wins the low", - "wins the high pot", "wins the high side pot", "wins the main pot", "wins the side pot", "collected" ) - -def isWinLine(line): - """ returns boolean whether the passed line is a win line """ - return any(x for x in WinLines if x in line) - -#returns the amount of cash/chips put into the put in the given action line -def parseActionAmount(line, atype, isTourney): - #if (line.endswith(" and is all-in")): - # line=line[:-14] - #elif (line.endswith(", and is all in")): - # line=line[:-15] - - #ideally we should recognise this as an all-in if category is capXl - if line.endswith(", and is capped"): - line=line[:-15] - if line.endswith(" and is capped"): - line=line[:-14] - - if atype == "fold" or atype == "check": - amount = 0 - elif atype == "unbet": - pos1 = line.find("$") + 1 - if pos1 == 0: - pos1 = line.find("(") + 1 - pos2 = line.find(")") - amount = float2int(line[pos1:pos2]) - elif atype == "bet" and ": raises $" in line and "to $" in line: - pos = line.find("to $")+4 - amount = float2int(line[pos:]) - else: - if not isTourney: - pos = line.rfind("$")+1 - #print "parseActionAmount, line:", line, "line[pos:]:", line[pos:] - amount = float2int(line[pos:]) - else: - #print "line:"+line+"EOL" - pos = line.rfind(" ")+1 - #print "pos:",pos - #print "pos of 20:", line.find("20") - amount = int(line[pos:]) - - if atype == "unbet": - amount *= -1 - return amount -#end def parseActionAmount - -#doesnt return anything, simply changes the passed arrays action_types and -# action_amounts. For stud this expects numeric streets (3-7), for -# holdem/omaha it expects predeal, preflop, flop, turn or river -def parseActionLine(base, isTourney, line, street, playerIDs, names, action_types, allIns, action_amounts, actionNos, actionTypeByNo): - if street == "predeal" or street == "preflop": - street = 0 - elif street == "flop": - street = 1 - elif street == "turn": - street = 2 - elif street == "river": - street = 3 - - nextActionNo = 0 - for player in xrange(len(actionNos[street])): - for count in xrange(len(actionNos[street][player])): - if actionNos[street][player][count]>=nextActionNo: - nextActionNo=actionNos[street][player][count]+1 - - (line, allIn) = goesAllInOnThisLine(line) - atype = parseActionType(line) - playerno = recognisePlayerNo(line, names, atype) - amount = parseActionAmount(line, atype, isTourney) - - action_types[street][playerno].append(atype) - allIns[street][playerno].append(allIn) - action_amounts[street][playerno].append(amount) - actionNos[street][playerno].append(nextActionNo) - tmp=(playerIDs[playerno], atype) - actionTypeByNo[street].append(tmp) - -def goesAllInOnThisLine(line): - """returns whether the player went all-in on this line and removes the all-in text from the line.""" - isAllIn = False - if (line.endswith(" and is all-in")): - line = line[:-14] - isAllIn = True - elif (line.endswith(", and is all in")): - line = line[:-15] - isAllIn = True - return (line, isAllIn) - -#returns the action type code (see table design) of the given action line -ActionTypes = { 'brings in for' :"blind", - ' posts $' :"blind", - ' posts a dead ' :"blind", - ' posts the small blind of $' :"blind", - ': posts big blind ' :"blind", - ': posts small blind ' :"blind", - ' posts the big blind of $' :"blind", - ': posts small & big blinds $' :"blind", - ': posts small blind $' :"blind", - 'calls' :"call", - 'completes it to' :"bet", - ' bets' :"bet", - ' raises' :"bet" - } -def parseActionType(line): - if (line.startswith("Uncalled bet")): - return "unbet" - elif (line.endswith(" folds")): - return "fold" - elif (line.endswith(" checks")): - return "check" - else: - for x in ActionTypes: - if x in line: - return ActionTypes[x] - raise FpdbError ("failed to recognise actiontype in parseActionLine in: "+line) - -#parses the ante out of the given line and checks which player paid it, updates antes accordingly. -def parseAnteLine(line, isTourney, names, antes): - for i, name in enumerate(names): - if line.startswith(name.encode(LOCALE_ENCODING)): - pos = line.rfind("$") + 1 - if not isTourney: - antes[i] += float2int(line[pos:]) - else: - if "all-in" not in line: - pos = line.rfind(" ") + 1 - antes[i] += int(line[pos:]) - else: - pos1 = line.rfind("ante") + 5 - pos2 = line.find(" ", pos1) - antes[i] += int(line[pos1:pos2]) - -#returns the buyin of a tourney in cents -def parseBuyin(topline): - pos1 = topline.find("$")+1 - if pos1 != 0: - pos2 = topline.find("+") - else: - pos1 = topline.find("€")+3 - pos2 = topline.find("+") - return float2int(topline[pos1:pos2]) - -#parses a card line and changes the passed arrays accordingly -#todo: reorganise this messy method -def parseCardLine(category, street, line, names, cardValues, cardSuits, boardValues, boardSuits): - if line.startswith("Dealt to") or " shows [" in line or "mucked [" in line: - playerNo = recognisePlayerNo(line, names, "card") #anything but unbet will be ok for that string - - pos = line.rfind("[")+1 - if category == "holdem": - for i in (pos, pos+3): - cardValues[playerNo].append(line[i:i+1]) - cardSuits[playerNo].append(line[i+1:i+2]) - if len(cardValues[playerNo]) != 2: - if (cardValues[playerNo][0] == cardValues[playerNo][2] and - cardSuits[playerNo][1] == cardSuits[playerNo][3]): - cardValues[playerNo]=cardValues[playerNo][0:2] - cardSuits[playerNo]=cardSuits[playerNo][0:2] - else: - print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] - raise FpdbError("read too many/too few holecards in parseCardLine") - elif category == "omahahi" or category == "omahahilo": - for i in (pos, pos+3, pos+6, pos+9): - cardValues[playerNo].append(line[i:i+1]) - cardSuits[playerNo].append(line[i+1:i+2]) - if (len(cardValues[playerNo])!=4): - if (cardValues[playerNo][0] == cardValues[playerNo][4] and - cardSuits[playerNo][3] == cardSuits[playerNo][7]): #two tests will do - cardValues[playerNo] = cardValues[playerNo][0:4] - cardSuits[playerNo] = cardSuits[playerNo][0:4] - else: - print "line:",line,"cardValues[playerNo]:",cardValues[playerNo] - raise FpdbError("read too many/too few holecards in parseCardLine") - elif category == "razz" or category == "studhi" or category == "studhilo": - if "shows" not in line and "mucked" not in line: - #print "parseCardLine(in stud if), street:", street - if line[pos+2]=="]": #-> not (hero and 3rd street) - cardValues[playerNo][street+2]=line[pos:pos+1] - cardSuits[playerNo][street+2]=line[pos+1:pos+2] - else: - #print "hero card1:", line[pos:pos+2], "hero card2:", line[pos+3:pos+5], "hero card3:", line[pos+6:pos+8], - cardValues[playerNo][street]=line[pos:pos+1] - cardSuits[playerNo][street]=line[pos+1:pos+2] - cardValues[playerNo][street+1]=line[pos+3:pos+4] - cardSuits[playerNo][street+1]=line[pos+4:pos+5] - cardValues[playerNo][street+2]=line[pos+6:pos+7] - cardSuits[playerNo][street+2]=line[pos+7:pos+8] - else: - #print "parseCardLine(in stud else), street:", street - cardValues[playerNo][0]=line[pos:pos+1] - cardSuits[playerNo][0]=line[pos+1:pos+2] - pos+=3 - cardValues[playerNo][1]=line[pos:pos+1] - cardSuits[playerNo][1]=line[pos+1:pos+2] - if street==4: - pos=pos=line.rfind("]")-2 - cardValues[playerNo][6]=line[pos:pos+1] - cardSuits[playerNo][6]=line[pos+1:pos+2] - #print "cardValues:", cardValues - #print "cardSuits:", cardSuits - else: - print "line:",line,"street:",street - raise FpdbError("invalid category") - #print "end of parseCardLine/playercards, cardValues:",cardValues - elif (line.startswith("*** FLOP ***")): - pos=line.find("[")+1 - for i in (pos, pos+3, pos+6): - boardValues.append(line[i:i+1]) - boardSuits.append(line[i+1:i+2]) - #print boardValues - elif (line.startswith("*** TURN ***") or line.startswith("*** RIVER ***")): - pos=line.find("[")+1 - pos=line.find("[", pos+1)+1 - boardValues.append(line[pos:pos+1]) - boardSuits.append(line[pos+1:pos+2]) - #print boardValues - else: - raise FpdbError ("unrecognised line:"+line) - -def parseCashesAndSeatNos(lines): - """parses the startCashes and seatNos of each player out of the given lines and returns them as a dictionary of two arrays""" - cashes = [] - seatNos = [] - for i in xrange (len(lines)): - pos2=lines[i].find(":") - seatNos.append(int(lines[i][5:pos2])) - - pos1=lines[i].rfind("($")+2 - if pos1==1: #for tourneys - it's 1 instead of -1 due to adding 2 above - pos1=lines[i].rfind("(")+1 - pos2=lines[i].find(" in chips") - cashes.append(float2int(lines[i][pos1:pos2])) - return {'startCashes':cashes, 'seatNos':seatNos} - -#returns the buyin of a tourney in cents -def parseFee(topline): - pos1 = topline.find("$")+1 - if pos1 != 0: - pos1 = topline.find("$", pos1)+1 - pos2 = topline.find(" ", pos1) - else: - pos1 = topline.find("€")+3 - pos1 = topline.find("€", pos1)+3 - pos2 = topline.find(" ", pos1) - return float2int(topline[pos1:pos2]) - -#returns a datetime object with the starttime indicated in the given topline -def parseHandStartTime(topline): - #convert x:13:35 to 0x:13:35 - counter=0 - while counter < 10: - pos = topline.find(" %d:" % counter) - if pos != -1: - topline = "%s0%s" % (topline[0:pos+1], topline[pos+1:]) - break - counter += 1 - - isUTC=False - if topline.find("UTC")!=-1: - pos1 = topline.find("-")+2 - pos2 = topline.find("UTC") - tmp=topline[pos1:pos2] - isUTC=True - else: - tmp=topline - #print "parsehandStartTime, tmp:", tmp - pos = tmp.find("-")+2 - tmp = tmp[pos:] - #Need to match either - # 2008/09/07 06:23:14 ET or - # 2008/08/17 - 01:14:43 (ET) or - # 2008/11/12 9:33:31 CET [2008/11/12 3:33:31 ET] - rexx = '(?P[0-9]{4})\/(?P[0-9]{2})\/(?P[0-9]{2})[\- ]+(?P
[0-9]+):(?P[0-9]+):(?P[0-9]+)' - m = re.search(rexx,tmp) - result = datetime.datetime(int(m.group('YEAR')), int(m.group('MON')), int(m.group('DAY')), int(m.group('HR')), int(m.group('MIN')), int(m.group('SEC'))) - - if not isUTC: #these use US ET - result += datetime.timedelta(hours=5) - - return result - -#parses the names out of the given lines and returns them as an array -def findName(line): - pos1 = line.find(":") + 2 - pos2 = line.rfind("(") - 1 - return unicode(line[pos1:pos2], LOCALE_ENCODING) - -def parseNames(lines): - return [findName(line) for line in lines] - -def parsePositions(hand, names): - positions = [-1 for i in names] - sb, bb = -1, -1 - - for line in hand: - if sb == -1 and "small blind" in line and "dead small blind" not in line: - sb = line - if bb == -1 and "big blind" in line and "dead big blind" not in line: - bb = line - -#identify blinds -#print "parsePositions before recognising sb/bb. names:",names - sbExists = True - if sb != -1: - sb = recognisePlayerNo(sb, names, "bet") - else: - sbExists = False - if bb != -1: - bb = recognisePlayerNo(bb, names, "bet") - -# print "sb = ", sb, "bb = ", bb - if bb == sb: # if big and small are same, then don't duplicate the small - sbExists = False - sb = -1 - - #write blinds into array - if sbExists: - positions[sb]="S" - positions[bb]="B" - - #fill up rest of array - arraypos = sb - 1 if sbExists else bb - 1 - - distFromBtn=0 - while arraypos >= 0 and arraypos != bb: - #print "parsePositions first while, arraypos:",arraypos,"positions:",positions - positions[arraypos] = distFromBtn - arraypos -= 1 - distFromBtn += 1 - - # eric - this takes into account dead seats between blinds - if sbExists: - i = bb - 1 - while positions[i] < 0 and i != sb: - positions[i] = 9 - i -= 1 - ### RHH - Changed to set the null seats before BB to "9" - i = sb - 1 if sbExists else bb - 1 - - while positions[i] < 0: - positions[i]=9 - i-=1 - - arraypos=len(names)-1 - if (bb!=0 or (bb==0 and sbExists==False) or (bb == 1 and sb != arraypos) ): - while (arraypos > bb and arraypos > sb): - positions[arraypos] = distFromBtn - arraypos -= 1 - distFromBtn += 1 - - if any(p == -1 for p in positions): - print "parsePositions names:",names - print "result:",positions - raise FpdbError ("failed to read positions") -# print str(positions), "\n" - return positions - -#simply parses the rake amount and returns it as an int -def parseRake(line): - pos = line.find("Rake")+6 - rake = float2int(line[pos:]) - return rake - -def parseSiteHandNo(topline): - """returns the hand no assigned by the poker site""" - pos1 = topline.find("#")+1 - pos2 = topline.find(":") - return topline[pos1:pos2] - -def parseTableLine(base, line): - """returns a dictionary with maxSeats and tableName""" - pos1=line.find('\'')+1 - pos2=line.find('\'', pos1) - #print "table:",line[pos1:pos2] - pos3=pos2+2 - pos4=line.find("-max") - #print "seats:",line[pos3:pos4] - return {'maxSeats':int(line[pos3:pos4]), 'tableName':line[pos1:pos2]} -#end def parseTableLine - -#returns the hand no assigned by the poker site -def parseTourneyNo(topline): - pos1 = topline.find("Tournament #")+12 - pos2 = topline.find(",", pos1) - #print "parseTourneyNo pos1:",pos1," pos2:",pos2, " result:",topline[pos1:pos2] - return topline[pos1:pos2] - -#parses a win/collect line. manipulates the passed array winnings, no explicit return -def parseWinLine(line, names, winnings, isTourney): - #print "parseWinLine: line:",line - for i,n in enumerate(names): - n = n.encode(LOCALE_ENCODING) - if line.startswith(n): - if isTourney: - pos1 = line.rfind("collected ") + 10 - pos2 = line.find(" ", pos1) - winnings[i] += int(line[pos1:pos2]) - else: - pos1 = line.rfind("$") + 1 - pos2 = line.find(" ", pos1) - winnings[i] += float2int(line[pos1:pos2]) - -#returns the category (as per database) string for the given line -def recogniseCategory(line): - if "Razz" in line: - return "razz" - elif "Hold'em" in line: - return "holdem" - elif "Omaha" in line: - if "Hi/Lo" not in line and "H/L" not in line: - return "omahahi" - else: - return "omahahilo" - elif "Stud" in line: - if "Hi/Lo" not in line and "H/L" not in line: - return "studhi" - else: - return "studhilo" - else: - raise FpdbError("failed to recognise category, line:"+line) - -#returns the int for the gametype_id for the given line -def recogniseGametypeID(backend, db, cursor, topline, smallBlindLine, site_id, category, isTourney):#todo: this method is messy - #if (topline.find("HORSE")!=-1): - # raise FpdbError("recogniseGametypeID: HORSE is not yet supported.") - - #note: the below variable names small_bet and big_bet are misleading, in NL/PL they mean small/big blind - if isTourney: - type = "tour" - pos1 = topline.find("(")+1 - if(topline[pos1] == "H" or topline[pos1] == "O" or - topline[pos1] == "R" or topline[pos1]=="S" or - topline[pos1+2] == "C"): - pos1 = topline.find("(", pos1)+1 - pos2 = topline.find("/", pos1) - small_bet = int(topline[pos1:pos2]) - else: - type = "ring" - pos1 = topline.find("$")+1 - pos2 = topline.find("/$") - small_bet = float2int(topline[pos1:pos2]) - - pos1 = pos2+2 - if isTourney: - pos1 -= 1 - pos2 = topline.find(")") - - if pos2 <= pos1: - pos2 = topline.find(")", pos1) - - if isTourney: - big_bet = int(topline[pos1:pos2]) - else: - big_bet = float2int(topline[pos1:pos2]) - - if 'No Limit' in topline: - limit_type = "nl" if 'Cap No' not in topline else "cn" - elif 'Pot Limit' in topline: - limit_type = "pl" if 'Cap Pot' not in topline else "cp" - else: - limit_type = "fl" - - #print "recogniseGametypeID small_bet/blind:",small_bet,"big bet/blind:", big_bet,"limit type:",limit_type - if limit_type == "fl": - cursor.execute(db.sql.query['getGametypeFL'], (site_id, type, category, - limit_type, small_bet, - big_bet)) - else: - cursor.execute(db.sql.query['getGametypeNL'], (site_id, type, category, - limit_type, small_bet, - big_bet)) - result = cursor.fetchone() - #print "recgt1 result=",result - #ret=result[0] - #print "recgt1 ret=",ret - #print "tried SELECTing gametypes.id, result:",result - - try: - len(result) - except TypeError: - if category=="holdem" or category=="omahahi" or category=="omahahilo": - base="hold" - else: - base="stud" - - if category=="holdem" or category=="omahahi" or category=="studhi": - hiLo='h' - elif category=="razz": - hiLo='l' - else: - hiLo='s' - - if (limit_type=="fl"): - big_blind=small_bet - if base=="hold": - if smallBlindLine==topline: - raise FpdbError("invalid small blind line") - elif isTourney: - pos=smallBlindLine.rfind(" ")+1 - small_blind=int(smallBlindLine[pos:]) - else: - pos=smallBlindLine.rfind("$")+1 - small_blind=float2int(smallBlindLine[pos:]) - else: - small_blind=0 - result = db.insertGameTypes( (site_id, type, base, category, limit_type, hiLo - ,small_blind, big_blind, small_bet, big_bet) ) - #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s - #AND limitType=%s AND smallBet=%s AND bigBet=%s", (site_id, type, category, limit_type, small_bet, big_bet)) - else: - result = db.insertGameTypes( (site_id, type, base, category, limit_type, hiLo - ,small_bet, big_bet, 0, 0) )#remember, for these bet means blind - #cursor.execute ("SELECT id FROM Gametypes WHERE siteId=%s AND type=%s AND category=%s - #AND limitType=%s AND smallBlind=%s AND bigBlind=%s", (site_id, type, category, limit_type, small_bet, big_bet)) - - return result[0] -#end def recogniseGametypeID - -def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebuyOrAddon): - ret = -1 - cursor = db.get_cursor() - # First we try to find the tourney itself (by its tourneySiteId) in case it has already been inserted before (by a summary file for instance) - # The reason is that some tourneys may not be identified correctly in the HH toplines (especially Buy-In and Fee which are used to search/create the TourneyTypeId) - #TODO: When the summary file will be dumped to BD, if the tourney is already in, Buy-In/Fee may need an update (e.g. creation of a new type and link to the Tourney) - cursor.execute (db.sql.query['getTourneyTypeIdByTourneyNo'].replace('%s', db.sql.query['placeholder']), (tourneySiteId, siteId)) - result = cursor.fetchone() - - try: - len(result) - ret = result[0] - except: - cursor.execute( """SELECT id FROM TourneyTypes - WHERE siteId=%s AND buyin=%s AND fee=%s - AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - result = cursor.fetchone() - #print "tried selecting tourneytypes.id, result:", result - - try: - len(result) - ret = result[0] - except TypeError:#this means we need to create a new entry - #print "insert new tourneytype record ..." - try: - cursor.execute( """INSERT INTO TourneyTypes (siteId, buyin, fee, knockout, rebuyOrAddon) - VALUES (%s, %s, %s, %s, %s)""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - ret = db.get_last_insert_id(cursor) - except: - #print "maybe tourneytype was created since select, try selecting again ..." - cursor.execute( """SELECT id FROM TourneyTypes - WHERE siteId=%s AND buyin=%s AND fee=%s - AND knockout=%s AND rebuyOrAddon=%s""".replace('%s', db.sql.query['placeholder']) - , (siteId, buyin, fee, knockout, rebuyOrAddon) ) - result = cursor.fetchone() - try: - len(result) - ret = result[0] - except: - print "Failed to find or insert TourneyTypes record" - ret = -1 # failed to find or insert record - #print "tried selecting tourneytypes.id again, result:", result - - #print "recogniseTourneyTypeId: returning", ret - return ret -#end def recogniseTourneyTypeId - - -#recognises the name in the given line and returns its array position in the given array -def recognisePlayerNo(line, names, atype): - #print "recogniseplayerno, names:",names - for i in xrange(len(names)): - encodedName = names[i].encode(LOCALE_ENCODING) - if (atype=="unbet"): - if (line.endswith(encodedName)): - return (i) - elif (line.startswith("Dealt to ")): - #print "recognisePlayerNo, card precut, line:",line - tmp=line[9:] - #print "recognisePlayerNo, card postcut, tmp:",tmp - if (tmp.startswith(encodedName)): - return (i) - elif (line.startswith("Seat ")): - if (line.startswith("Seat 10")): - tmp=line[9:] - else: - tmp=line[8:] - - if (tmp.startswith(encodedName)): - return (i) - else: - if (line.startswith(encodedName)): - return (i) - #if we're here we mustve failed - raise FpdbError ("failed to recognise player in: "+line+" atype:"+atype) -#end def recognisePlayerNo - - -#removes trailing \n from the given array -def removeTrailingEOL(arr): - for i in xrange(len(arr)): - if (arr[i].endswith("\n")): - #print "arr[i] before removetrailingEOL:", arr[i] - arr[i]=arr[i][:-1] - #print "arr[i] after removetrailingEOL:", arr[i] - return arr -#end def removeTrailingEOL - -#splits the rake according to the proportion of pot won. manipulates the second passed array. -def splitRake(winnings, rakes, totalRake): - winnercnt=0 - totalWin=0 - for i in xrange(len(winnings)): - if winnings[i]!=0: - winnercnt+=1 - totalWin+=winnings[i] - firstWinner=i - if winnercnt==1: - rakes[firstWinner]=totalRake - else: - totalWin=float(totalWin) - for i in xrange(len(winnings)): - if winnings[i]!=0: - winPortion=winnings[i]/totalWin - rakes[i]=totalRake*winPortion -#end def splitRake - -def generateHudCacheData(player_ids, base, category, action_types, allIns, actionTypeByNo - ,winnings, totalWinnings, positions, actionTypes, actionAmounts, antes): - """calculates data for the HUD during import. IMPORTANT: if you change this method make -sure to also change the following storage method and table_viewer.prepare_data if necessary -""" - #print "generateHudCacheData, len(player_ids)=", len(player_ids) - #setup subarrays of the result dictionary. - 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=[] - hudDataPositions=[] - - street0Calls=[] - street1Calls=[] - street2Calls=[] - street3Calls=[] - street4Calls=[] - street0Bets=[] - street1Bets=[] - street2Bets=[] - street3Bets=[] - street4Bets=[] - #street0Raises=[] - #street1Raises=[] - #street2Raises=[] - #street3Raises=[] - #street4Raises=[] - - # Summary figures for hand table: - result={} - result['playersVpi']=0 - result['playersAtStreet1']=0 - result['playersAtStreet2']=0 - result['playersAtStreet3']=0 - result['playersAtStreet4']=0 - result['playersAtShowdown']=0 - result['street0Raises']=0 - result['street1Raises']=0 - result['street2Raises']=0 - result['street3Raises']=0 - result['street4Raises']=0 - result['street1Pot']=0 - result['street2Pot']=0 - result['street3Pot']=0 - result['street4Pot']=0 - result['showdownPot']=0 - - firstPfRaiseByNo=-1 - firstPfRaiserId=-1 - firstPfRaiserNo=-1 - firstPfCallByNo=-1 - firstPfCallerId=-1 - - for i, action in enumerate(actionTypeByNo[0]): - if action[1] == "bet": - firstPfRaiseByNo = i - firstPfRaiserId = action[0] - for j, pid in enumerate(player_ids): - if pid == firstPfRaiserId: - firstPfRaiserNo = j - break - break - for i, action in enumerate(actionTypeByNo[0]): - if action[1] == "call": - firstPfCallByNo = i - firstPfCallerId = action[0] - break - firstPlayId = firstPfCallerId - if firstPfRaiseByNo <> -1: - if firstPfRaiseByNo < firstPfCallByNo or firstPfCallByNo == -1: - firstPlayId = firstPfRaiserId - - - cutoffId=-1 - buttonId=-1 - sbId=-1 - bbId=-1 - if base=="hold": - for player, pos in enumerate(positions): - if pos == 1: - cutoffId = player_ids[player] - if pos == 0: - buttonId = player_ids[player] - if pos == 'S': - sbId = player_ids[player] - if pos == 'B': - bbId = player_ids[player] - - someoneStole=False - - #run a loop for each player preparing the actual values that will be commited to SQL - for player in xrange(len(player_ids)): - #set default values - myStreet0VPI=False - myStreet0Aggr=False - myStreet0_3BChance=False - myStreet0_3BDone=False - myStreet1Seen=False - myStreet2Seen=False - myStreet3Seen=False - myStreet4Seen=False - mySawShowdown=False - myStreet1Aggr=False - myStreet2Aggr=False - myStreet3Aggr=False - myStreet4Aggr=False - myOtherRaisedStreet1=False - myOtherRaisedStreet2=False - myOtherRaisedStreet3=False - myOtherRaisedStreet4=False - myFoldToOtherRaisedStreet1=False - myFoldToOtherRaisedStreet2=False - myFoldToOtherRaisedStreet3=False - myFoldToOtherRaisedStreet4=False - myWonWhenSeenStreet1=0.0 - myWonAtSD=0.0 - myStealAttemptChance=False - myStealAttempted=False - myStreet0Calls=0 - myStreet1Calls=0 - myStreet2Calls=0 - myStreet3Calls=0 - myStreet4Calls=0 - myStreet0Bets=0 - myStreet1Bets=0 - myStreet2Bets=0 - myStreet3Bets=0 - myStreet4Bets=0 - #myStreet0Raises=0 - #myStreet1Raises=0 - #myStreet2Raises=0 - #myStreet3Raises=0 - #myStreet4Raises=0 - - #calculate VPIP and PFR - street=0 - heroPfRaiseCount=0 - for currentAction in action_types[street][player]: # finally individual actions - if currentAction == "bet": - myStreet0Aggr = True - if currentAction == "bet" or currentAction == "call": - myStreet0VPI = True - - if myStreet0VPI: - result['playersVpi'] += 1 - myStreet0Calls = action_types[street][player].count('call') - myStreet0Bets = action_types[street][player].count('bet') - # street0Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street0Raises'] += myStreet0Bets - - #PF3BChance and PF3B - pfFold=-1 - pfRaise=-1 - if firstPfRaiseByNo != -1: - for i, actionType in enumerate(actionTypeByNo[0]): - if actionType[0] == player_ids[player]: - if actionType[1] == "bet" and pfRaise == -1 and i > firstPfRaiseByNo: - pfRaise = i - if actionType[1] == "fold" and pfFold == -1: - pfFold = i - if pfFold == -1 or pfFold > firstPfRaiseByNo: - myStreet0_3BChance = True - if pfRaise > firstPfRaiseByNo: - myStreet0_3BDone = True - - #steal calculations - if base=="hold": - if len(player_ids)>=3: # no point otherwise # was 5, use 3 to match pokertracker definition - if positions[player]==1: - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==cutoffId or firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]==0: - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==buttonId or firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]=='S': - if firstPfRaiserId==player_ids[player] \ - and (firstPfCallByNo==-1 or firstPfCallByNo>firstPfRaiseByNo): - myStealAttempted=True - myStealAttemptChance=True - if firstPlayId==sbId or firstPlayId==bbId or firstPlayId==-1: - myStealAttemptChance=True - if positions[player]=='B': - pass - - if myStealAttempted: - someoneStole=True - - - #calculate saw* values - isAllIn = any(i for i in allIns[0][player]) - if isAllIn or len(action_types[1][player]) > 0: - myStreet1Seen = True - - if not isAllIn: - isAllIn = any(i for i in allIns[1][player]) - if isAllIn or len(action_types[2][player]) > 0: - if all(actiontype != "fold" for actiontype in action_types[1][player]): - myStreet2Seen = True - - if not isAllIn: - isAllAin = any(i for i in allIns[2][player]) - if isAllIn or len(action_types[3][player]) > 0: - if all(actiontype != "fold" for actiontype in action_types[2][player]): - myStreet3Seen = True - - #print "base:", base - if base == "hold": - mySawShowdown = not any(actiontype == "fold" for actiontype in action_types[3][player]) - else: - #print "in else" - if not isAllIn: - isAllIn = any(i for i in allIns[3][player]) - if isAllIn or len(action_types[4][player]) > 0: - #print "in if" - myStreet4Seen = True - - mySawShowdown = not any(actiontype == "fold" for actiontype in action_types[4][player]) - - if myStreet1Seen: - result['playersAtStreet1'] += 1 - if myStreet2Seen: - result['playersAtStreet2'] += 1 - if myStreet3Seen: - result['playersAtStreet3'] += 1 - if myStreet4Seen: - result['playersAtStreet4'] += 1 - if mySawShowdown: - result['playersAtShowdown'] += 1 - - #flop stuff - street = 1 - if myStreet1Seen: - myStreet1Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet1Calls = action_types[street][player].count('call') - myStreet1Bets = action_types[street][player].count('bet') - # street1Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street1Raises'] += myStreet1Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet1 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet1 = True - - #turn stuff - copy of flop with different vars - street = 2 - if myStreet2Seen: - myStreet2Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet2Calls = action_types[street][player].count('call') - myStreet2Bets = action_types[street][player].count('bet') - # street2Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street2Raises'] += myStreet2Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet2 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet2 = True - - #river stuff - copy of flop with different vars - street = 3 - if myStreet3Seen: - myStreet3Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet3Calls = action_types[street][player].count('call') - myStreet3Bets = action_types[street][player].count('bet') - # street3Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street3Raises'] += myStreet3Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet3 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet3 = True - - #stud river stuff - copy of flop with different vars - street = 4 - if myStreet4Seen: - myStreet4Aggr = any(actiontype == "bet" for actiontype in action_types[street][player]) - myStreet4Calls = action_types[street][player].count('call') - myStreet4Bets = action_types[street][player].count('bet') - # street4Raises = action_types[street][player].count('raise') bet count includes raises for now - result['street4Raises'] += myStreet4Bets - - for otherPlayer in xrange(len(player_ids)): - if player == otherPlayer: - pass - else: - for countOther in xrange(len(action_types[street][otherPlayer])): - if action_types[street][otherPlayer][countOther] == "bet": - myOtherRaisedStreet4 = True - for countOtherFold in xrange(len(action_types[street][player])): - if action_types[street][player][countOtherFold] == "fold": - myFoldToOtherRaisedStreet4 = True - - if winnings[player] != 0: - if myStreet1Seen: - myWonWhenSeenStreet1 = winnings[player] / float(totalWinnings) - if mySawShowdown: - myWonAtSD = myWonWhenSeenStreet1 - - #add each value to the appropriate array - street0VPI.append(myStreet0VPI) - street0Aggr.append(myStreet0Aggr) - street0_3BChance.append(myStreet0_3BChance) - street0_3BDone.append(myStreet0_3BDone) - street1Seen.append(myStreet1Seen) - street2Seen.append(myStreet2Seen) - street3Seen.append(myStreet3Seen) - street4Seen.append(myStreet4Seen) - sawShowdown.append(mySawShowdown) - street1Aggr.append(myStreet1Aggr) - street2Aggr.append(myStreet2Aggr) - street3Aggr.append(myStreet3Aggr) - street4Aggr.append(myStreet4Aggr) - otherRaisedStreet1.append(myOtherRaisedStreet1) - otherRaisedStreet2.append(myOtherRaisedStreet2) - otherRaisedStreet3.append(myOtherRaisedStreet3) - otherRaisedStreet4.append(myOtherRaisedStreet4) - foldToOtherRaisedStreet1.append(myFoldToOtherRaisedStreet1) - foldToOtherRaisedStreet2.append(myFoldToOtherRaisedStreet2) - foldToOtherRaisedStreet3.append(myFoldToOtherRaisedStreet3) - foldToOtherRaisedStreet4.append(myFoldToOtherRaisedStreet4) - wonWhenSeenStreet1.append(myWonWhenSeenStreet1) - wonAtSD.append(myWonAtSD) - stealAttemptChance.append(myStealAttemptChance) - stealAttempted.append(myStealAttempted) - if base=="hold": - pos=positions[player] - if pos=='B': - hudDataPositions.append('B') - elif pos=='S': - hudDataPositions.append('S') - elif pos==0: - hudDataPositions.append('D') - elif pos==1: - hudDataPositions.append('C') - elif pos>=2 and pos<=4: - hudDataPositions.append('M') - elif pos>=5 and pos<=8: - hudDataPositions.append('E') - ### RHH Added this elif to handle being a dead hand before the BB (pos==9) - elif pos==9: - hudDataPositions.append('X') - else: - raise FpdbError("invalid position") - elif base=="stud": - #todo: stud positions and steals - pass - - street0Calls.append(myStreet0Calls) - street1Calls.append(myStreet1Calls) - street2Calls.append(myStreet2Calls) - street3Calls.append(myStreet3Calls) - street4Calls.append(myStreet4Calls) - street0Bets.append(myStreet0Bets) - street1Bets.append(myStreet1Bets) - street2Bets.append(myStreet2Bets) - street3Bets.append(myStreet3Bets) - street4Bets.append(myStreet4Bets) - #street0Raises.append(myStreet0Raises) - #street1Raises.append(myStreet1Raises) - #street2Raises.append(myStreet2Raises) - #street3Raises.append(myStreet3Raises) - #street4Raises.append(myStreet4Raises) - - #add each array to the to-be-returned dictionary - result['street0VPI']=street0VPI - result['street0Aggr']=street0Aggr - result['street0_3BChance']=street0_3BChance - result['street0_3BDone']=street0_3BDone - result['street1Seen']=street1Seen - result['street2Seen']=street2Seen - result['street3Seen']=street3Seen - result['street4Seen']=street4Seen - result['sawShowdown']=sawShowdown - - result['street1Aggr']=street1Aggr - result['otherRaisedStreet1']=otherRaisedStreet1 - result['foldToOtherRaisedStreet1']=foldToOtherRaisedStreet1 - result['street2Aggr']=street2Aggr - result['otherRaisedStreet2']=otherRaisedStreet2 - result['foldToOtherRaisedStreet2']=foldToOtherRaisedStreet2 - result['street3Aggr']=street3Aggr - result['otherRaisedStreet3']=otherRaisedStreet3 - result['foldToOtherRaisedStreet3']=foldToOtherRaisedStreet3 - result['street4Aggr']=street4Aggr - result['otherRaisedStreet4']=otherRaisedStreet4 - result['foldToOtherRaisedStreet4']=foldToOtherRaisedStreet4 - result['wonWhenSeenStreet1']=wonWhenSeenStreet1 - result['wonAtSD']=wonAtSD - result['stealAttemptChance']=stealAttemptChance - result['stealAttempted']=stealAttempted - result['street0Calls']=street0Calls - result['street1Calls']=street1Calls - result['street2Calls']=street2Calls - result['street3Calls']=street3Calls - result['street4Calls']=street4Calls - result['street0Bets']=street0Bets - result['street1Bets']=street1Bets - result['street2Bets']=street2Bets - result['street3Bets']=street3Bets - result['street4Bets']=street4Bets - #result['street0Raises']=street0Raises - #result['street1Raises']=street1Raises - #result['street2Raises']=street2Raises - #result['street3Raises']=street3Raises - #result['street4Raises']=street4Raises - - #now the various steal values - foldBbToStealChance=[] - foldedBbToSteal=[] - foldSbToStealChance=[] - foldedSbToSteal=[] - for player in xrange(len(player_ids)): - myFoldBbToStealChance=False - myFoldedBbToSteal=False - myFoldSbToStealChance=False - myFoldedSbToSteal=False - - if base=="hold": - if someoneStole and (positions[player]=='B' or positions[player]=='S') and firstPfRaiserId!=player_ids[player]: - street=0 - for count in xrange(len(action_types[street][player])):#individual actions - if positions[player]=='B': - myFoldBbToStealChance=True - if action_types[street][player][count]=="fold": - myFoldedBbToSteal=True - if positions[player]=='S': - myFoldSbToStealChance=True - if action_types[street][player][count]=="fold": - myFoldedSbToSteal=True - - - foldBbToStealChance.append(myFoldBbToStealChance) - foldedBbToSteal.append(myFoldedBbToSteal) - foldSbToStealChance.append(myFoldSbToStealChance) - foldedSbToSteal.append(myFoldedSbToSteal) - result['foldBbToStealChance']=foldBbToStealChance - result['foldedBbToSteal']=foldedBbToSteal - result['foldSbToStealChance']=foldSbToStealChance - result['foldedSbToSteal']=foldedSbToSteal - - #now CB - street1CBChance=[] - street1CBDone=[] - didStreet1CB=[] - for player in xrange(len(player_ids)): - myStreet1CBChance=False - myStreet1CBDone=False - - if street0VPI[player]: - myStreet1CBChance=True - if street1Aggr[player]: - myStreet1CBDone=True - didStreet1CB.append(player_ids[player]) - - street1CBChance.append(myStreet1CBChance) - street1CBDone.append(myStreet1CBDone) - result['street1CBChance']=street1CBChance - result['street1CBDone']=street1CBDone - - #now 2B - street2CBChance=[] - street2CBDone=[] - didStreet2CB=[] - for player in xrange(len(player_ids)): - myStreet2CBChance=False - myStreet2CBDone=False - - if street1CBDone[player]: - myStreet2CBChance=True - if street2Aggr[player]: - myStreet2CBDone=True - didStreet2CB.append(player_ids[player]) - - street2CBChance.append(myStreet2CBChance) - street2CBDone.append(myStreet2CBDone) - result['street2CBChance']=street2CBChance - result['street2CBDone']=street2CBDone - - #now 3B - street3CBChance=[] - street3CBDone=[] - didStreet3CB=[] - for player in xrange(len(player_ids)): - myStreet3CBChance=False - myStreet3CBDone=False - - if street2CBDone[player]: - myStreet3CBChance=True - if street3Aggr[player]: - myStreet3CBDone=True - didStreet3CB.append(player_ids[player]) - - street3CBChance.append(myStreet3CBChance) - street3CBDone.append(myStreet3CBDone) - result['street3CBChance']=street3CBChance - result['street3CBDone']=street3CBDone - - #and 4B - street4CBChance=[] - street4CBDone=[] - didStreet4CB=[] - for player in xrange(len(player_ids)): - myStreet4CBChance=False - myStreet4CBDone=False - - if street3CBDone[player]: - myStreet4CBChance=True - if street4Aggr[player]: - myStreet4CBDone=True - didStreet4CB.append(player_ids[player]) - - street4CBChance.append(myStreet4CBChance) - street4CBDone.append(myStreet4CBDone) - result['street4CBChance']=street4CBChance - result['street4CBDone']=street4CBDone - - - result['position']=hudDataPositions - - foldToStreet1CBChance=[] - foldToStreet1CBDone=[] - foldToStreet2CBChance=[] - foldToStreet2CBDone=[] - foldToStreet3CBChance=[] - foldToStreet3CBDone=[] - foldToStreet4CBChance=[] - foldToStreet4CBDone=[] - - for player in xrange(len(player_ids)): - myFoldToStreet1CBChance=False - myFoldToStreet1CBDone=False - foldToStreet1CBChance.append(myFoldToStreet1CBChance) - foldToStreet1CBDone.append(myFoldToStreet1CBDone) - - myFoldToStreet2CBChance=False - myFoldToStreet2CBDone=False - foldToStreet2CBChance.append(myFoldToStreet2CBChance) - foldToStreet2CBDone.append(myFoldToStreet2CBDone) - - myFoldToStreet3CBChance=False - myFoldToStreet3CBDone=False - foldToStreet3CBChance.append(myFoldToStreet3CBChance) - foldToStreet3CBDone.append(myFoldToStreet3CBDone) - - myFoldToStreet4CBChance=False - myFoldToStreet4CBDone=False - foldToStreet4CBChance.append(myFoldToStreet4CBChance) - foldToStreet4CBDone.append(myFoldToStreet4CBDone) - - if len(didStreet1CB)>=1: - generateFoldToCB(1, player_ids, didStreet1CB, street1CBDone, foldToStreet1CBChance, foldToStreet1CBDone, actionTypeByNo) - - if len(didStreet2CB)>=1: - generateFoldToCB(2, player_ids, didStreet2CB, street2CBDone, foldToStreet2CBChance, foldToStreet2CBDone, actionTypeByNo) - - if len(didStreet3CB)>=1: - generateFoldToCB(3, player_ids, didStreet3CB, street3CBDone, foldToStreet3CBChance, foldToStreet3CBDone, actionTypeByNo) - - if len(didStreet4CB)>=1: - generateFoldToCB(4, player_ids, didStreet4CB, street4CBDone, foldToStreet4CBChance, foldToStreet4CBDone, actionTypeByNo) - - result['foldToStreet1CBChance']=foldToStreet1CBChance - result['foldToStreet1CBDone']=foldToStreet1CBDone - result['foldToStreet2CBChance']=foldToStreet2CBChance - result['foldToStreet2CBDone']=foldToStreet2CBDone - result['foldToStreet3CBChance']=foldToStreet3CBChance - result['foldToStreet3CBDone']=foldToStreet3CBDone - result['foldToStreet4CBChance']=foldToStreet4CBChance - result['foldToStreet4CBDone']=foldToStreet4CBDone - - - totalProfit=[] - - street1CheckCallRaiseChance=[] - street1CheckCallRaiseDone=[] - street2CheckCallRaiseChance=[] - street2CheckCallRaiseDone=[] - street3CheckCallRaiseChance=[] - street3CheckCallRaiseDone=[] - street4CheckCallRaiseChance=[] - street4CheckCallRaiseDone=[] - #print "b4 totprof calc, len(playerIds)=", len(player_ids) - for pl in xrange(len(player_ids)): - #print "pl=", pl - myTotalProfit=winnings[pl] # still need to deduct other costs - if antes: - myTotalProfit=winnings[pl] - antes[pl] - for i in xrange(len(actionTypes)): #iterate through streets - #for j in xrange(len(actionTypes[i])): #iterate through names (using pl loop above) - for k in xrange(len(actionTypes[i][pl])): #iterate through individual actions of that player on that street - myTotalProfit -= actionAmounts[i][pl][k] - - myStreet1CheckCallRaiseChance=False - myStreet1CheckCallRaiseDone=False - myStreet2CheckCallRaiseChance=False - myStreet2CheckCallRaiseDone=False - myStreet3CheckCallRaiseChance=False - myStreet3CheckCallRaiseDone=False - myStreet4CheckCallRaiseChance=False - myStreet4CheckCallRaiseDone=False - - #print "myTotalProfit=", myTotalProfit - totalProfit.append(myTotalProfit) - #print "totalProfit[]=", totalProfit - - street1CheckCallRaiseChance.append(myStreet1CheckCallRaiseChance) - street1CheckCallRaiseDone.append(myStreet1CheckCallRaiseDone) - street2CheckCallRaiseChance.append(myStreet2CheckCallRaiseChance) - street2CheckCallRaiseDone.append(myStreet2CheckCallRaiseDone) - street3CheckCallRaiseChance.append(myStreet3CheckCallRaiseChance) - street3CheckCallRaiseDone.append(myStreet3CheckCallRaiseDone) - street4CheckCallRaiseChance.append(myStreet4CheckCallRaiseChance) - street4CheckCallRaiseDone.append(myStreet4CheckCallRaiseDone) - - result['totalProfit']=totalProfit - #print "res[totalProfit]=", result['totalProfit'] - - result['street1CheckCallRaiseChance']=street1CheckCallRaiseChance - result['street1CheckCallRaiseDone']=street1CheckCallRaiseDone - result['street2CheckCallRaiseChance']=street2CheckCallRaiseChance - result['street2CheckCallRaiseDone']=street2CheckCallRaiseDone - result['street3CheckCallRaiseChance']=street3CheckCallRaiseChance - result['street3CheckCallRaiseDone']=street3CheckCallRaiseDone - result['street4CheckCallRaiseChance']=street4CheckCallRaiseChance - result['street4CheckCallRaiseDone']=street4CheckCallRaiseDone - return result -#end def generateHudCacheData - -def generateFoldToCB(street, playerIDs, didStreetCB, streetCBDone, foldToStreetCBChance, foldToStreetCBDone, actionTypeByNo): - """fills the passed foldToStreetCB* arrays appropriately depending on the given street""" - #print "beginning of generateFoldToCB, street:", street, "len(actionTypeByNo):", len(actionTypeByNo) - #print "len(actionTypeByNo[street]):",len(actionTypeByNo[street]) - firstCBReaction=0 - for action in xrange(len(actionTypeByNo[street])): - if actionTypeByNo[street][action][1]=="bet": - for player in didStreetCB: - if player==actionTypeByNo[street][action][0] and firstCBReaction==0: - firstCBReaction=action+1 - break - - for action in actionTypeByNo[street][firstCBReaction:]: - for player in xrange(len(playerIDs)): - if playerIDs[player]==action[0]: - foldToStreetCBChance[player]=True - if action[1]=="fold": - foldToStreetCBDone[player]=True -#end def generateFoldToCB diff --git a/pyfpdb/test_PokerStars.py b/pyfpdb/test_PokerStars.py index 18a9f556..72c9049c 100644 --- a/pyfpdb/test_PokerStars.py +++ b/pyfpdb/test_PokerStars.py @@ -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 diff --git a/pyfpdb/test_fpdb_simple.py b/pyfpdb/test_fpdb_simple.py deleted file mode 100755 index 3d9615cb..00000000 --- a/pyfpdb/test_fpdb_simple.py +++ /dev/null @@ -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 -