def test_cards_to_hand(self): hand = PSHandHistory.cards_to_hand('As Qd') self.assertEqual(hand, 'AQo') hand = PSHandHistory.cards_to_hand('2s 2d') self.assertEqual(hand, '22') hand = PSHandHistory.cards_to_hand('Js Qd') self.assertEqual(hand, 'QJo') hand = PSHandHistory.cards_to_hand('5s Qs') self.assertEqual(hand, 'Q5s') hand = PSHandHistory.cards_to_hand('Qs 5c') self.assertEqual(hand, 'Q5o')
def test_co_reg_filter(): th = Path('cases/bb-not-reg.txt').read_text(encoding='utf-8') parsed = PSHandHistory(th) f = filters.CORegFilter() result = f(parsed, notes=notes, config=config) expected = False assert result == expected
def test_bu_fish_filter(): th = Path('cases/bb-not-reg.txt').read_text(encoding='utf-8') parsed = PSHandHistory(th) f = filters.BUFishFilter() result = f(parsed, notes=notes, config=config) expected = True assert result == expected
def test_co_fish_filter(): th = Path('cases/bb-not-reg.txt').read_text(encoding='utf-8') parsed = PSHandHistory(th) f = filters.COFishFilter() result = f(parsed, **{'notes': notes, 'config': config}) expected = True assert result == expected
def get_calc_results(hand_text: str) -> CalcResults: parsed_hand = PSHandHistory(hand_text) hero = parsed_hand.hero prize = get_prize_structure(parsed_hand) icm = Icm(prize) try: ev_calc = EV(parsed_hand, icm) ev_calc.calc(hero) ai_equity = round(ev_calc.get_probs(hero), 4) * 100 icm_ev_diff_cur = round(ev_calc.icm_ev_diff(), 2) icm_ev_diff = round(ev_calc.icm_ev_diff_pct(), 4) * 100 chip_ev_diff = round(ev_calc.chip_diff_ev_adj(), 0) chip_won = ev_calc.chip_net_won().get(hero, 0) chip_won_adj = chip_ev_diff + chip_won won_amount = round(parsed_hand.prize_won.get(hero, 0), 2) except Exception as e: logger.exception(f"Exception", exc_info=sys.exc_info()) rc = CalcResults( dt=parsed_hand.datetime, bi=parsed_hand.bi, hero_cards=parsed_hand.hero_cards, hero=parsed_hand.hero, h_id=parsed_hand.hid, prize=get_prize_structure(parsed_hand), ai_equity=ai_equity, icm_ev_diff_cur=icm_ev_diff_cur, icm_ev_diff=icm_ev_diff, chip_ev_diff=chip_ev_diff, chip_won=chip_won, chip_won_adj=chip_won_adj, won_amount=won_amount, t_id=parsed_hand.tid, ) return rc
def test_wrong_condition_bi(): hf = HandFilter() th = Path('cases/bb-not-reg.txt').read_text(encoding='utf-8') parsed = PSHandHistory(th) cond = Condition('xxbi', operator.gt, 14) hf.add_condition(cond, notes=notes, config=config) result = hf.check_conditions(parsed) expected = False assert result == expected
def test_condition_dt(): hf = HandFilter() th = Path('cases/bb-not-reg.txt').read_text(encoding='utf-8') parsed = PSHandHistory(th) dt1 = datetime.datetime(2020, 4, 26, 13, 43) dt2 = datetime.datetime(2020, 4, 26, 13, 49) cond1 = Condition('datetime', operator.gt, dt1) cond2 = Condition('datetime', operator.lt, dt2) hf.add_condition(cond1) hf.add_condition(cond2) result = hf.check_conditions(parsed) expected = True assert result == expected
def test_hand_filter_match_3conditions(): hf = HandFilter() th = Path('cases/bb-not-reg.txt').read_text(encoding='utf-8') parsed = PSHandHistory(th) f1 = filters.SBRegFilter() f2 = filters.BBFishFilter() f3 = filters.BUFishFilter() hf.add_condition(f1, notes=notes, config=config) hf.add_condition(f2, notes=notes, config=config) hf.add_condition(f3, notes=notes, config=config) result = hf.check_conditions(parsed) expected = True assert result == expected
def test_multi_condition_bi(): hf = HandFilter() th = Path('cases/bb-not-reg.txt').read_text(encoding='utf-8') parsed = PSHandHistory(th) cond1 = Condition('bi', operator.gt, 14) cond2 = Condition('hero', operator.eq, "DiggErr555") cond3 = Condition('bi', operator.lt, 26) hf.add_condition(cond1, notes=notes, config=config) hf.add_condition(cond2, notes=notes, config=config) hf.add_condition(cond3, notes=notes, config=config) result = hf.check_conditions(parsed) expected = True assert result == expected
def test__process_regexp(self): # TODO more tests on _process_regexp ACTIONS_AMOUNTS_REGEX = "(?P<player>.*?): (?:calls|raises.*to|bets|checks) (?P<amount>\d+)?" ACTIONS_AMOUNTS_DICT = {'player': 'amount'} parsed_hand = get_parsed_hand_from_file( "hh/sat16/round1/hu-ai-postflop.txt") hand_txt = parsed_hand.preflop_str print(hand_txt) res = PSHandHistory._process_regexp("", ACTIONS_AMOUNTS_REGEX, hand_txt, type_func=lambda x: int(x), reslist=True, **ACTIONS_AMOUNTS_DICT) self.assertDictEqual(res, {'NL_Classic': [50], 'Smdpair77': [0]})
def sort(self, options): # this script filters hh of sats with 4 playrs tables, suits for 4max and for 3max # checking input and output directories try: input_path = get_path_dir_or_error(options.input_dir) except RuntimeError: self.statusBar().showMessage( 'Place hand history files in "input" directory') return output_dir_path = get_path_dir_or_create(options.output_dir) storage = HandStorage(input_path) result = [] total = len(list(storage.read_hand())) counter = 0 skipped = 0 hands_write_query = [] self.progressBar.reset() self.progressBar.setRange(0, total) self.statusBar().showMessage('Sorting hands...') for txt in storage.read_hand(): try: hh = PSHandHistory(txt) except Exception as e: self.statusBar().showMessage("%s " % e) continue counter += 1 self.progressBar.setValue(counter) # TODO add filters # if not pass_filters(hh, options): # continue try: pos_str = get_positions_str(hh) except RuntimeError: continue entry = HandWriteEntry(output_dir_path.joinpath(pos_str), hh.hid + '.txt', txt) hands_write_query.append(entry) self.progressBar.setValue(total) self.save_hands(hands_write_query) self.statusBar().showMessage( f'Total hands processed: {counter}, skipped: {skipped}')
def get_dt_from_hh(hh: str): """returns (dd, mm, yy) from hand history file""" s = hh.split('\n\n') # determine date and time by first hand in tournament hh = None dt = datetime.now() for text in s: try: # if None or empty string take next element if not bool(text and text.strip()): continue # print(f'text: {text}') hh = PSHandHistory(text) dt = hh.datetime break except Exception as e: logger.exception('hand id: %s, tournament id: %s', hh.hid, hh.tid) return dt
def process_hands(self, hands, file, notes, options, hand_filter, path, hands_write_query, by_position=False): new_path = Path(path) for txt in hands: if bool(txt and txt.strip()): pos_str = '0' try: parsed = PSHandHistory(txt) dd, mm, yy = get_ddmmyy_from_dt(parsed.datetime) except Exception as e: logger.exception('Exception %s while parsing file: %s', e, file) logger.debug("hid: " + str(parsed.hid)) logger.debug("hh: " + parsed.hand_history) continue if hand_filter.check_conditions(parsed, notes=notes, config=options): if by_position: try: pos_str = get_positions_str(parsed) new_path = path.joinpath(pos_str) except (RuntimeError, KeyError) as e: logger.exception( 'Exception %s in get_position_str in file: %s', e, file) continue self.append_write_entry(new_path, yy, mm, dd, parsed, txt, hands_write_query)
def get_parsed_hand_from_file(fn): with open(fn) as f: hh_text = f.read() parsed_hand = PSHandHistory(hh_text) return parsed_hand
def setUp(self): self.case0 = PSHandHistory(th) # self.case1 = PSHandHistory(th1) self.case2 = PSHandHistory(th2) # self.case3 = PSHandHistory(th3) self.case4 = PSHandHistory(th4) self.case5 = PSHandHistory(th5) self.case6 = PSHandHistory(th6) self.case7 = PSHandHistory(th7) self.case8 = PSHandHistory(th8) self.case9 = PSHandHistory(th9) #2 bounty won case self.case10 = PSHandHistory(th10) #3 bounty won case self.auto_ai_case = PSHandHistory(auto_ai_th) self.case11 = PSHandHistory(debug_hrcparser)
def main(): logging.basicConfig( format='[%(asctime)s] %(levelname).1s %(message)s', datefmt='%Y.%m.%d %H:%M:%S', level=logging.INFO ) args = parse_arguments() load_config(config, args.config) logging.info('Start...') notes = load_ps_notes(config['NOTES_FILE']) logging.info('Player notes loaded...') hero = config['HERO'] storage = hand_storage.HandStoragePgsql(dbname='nolim 2.3.0 04-12-2017', user='******', host='127.0.0.1', port='5318', pwd='') # storage = hand_storage.HandStorage('hands/debug') results_icm = {} results_bounty = {} tournaments = {} finishes = {} logging.info('Selecting hands...') for hand in storage.read_hand(start_date=config['START_DATE'], end_date=config['END_DATE']): # for hand in storage.read_hand(): try: hh = PSHandHistory(hand) except Exception as e: logging.info(hh) logging.info(e) continue if hh.hero != hero: continue if hh.bi not in (10.0, 25.0, 5.0, 100.0, 50.0): continue if tournaments.get(hh.tid) is None: # if len(hh.players) == 6: tournaments[hh.tid] = [[hh.bi, hh.datetime, fish_per_table(hh.players, notes), hh.bounty]] results_icm[hh.tid] = -hh.bi + hh.prize_won.get(hero, 0) results_bounty[hh.tid] = hh.bounty_won.get(hero, 0) else: tournaments[hh.tid].append([hh.bi, hh.datetime, fish_per_table(hh.players, notes), hh.bounty]) results_icm[hh.tid] += hh.prize_won.get(hero, 0) results_bounty[hh.tid] += hh.bounty_won.get(hero, 0) if hh.finishes.get(hero): finishes[hh.tid] = hh.finishes.get(hero) # logging.info(f'{results_bounty[hh.tid]} {hh.hid} {hh.datetime}') logging.info('Calculating statistics') results = [] for tour, value in tournaments.items(): if finishes.get(tour) is None: ts_text = storage.read_summary(tour) if ts_text: ts = PSTournamentSummary(ts_text) finishes[tour] = ts.finishes results_icm[tour] += ts.prize_won.get(hero, 0) if ts.finishes == 1: logging.info(results_bounty[tour]) results_bounty[tour] += value[0][3] * 2 results.append([tour, value[0][0], min([_[1] for _ in value]), max([_[2] for _ in value]), results_icm[tour], results_bounty[tour], results_icm[tour] + results_bounty[tour], finishes.get(tour, 0), len(value) ]) if results: logging.info('Saving results...') df = pd.DataFrame(results) columns = ['tid', 'bi', 'date', 'fish', 'prize_won', 'bounty_won', 'total_won', 'finishes', 'hands'] df.to_csv(f'results {config["START_DATE"]} {config["END_DATE"]}.csv', header=columns) logging.info('Success') else: logging.info('No tournament results found!')
def sort_by_tournament_position(options): # this script filters hh of sats with 4 playrs tables, suits for 4max and for 3max try: storage = HandStorage(options.input_dir) except IOError: logging.exception('Invalid input dir') try: storage = HandStorage(CWD.joinpath(DEFAULT_INPIT_DIR)) except IOError: logging.exception('Default input dir doesnt exists') return output_dir_path = get_path_dir_or_create(options.output_dir) result = [] pos_codes = set() total = len(list(storage.read_hand())) counter = 0 logging.info('Sorting hands...') printProgressBar(counter, total) for txt in storage.read_hand(): try: hh = PSHandHistory(txt) except Exception as e: logging.exception("%s " % e) continue counter += 1 printProgressBar(counter, total) if not pass_filters(hh, options): continue positions = hh.positions() player_pos = { pos: hh.tournamentPosition(player) for player, pos in positions.items() } # for now only for 4 and 3 max if hh.players_number() == 4: pos_str = str(player_pos['CO']) + str(player_pos['BU']) + str( player_pos['SB']) + str(player_pos['BB']) elif hh.players_number() == 3: pos_str = str(player_pos['BU']) + str(player_pos['SB']) + str( player_pos['BB']) else: continue # for ex. "1234" if CO has 1 stack BU 2 stack SB -3 BB -4 pos_codes.add(pos_str) result_row = {'pos_code': pos_str, 'txt': txt, 'fn': hh.hid} result.append(result_row) # create all possible output directories from pos_codes for pos_code in pos_codes: pos_code_dir_path = output_dir_path.joinpath(pos_code) if not pos_code_dir_path.exists(): pos_code_dir_path.mkdir() counter = 0 total = len(result) logging.info('Saving results...') printProgressBar(counter, total) for row in result: res_dir_path = output_dir_path.joinpath(row['pos_code']) res_file_path = res_dir_path.joinpath(row['fn']).with_suffix('.txt') res_file_path.write_text(row['txt'], encoding='utf-8') counter += 1 printProgressBar(counter, total)