//
//  Feral Cow Poker Hand History Converter
//
//  July 2009
//  by vbnautilus & qyayqi
//
//  Copyright 2009.  All rights reserved. 
//  You are not permitted to distribute, copy, or otherwise use this code without
//  the expressed permission of its authors.  
//
var version = "1.11";

var debug = 0;

var PSTARS = 0;
var FTP = 1;
var CEREUS = 2;
var HEM = 3;
var RPM = 4;

var reBlinds = new Array();
reBlinds[PSTARS] = /[\$|\(]?([\d|,|\.]+)\/[\$]?([\d|,|\.]+)[\)]?/;
reBlinds[FTP] = /[\$]?([\d|,|\.]+)\/[\$]?([\d|,|\.]+)/;
reBlinds[CEREUS] = /[\$]?([\d|,|\.]+)\/[\$]?([\d|,|\.]+)/;
reBlinds[HEM] = /[\$]?([\d|,|\.]+)\/[\$]?([\d|,|\.]+)/;
reBlinds[RPM] = /[\$]?([\d|,|\.]+)\/[\$]?([\d|,|\.]+)/;

var reGameSize = new Array();
reGameSize[PSTARS] = /(\d+)-max/;
reGameSize[FTP] = /(\d+) max/;
reGameSize[CEREUS] = /(\d+)-max/;
reGameSize[HEM] = /(\d+)-max/;

var reAnteText = new Array();
reAnteText[PSTARS] = /(.*?)\*\*\*/;
reAnteText[FTP] = /(.*?)\*\*\*/;
reAnteText[CEREUS] = /(.*?)\*\*\* 3rd/;
reAnteText[HEM] = /(.*?)\*\* Dealing down/;
reAnteText[RPM] = /(.*?)<round id=\"PREFLOP\"/;

var reAnteLines = new Array();
reAnteLines[PSTARS] = /posts the ante [\$]?([\d|,|\.]+)/;
reAnteLines[FTP] = / antes [\$]?([\d|,|\.]+)/;
reAnteLines[CEREUS] = / - Ante [\$]?([\d|,|\.]+)/;
reAnteLines[HEM] = / posts ante of \[[\$]?([\d|,|\.]+)/;

var reSeatingText = new Array();
reSeatingText[PSTARS] = /(.*?)\*\*\* /;
reSeatingText[FTP] = /(.*?)\*\*\* /;
reSeatingText[CEREUS] = /(.*?)\*\*\* /;
reSeatingText[HEM] = /\■(.*)\*\* Dealing down/i;
reAnteText[RPM] = /(.*?)<round id=\"BLINDS\"/;

var reGameType = new Array();
reGameType[PSTARS] = /Tournament/;
reGameType[FTP] = /Seat.*\(\d/;
reGameType[CEREUS] = /Tournament/;
reGameType[HEM] = /Tournament/;
reGameType[RPM] = /Tournament/;

var reFindSeats = new Array();
reFindSeats[PSTARS] = /(Seat \d+)\: .*chips\)/g;
reFindSeats[FTP] = /(Seat \d+)\: .*/g;
reFindSeats[CEREUS] = /(Seat \d+) -.*chips\)/g;
reFindSeats[HEM] = /(Seat \d+)\: .* \( [\$]?([\d|,|\.]+)/g;
reFindSeats[RPM] = /<(player seat=\"\d+\")/g;

var reFindInfo = new Array();
reFindInfo[PSTARS] = /Seat \d+\:.*/g;
reFindInfo[FTP] = /Seat \d+\: .*/g;
reFindInfo[CEREUS] = /Seat \d+ - .*/g;
reFindInfo[HEM] = /Seat \d+\: .*/g;
reFindSeats[RPM] = /<player seat=\"\d+\" .*/g;

var rePlayerInfo = new Array();
rePlayerInfo[PSTARS] = /Seat (\d+)\: (.*) \([\$]?([\d|,|\.]+) in chips\)/;
rePlayerInfo[FTP] = /Seat (\d+)\: (.*) \([\$]?([\d|,|\.]+)\)/;
rePlayerInfo[CEREUS] = /Seat (\d+) - (.*) \([\$]?([\d|,|\.]+) in chips\)/;
rePlayerInfo[HEM] = /Seat (\d+)\: (.*) \( [\$]?([\d|,|\.]+) \S* \)/;
rePlayerInfo[RPM] = /<player seat=\"(\d+)\" nickname=\"(.*)\" balance=\"[\$]?([\d|,|.])\"/;

var reButton = new Array();
reButton[PSTARS] = /Seat \#(\d+) is the button/;
reButton[FTP] = /The button is in seat \#(\d)/;
reButton[CEREUS] = /Seat \#(\d+) is the dealer/;
reButton[HEM] = /Seat (\d+) is the button/;
reButton[RPM] = /<players dealer=\"(\d+)\"/;

var reGetHandPre = new Array();
var reGetHandPost = new Array();
var reGetHandPost2 = new Array();

reGetHandPre[PSTARS] = "(?:Dealt to|Seat \\d+:) ";
reGetHandPre[FTP] = "(?:Dealt to|Seat \\d+:) ";
reGetHandPre[CEREUS] = "(?:Seat \\d+: )?";
reGetHandPre[HEM] = "(?:Dealt to|Seat \\d+:) ";
reGetHandPre[RPM] = "<cards type"

reGetHandPost[PSTARS] = " (\\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\]■)";
reGetHandPost[FTP] = " (\\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\] \\[[2-9TJQKA][hdsc]\\]■)";
reGetHandPost[CEREUS] = " - (?:Pocket) (\\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\]■)";

reGetHandPost2[PSTARS] = " (?:mucked |showed )?(\\[(.*)\\])";
reGetHandPost2[FTP] = " (?:mucked |showed )?(\\[(.*)\\])";
reGetHandPost2[CEREUS] = " - (?:Pocket |Shows )?(\\[(.*)\\])";

var reTDGetHandPost = new Array();
reTDGetHandPost[PSTARS] = "( \\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\]■)";

var reMatchCard = new Array();
reMatchCard[PSTARS] = /([2-9TJQKA][hdsc])/g;
reMatchCard[FTP] = /([2-9TJQKA][hdsc])/g;
reMatchCard[CEREUS] = /([2-9TJQKA][hdsc])/g;

var reStreetMatch = new Array();
var reStreetMatchAlt = new Array();
reStreetMatch[PSTARS] = new Array(/3rd STREET \*\*\*■(.*)\*\*\* 4th/i, /4th STREET \*\*\*■(.*)\*\*\* 5th/i, /5th STREET \*\*\*■(.*)\*\*\* 6th/i, /6th STREET \*\*\*■(.*)\*\*\* RIVER/i, /RIVER \*\*\*■(.*)\*\*\* show/i);
reStreetMatch[FTP] = new Array(/3rd STREET \*\*\*■(.*)\*\*\* 4th/i, /4th STREET \*\*\*■(.*)\*\*\* 5th/i, /5th STREET \*\*\*■(.*)\*\*\* 6th/i, /6th STREET \*\*\*■(.*)\*\*\* 7th STREET/i, /7th STREET \*\*\*■(.*)\*\*\* show/i);
reStreetMatch[CEREUS] = new Array(/3rd STREET \*\*\*■(.*)\*\*\* 4th/i, /4th STREET \*\*\*■(.*)\*\*\* 5th/i, /5th STREET \*\*\*■(.*)\*\*\* 6th/i, /6th STREET \*\*\*■(.*)\*\*\* RIVER/i, /RIVER \*\*\*■(.*)\*\*\* show/i);
reStreetMatchAlt[PSTARS] = new Array(/3rd STREET \*\*\*■(.*)\*\*\* sum/i, /4th STREET \*\*\*■(.*)\*\*\* sum/i, /5th STREET \*\*\*■(.*)\*\*\* sum/i, /6th STREET \*\*\*■(.*)\*\*\* sum/i, /RIVER \*\*\*■(.*)\*\*\* sum/i);
reStreetMatchAlt[FTP] = new Array(/3RD STREET \*\*\*■(.*)\*\*\* SUM/i, /4th STREET \*\*\*■(.*)\*\*\* sum/i, /5th STREET \*\*\*■(.*)\*\*\* sum/i, /6th STREET \*\*\*■(.*)\*\*\* sum/i, /7th STREET \*\*\*■(.*)\*\*\* sum/i);
reStreetMatchAlt[CEREUS] = new Array(/3rd STREET \*\*\*■(.*)\*\*\* sum/i, /4th STREET \*\*\*■(.*)\*\*\* sum/i, /5th STREET \*\*\*■(.*)\*\*\* sum/i, /6th STREET \*\*\*■(.*)\*\*\* sum/i, /RIVER \*\*\*■(.*)\*\*\* sum/i);

var reTDStreetMatch = new Array();
var reTDStreetMatchAlt = new Array();
reTDStreetMatch[PSTARS] = new Array(/DEALING HANDS \*\*\*■(.*)\*\*\* FIRST/i, /FIRST DRAW \*\*\*■(.*)\*\*\* SECOND/i, /SECOND DRAW \*\*\*■(.*)\*\*\* THIRD/i, /THIRD DRAW \*\*\*■(.*)\*\*\* SHOW/i);
reTDStreetMatchAlt[PSTARS] = new Array(/DEALING HANDS \*\*\*■(.*)\*\*\* sum/i, /FIRST DRAW \*\*\*■(.*)\*\*\* sum/i, /SECOND DRAW \*\*\*■(.*)\*\*\* sum/i, /THIRD DRAW \*\*\*■(.*)\*\*\* sum/i);

var reSDStreetMatch = new Array();
var reSDStreetMatchAlt = new Array();
reSDStreetMatch[PSTARS] = new Array(/DEALING HANDS \*\*\*■(.*?)■(.*?)\: (stands|discards)/i, /DEALING HANDS \*\*\*■.*?■(.*?\: (stands|discards) .*)■\*\*\* SHOW/i);
reSDStreetMatchAlt[PSTARS] = new Array(/DEALING HANDS \*\*\*■(.*?)■\*\*\* sum/i, /.*?■((.*?)\: (stands|discards) .*)■\*\*\* sum/i);

var reMatchSummary = new Array();
reMatchSummary[PSTARS] = /SUMMARY \*\*\*|(.*)/;
reMatchSummary[FTP] = /SUMMARY \*\*\*|(.*)/;
reMatchSummary[CEREUS] = /SUMMARY \*\*\*|(.*)/;
reMatchSummary[HEM] = /Dealing River \*\* \[ [2-9TJQKA][hdsc] \]■(.*)/;

var reSummaryExtraction1 = new Array();
reSummaryExtraction1[PSTARS] = /Seat \d+: (.*?) (?:\(small blind\) |\(big blind\) |\(button\) |\(dealer\) |)+(showed|mucked)(.*)/;
reSummaryExtraction1[FTP] = /Seat \d+: (.*?) (?:\(small blind\) |\(big blind\) |\(button\) |\(dealer\) |)+(showed|mucked|collected)(.*)/;
reSummaryExtraction1[CEREUS] = /Seat \d+: (.*?) (?:\(small blind\) |\(big blind\) |\(button\) |\(dealer\) |)+(showed|mucked|collected|won|(?:[A-Z]*:)lost)(.*)/;
reSummaryExtraction1[HEM] = /(.*) wins (.*) from main pot/;

var reHESummaryExtraction2 = new Array();
reHESummaryExtraction2[PSTARS] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)?(?: with )?(.*)?/;
reHESummaryExtraction2[FTP] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)?(?: with )?(.*)?/;
reHESummaryExtraction2[CEREUS] = /(.*?)(?:[:| ]with )(.*?)\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) /;
reHESummaryExtraction2[HEM] = /(.*) (?:shows|doesn\'t show) \[([2-9TJQKA][hdsc]), ([2-9TJQKA][hdsc]) \]/;

var reOSummaryExtraction2 = new Array();
reOSummaryExtraction2[PSTARS] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)?(?: with )?(.*)?/;
//reOSummaryExtraction2[PSTARS] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)?(?: with )?(.*)?/;
reOSummaryExtraction2[FTP] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)?(?: with )?(.*)?/;
reOSummaryExtraction2[CEREUS] = /(.*?)(?:[:| ]with )(.*?)\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) /;
reOSummaryExtraction2[HEM] = /(.*) (?:shows|doesn\'t show) \[([2-9TJQKA][hdsc]), ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) \]/;

var reTDSummaryExtraction2 = new Array();
reTDSummaryExtraction2[PSTARS] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)?(?: with )?(.*)?/;

var reStudSummaryExtraction2 = new Array();
reStudSummaryExtraction2[PSTARS] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)(?: with )(.*)/;
reStudSummaryExtraction2[FTP] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\](.*?)(?:with|\-)(.*)/;
reStudSummaryExtraction2[CEREUS] = /(.*?)(?:[:| ]with )(.*)\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) /;
reStudSummaryExtraction2[HEM]= / /;

var reTheMoney = new Array();
reTheMoney[PSTARS] = /\([\$]?([\d|,|\.]+)\)/;
reTheMoney[FTP] = /\([\$]?([\d|,|\.]+)\)/;
reTheMoney[CEREUS] = /\([\$]?([\d|,|\.]+)\)/;
reTheMoney[HEM] = / [\$]?([\d|,|\.]+) /;

var reRake = new Array();
reRake[PSTARS] = /Rake [\$]?([\d|,|\.]+)/;
reRake[FTP] = /Rake [\$]?([\d|,|\.]+)/;
reRake[CEREUS] = /Rake \([\$]?([\d|,|\.]+)\)/;

var reSmallBlind = new Array();
reSmallBlind[PSTARS] = /(.*)\: posts small blind [\$]?([\d|,|\.]+)/;
reSmallBlind[FTP] = /(.*) posts the small blind of [\$]?([\d|,|\.]+)/;
reSmallBlind[CEREUS] = /(.*) - Posts small blind [\$]?([\d|,|\.]+)/;
reSmallBlind[HEM] = /(.*) posts small blind \[[\$]?([\d|,|\.]+)/;

var reBigBlind = new Array();
reBigBlind[PSTARS] = /(.*)\: posts big blind [\$]?([\d|,|\.]+)/;
reBigBlind[FTP] = /(.*) posts the big blind of [\$]?([\d|,|\.]+)/;
reBigBlind[CEREUS] = /(.*) - Posts big blind [\$]?([\d|,|\.]+)/;
reBigBlind[HEM] = /(.*) posts big blind \[[\$]?([\d|,|\.]+)/;

var reOHoleCards = new Array();
reOHoleCards[PSTARS] = /Dealt to (.*) \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reOHoleCards[FTP] = /Dealt to (.*) \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reOHoleCards[CEREUS] = /Dealt to (.*) \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reOHoleCards[HEM] = /Dealt to (.*) \[ ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) \]/;

var reHEHoleCards = new Array();
reHEHoleCards[PSTARS] = /Dealt to (.*) \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reHEHoleCards[FTP] = /Dealt to (.*) \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reHEHoleCards[CEREUS] = /Dealt to (.*) \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reHEHoleCards[HEM] = /Dealt to (.*) \[ [ ]?([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) \]/;

var rePreflopAction = new Array();
rePreflopAction[PSTARS] = /HOLE CARDS \*\*\*■(.*)\*\*\* FLOP/;
rePreflopAction[FTP] = /HOLE CARDS \*\*\*■(.*)\*\*\* FLOP/;
rePreflopAction[CEREUS] = /POCKET CARDS \*\*\*■(.*)\*\*\* FLOP/;
rePreflopAction[HEM] = /Dealing down cards \*\*■(.*)\*\* Dealing Flop/;

var rePreflopActionAlt = new Array();
rePreflopActionAlt[PSTARS] = /HOLE CARDS \*\*\*■(.*)\*\*\* (?:SUM)/;
rePreflopActionAlt[FTP] = /HOLE CARDS \*\*\*■(.*)\*\*\* (?:SUM)/;
rePreflopActionAlt[CEREUS] = /POCKET CARDS \*\*\*■(.*)\*\*\* (?:SUM)/;
rePreflopActionAlt[HEM] = /Dealing down cards \*\*■(.*)■(?:.*?) wins /;

var reFlop = new Array();
reFlop[PSTARS] = /FLOP \*\*\* \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reFlop[FTP] = /FLOP \*\*\* \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reFlop[CEREUS] = /FLOP \*\*\* \[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reFlop[HEM] = /Dealing Flop \*\*\ \[ ([2-9TJQKA][hdsc]), ([2-9TJQKA][hdsc]), ([2-9TJQKA][hdsc]) \]/;

var reFlopRunIt = new Array();
reFlopRunIt[PSTARS] = "FLOP (\\d) \\*\\*\\* \\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\\]";
reFlopRunIt[FTP] = "FLOP (\\d) \\*\\*\\* \\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\\]";
reFlopRunIt[CEREUS] = "FLOP (\\d) \\*\\*\\* \\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\\]";
reFlopRunIt[HEM] = "Dealing Flop (\\d) \\*\\* \\[ ([2-9TJQKA][hdsc]), ([2-9TJQKA][hdsc]), ([2-9TJQKA][hdsc]) \\]";

var reFlopAction = new Array();
reFlopAction[PSTARS] = /FLOP \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:TURN)/;
reFlopAction[FTP] = /FLOP \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:TURN)/;
reFlopAction[CEREUS] = /FLOP \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:TURN)/;
reFlopAction[HEM] = /Dealing Flop \*\*\ \[ [2-9TJQKA][hdsc], [2-9TJQKA][hdsc], [2-9TJQKA][hdsc] \]■(.*)\*\* Dealing Turn/;

var reFlopActionAlt = new Array();
reFlopActionAlt[PSTARS] = /FLOP \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reFlopActionAlt[FTP] = /FLOP \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reFlopActionAlt[CEREUS] = /FLOP \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reFlopActionAlt[HEM] = /Dealing Flop \*\*\ \[ [2-9TJQKA][hdsc], [2-9TJQKA][hdsc], [2-9TJQKA][hdsc] \]■(.*)/;

var reTurn = new Array();
reTurn[PSTARS] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[([2-9TJQKA][hdsc])\]/;
reTurn[FTP] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[([2-9TJQKA][hdsc])\]/;
reTurn[CEREUS] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[([2-9TJQKA][hdsc])\]/;
reTurn[HEM] = /Dealing Turn \*\* \[ ([2-9TJQKA][hdsc]) \]/;

var reTurnRunIt = new Array();
reTurnRunIt[PSTARS] = "TURN (\\d) \\*\\*\\* \\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\] \\[([2-9TJQKA][hdsc])\\]";
reTurnRunIt[FTP] = "TURN (\\d) \\*\\*\\* \\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\] \\[([2-9TJQKA][hdsc])\\]";
reTurnRunIt[CEREUS] = "TURN (\\d) \\*\\*\\* \\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\] \\[([2-9TJQKA][hdsc])\\]";
reTurnRunIt[HEM] = "Dealing Turn (\\d) \\*\\* \\[ ([2-9TJQKA][hdsc]) \\]";

var reTurnAction = new Array();
reTurnAction[PSTARS] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:RIVER)/;
reTurnAction[FTP] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:RIVER)/;
reTurnAction[CEREUS] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:RIVER)/;
reTurnAction[HEM] = /Dealing Turn \*\* \[ [2-9TJQKA][hdsc] \]■(.*)\*\* (?:Dealing River)/;

var reTurnActionAlt = new Array();
reTurnActionAlt[PSTARS] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reTurnActionAlt[FTP] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reTurnActionAlt[CEREUS] = /TURN \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reTurnActionAlt[HEM] = /Dealing Turn \*\* \[ [2-9TJQKA][hdsc] \]■(.*)/;

var reRiver = new Array();
reRiver[PSTARS] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[([2-9TJQKA][hdsc])\]/;
reRiver[FTP] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[([2-9TJQKA][hdsc])\]/;
reRiver[CEREUS] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[([2-9TJQKA][hdsc])\]/;
reRiver[HEM] = /Dealing River \*\* \[ ([2-9TJQKA][hdsc]) \]/;

var reRiverRunIt = new Array();
reRiverRunIt[PSTARS] = "RIVER (\\d) \\*\\*\\* \\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\] \\[([2-9TJQKA][hdsc])\\]";
reRiverRunIt[FTP] = "RIVER (\\d) \\*\\*\\* \\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\] \\[([2-9TJQKA][hdsc])\\]";
reRiverRunIt[CEREUS] = "RIVER (\\d) \\*\\*\\* \\[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\\] \\[([2-9TJQKA][hdsc])\\]";
reRiverRunIt[HEM] = "Dealing River (\\d) \\*\\* \\[ ([2-9TJQKA][hdsc]) \\]";

var reRiverAction = new Array();
reRiverAction[PSTARS] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SHOW)/;
reRiverAction[FTP] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SHOW)/;
reRiverAction[CEREUS] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SHOW)/;
reRiverAction[HEM] = /Dealing River \*\* \[ [2-9TJQKA][hdsc] \]■(.*?) wins /;

var reRiverActionAlt = new Array();
reRiverActionAlt[PSTARS] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reRiverActionAlt[FTP] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reRiverActionAlt[CEREUS] = /RIVER \*\*\* \[[2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc] [2-9TJQKA][hdsc]\] \[[2-9TJQKA][hdsc]\]■(.*)\*\*\* (?:SUM)/;
reRiverActionAlt[HEM] = /Dealing River \*\* \[ [2-9TJQKA][hdsc] \]■(?:.*?) wins /;

var reShowdownPlayers = new Array();
reShowdownPlayers[PSTARS] = /(.*): /;
reShowdownPlayers[FTP] = /(.*): /;
reShowdownPlayers[CEREUS] = /(.*) - /;

var reShowdownCards = new Array();
reShowdownCards[PSTARS] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reShowdownCards[FTP] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;
reShowdownCards[CEREUS] = /\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\]/;

var reMucks = new Array();
reMucks[PSTARS] = /mucks/;
reMucks[FTP] = /mucks/;
reMucks[CEREUS] = /Mucks/;

var reHEMuckedPre = new Array();
reHEMuckedPre[PSTARS] = "";
reHEMuckedPre[FTP] = "";
reHEMuckedPre[CEREUS] = "";
var reHEMuckedPost = new Array();
reHEMuckedPost[PSTARS] = ' mucked \\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\\]';
reHEMuckedPost[FTP] = ' mucked \\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\\]';
reHEMuckedPost[CEREUS] = ' .* [Mucked] \\[([2-9TJQKA][hdsc]) ([2-9TJQKA][hdsc])\\]';

var reGetShowdownHands = new Array();
reGetShowdownHands[PSTARS] = /\] \((.*)\)/;
reGetShowdownHands[FTP] = /\] \((.*)\)/;
reGetShowdownHands[CEREUS] = /\] \((.*)\)/;

var reGetResults = new Array();
reGetResults[PSTARS] = / collected /;
reGetResults[FTP] = / collected /;
reGetResults[CEREUS] = / Collects /;




function fcp_convert_hh(unformatted, outputType,showNames,showResults,cardType,debugOption) {

	
	
	var theHand = new hand(); //hand data structure
	var formatted; //the converted output text
	
	debug = debugOption;
	
	//default to Feral Cow Original (4bb) output type
	if (!outputType) {outputType = 0;}

	var myRegExp = new RegExp("(10)(h|c|d|s)([ |\\]])", "ig");
	unformatted = unformatted.replace(myRegExp, "T$2$3");
	//theHand.error = unformatted;
	theHand.unformatted = unformatted
	theHand.unformattedNoBreaks = unformatted.replace(/\n/g, "■");
	//for IE, also remove the \r characacter
	theHand.unformattedNoBreaks = theHand.unformattedNoBreaks.replace(/\r/g, "");
	theHand.prefix = "";
	
	//default cards for style 20
	if (outputType == 0) {
		if (cardType == 0) {
			outputType = 0;
			cardFolder = '';
		} else if (cardType ==1 ) {
			outputType = 20;
			cardFolder = 'ouch';
		} else if (cardType ==2 ) {
			outputType = 20;
			cardFolder='inline';
		}
	} else {
	
		if (cardType == 0 ) {
			cardFolder = 'ouch';
		} else if (cardType ==1) {
			cardFolder = 'ouch';
		} else if (cardType ==2) {
			cardFolder = 'inline';
		}
	}
	
	
	
	
	//parse options embedded within HH
	if (theHand.unformatted.match(/^(?:pos|position|showpos|showposition)$/m)) {showNames = 0;}
	if (theHand.unformatted.match(/^newcards$/m)) {outputType = 20; cardFolder = 'inline';}
	if (theHand.unformatted.match(/^(?:cwikcards|cwik)$/m)) {outputType = 20; cardFolder = 'ouch';}
	if (theHand.unformatted.match(/^hideresults$/m)) {showResults = 1;}

	
	//split the text by line breaks
	var lines = new Array();
	lines = theHand.unformatted.split('\n');
	theHand.lines = lines;
	

	//find which site
	//theHand.firstLine = lines[0] + "|" + lines[1];

	for (linecounter = 0; linecounter <lines.length;++linecounter) {
	
		theHand.firstLine = theHand.lines[linecounter];
		
		if (theHand.firstLine.match(/PokerStars/)) {
			theHand.firstLine = theHand.lines[linecounter] + theHand.lines[linecounter+1];
			theHand.site = "PokerStars";
			theHand = parse_site_pokerstars(theHand);
			break;
		} else if ((theHand.firstLine.match(/Full Tilt Poker/)) || (theHand.firstLine.match(/FullTiltPoker/))) {			theHand.firstLine = theHand.lines[linecounter] + theHand.lines[linecounter+1];
			theHand.site = "Full Tilt";
			theHand = parse_site_ftp(theHand);
			break;
		} else if (theHand.firstLine.match(/Stage \#/)) {
			theHand.firstLine = theHand.lines[linecounter] + theHand.lines[linecounter+1];
			theHand.site = "Cereus";
			theHand = parse_site_cereus(theHand);
			break;
		} else if (theHand.firstLine.match(/\*\*\*\*\* Hand History /)) {
			theHand.firstLine = theHand.lines[linecounter] + theHand.lines[linecounter+1];
			theHand.site = "Holdem Manager";
			theHand = parse_site_hem(theHand);
			break;
		} else {
			theHand.site = "NONE";
			theHand.prefix = theHand.prefix + theHand.lines[linecounter] + "\n";
		}
	}
	
	
	if (theHand.site == "NONE") {
		theHand.formatted = "Site unknown or unsupported.  Could not parse history."; 
	}
	else {
		//Send the populated data structure to be formatted into output	
		theHand.formatted = handToText(theHand,outputType,showNames,showResults);
	}
	
	//we return the entire hand object
	return (theHand);

}

function hand() {
	//this is just an object structure
}

function parse_site_ftp(handin) {

	//determine which game is being played
	theResult = "Game: unknown\n";
	if (handin.firstLine.match(/Cap No Limit Hold\'em/)) { //'
		handin.gameLong = "Cap No-Limit Hold\'em";
		handin.gameShort = "NLHE";
		handin = parse_holdem(handin, FTP);
	} else if (handin.firstLine.match(/No Limit Hold\'em/)) {
		handin.gameLong = "No-Limit Hold\'em";
		handin.gameShort = "NLHE";
		handin = parse_holdem(handin, FTP);
	} else if (handin.firstLine.match(/Pot Limit Hold\'em/)) {
		handin.gameLong = "Pot Limit Hold\'em";
		handin.gameShort = "PLHE";
		handin = parse_holdem(handin, FTP);
	} else if (handin.firstLine.match(/Limit Hold\'em/)) { //'
		handin.gameLong = "Limit Hold\'em";
		handin.gameShort = "LHE";
		handin = parse_holdem(handin, FTP);

	} else if ((handin.firstLine.match(/Omaha/)) || (handin.firstLine.match(/omaha/i))) {

		handin.gameLong = "Limit Omaha";
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/Pot Limit/i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		if (handin.firstLine.match(/h\/l/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}
		handin.gameShort = "OMAHA";
		handin = parse_omaha(handin, FTP);

	} else if ((handin.firstLine.match(/(Razz)/i)) || (handin.firstLine.match(/(Stud)/i))) {

		handin.gameLong = "Limit " + RegExp.$1;
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/pot limit/i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		if (handin.firstLine.match(/hi\/lo/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}

		handin.gameShort = RegExp.$1.toUpperCase();
		handin = parse_stud(handin, FTP);
	} else {

		handin.error = "Game type not currently supported."
	}

	return handin;

}

function parse_site_pokerstars(handin) {
	
	//get tourney buyin amount
	if (handin.firstLine.match(/Tournament/)) {
		if (handin.firstLine.match(/(\$[\d|\.|\,]+\+\$[\d|\.|\,]+)/)){
			handin.tourneyBuyin = RegExp.$1;
		}
	
	}

	//determine which game is being played
	theResult = "Game: unknown\n";
	if (handin.firstLine.match(/Hold\'em No Limit/)) { //'
		handin.gameLong = "No-Limit Hold'em";
		handin.gameShort = "NLHE";
		handin = parse_holdem(handin, PSTARS);

	} else if (handin.firstLine.match(/Hold\'em Limit/)) { //'
		handin.gameLong = "Limit Hold'em";
		handin.gameShort = "LHE";
		handin = parse_holdem(handin, PSTARS);

	} else if ((handin.firstLine.match(/Omaha/)) || (handin.firstLine.match(/omaha/i))) {

		handin.gameLong = "Limit Omaha";
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/pot limit/i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		if (handin.firstLine.match(/hi\/lo/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}
		handin.gameShort = "OMAHA";
		handin = parse_omaha(handin, PSTARS);

	} else if ((handin.firstLine.match(/(Razz)/i)) || (handin.firstLine.match(/(Stud)/i))) {

		handin.gameLong = "Limit " + RegExp.$1;
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/pot limit/i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		if (handin.firstLine.match(/hi\/lo/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}
		handin.gameShort = "STUD";
		handin = parse_stud(handin, PSTARS);

	} else if (handin.firstLine.match(/(Triple Draw)/i)) {

		handin.gameLong = "Limit " + RegExp.$1;
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/pot limit/i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		handin.gameShort = "DRAW";
		handin = parse_pokerstars_draw(handin, PSTARS);

	} else if (handin.firstLine.match(/(Single Draw)/i)) {

		handin.gameLong = "Limit " + RegExp.$1;
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/pot limit/i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		handin.gameShort = "DRAW";
		handin = parse_pokerstars_singledraw(handin, PSTARS);

	} else {

		handin.error = "Game type not currently supported.";

	}
	
	

	return handin;

}

function parse_site_cereus(handin) {

	//determine which game is being played
	if (handin.firstLine.match(/Holdem .*(No|Pot) Limit/)) { //'
		handin.gameLong = RegExp.$1 + " Limit Hold\'em";
		handin.gameShort = "NLHE";
		handin = parse_holdem(handin, CEREUS);

	} else if (handin.firstLine.match(/Holdem .*Limit/)) { //'
		handin.gameLong = "Limit Hold\'em";
		handin.gameShort = "LHE";
		handin = parse_holdem(handin, CEREUS);

	} else if ((handin.firstLine.match(/Omaha/)) || (handin.firstLine.match(/omaha/i))) {

		handin.gameLong = "Omaha";
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No Limit " + handin.gameLong;
		} else if (handin.firstLine.match(/pot limit/i)) {
			handin.gameLong = "Pot Limit " + handin.gameLong;
		}
		if (handin.firstLine.match(/hi\/lo/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}
		handin.gameShort = "OMAHA";
		handin = parse_omaha(handin, CEREUS);

	} else if ((handin.firstLine.match(/(Razz)/i)) || (handin.firstLine.match(/(Seven Card)/i))) {

		handin.gameLong = "Limit " + RegExp.$1;
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/pot limit/i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		if (handin.firstLine.match(/hi\/lo/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}
		handin.gameShort = "STUD";
		handin = parse_stud(handin, CEREUS);

	} else {

		handin.error = "Game type not currently supported."
	}

	//turn off Cereus support here
	//handin.error = "Cereus support coming soon.  Hold your horses.  er.. cows.";
	return handin;

}

function parse_site_hem(handin) {

	//get original site
	if (handin.firstLine.match(/\((.*)\)/)) {
		handin.HEMOriginalSite = RegExp.$1;
	}
	
	//determine which game is being played
	if (handin.firstLine.match(/.* (NL|PL) Texas Hold/)) {
		handin.gameLong = RegExp.$1 + " Hold\'em";
		handin.gameShort = "NLHE";
		handin = parse_holdem(handin, HEM);

	} else if (handin.firstLine.match(/Holdem .*Limit/) || handin.firstLine.match(/Limit Texas Hold\'em/)) {
		handin.gameLong = "Limit Hold\'em";
		handin.gameShort = "LHE";
		handin = parse_holdem(handin, HEM);

	} else if ((handin.firstLine.match(/Omaha/)) || (handin.firstLine.match(/omaha/i))) {

		handin.gameLong = "Limit Omaha";
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/ PL /i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		if (handin.firstLine.match(/hi\/lo/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}
		handin.gameShort = "OMAHA";
		handin = parse_omaha(handin, HEM);

	} else if ((handin.firstLine.match(/(Razz)/i)) || (handin.firstLine.match(/(Seven Card)/i))) {

		handin.gameLong = "Limit " + RegExp.$1;
		if (handin.firstLine.match(/no limit/i)) {
			handin.gameLong = "No " + handin.gameLong;
		} else if (handin.firstLine.match(/ PL /i)) {
			handin.gameLong = "Pot " + handin.gameLong;
		}
		if (handin.firstLine.match(/hi\/lo/i)) {
			handin.gameLong = handin.gameLong + " Hi/Lo";
		}
		handin.gameShort = "STUD";
		handin = parse_stud(handin, HEM);

	} else {

		handin.error = "Game type not currently supported."
	}

	//turn off Cereus support here
	//handin.error = "Cereus support coming soon.  Hold your horses.  er.. cows.";
	return handin;

}

function parse_pokerstars_singledraw(handin, site) {

	//Cash or tournament?
	if (handin.firstLine.match(/\$\d/)) {
		handin.gameType = "C";
		//handin.error = "Tournament hands not yet supported.";
	} else {
		handin.gameType = "T";
	}

	//find blinds
	if (handin.firstLine.match(reBlinds[site])) {
		handin.smallBlind = RegExp.$1;
		handin.bigBlind = RegExp.$2;
	}

	handin.smallBlindPostedAmount = 0;
	handin.bigBlindPostedAmount = 0;

	//find game size
	if (handin.unformatted.match(reGameSize[site])) {
		handin.gameSize = RegExp.$1 + '-max';
	}
	else {
		handin.gameSize = "";
	}

	handin.antesTotal = 0;
	anteLines = new Array;
	//find antes
	anteText = handin.unformattedNoBreaks.match(reAnteText[site]);
   if (anteText) {
		anteLines = anteText[1].split(/■/);
		for (j in anteLines) {
			if (anteLines[j].match(reAnteLines[site])) {
				handin.ante = RegExp.$1;
				handin.antesTotal = parseFloat(handin.antesTotal) + parseFloat(RegExp.$1);
			}
		}
	}
	
	result = handin.unformattedNoBreaks.match(reSeatingText[site]);
	if (result) {handin.seatText = result[1];}
	else {handin.seatText = " ";}

	handin.seatLines = handin.seatText.replace(/■/g, "\n");
	
	//find number of seats
	seats = handin.seatLines.match(reFindSeats[site]);
	handin.numPlayers = seats.length;
	
	// find button/bring-in?
	if (handin.unformatted.match(reButton[site])) {
		handin.button = RegExp.$1;
	}
	
	//find player names and stack sizes
	playerLines = handin.seatLines.match(reFindInfo[site]);
	handin.players = new Array;
	handin.stacks = new Array;
	handin.seatNumbers = new Array;

	j = 0;
	for (i = 0; i < handin.numPlayers; i = i + 1) {
		
		if (playerLines[i].match(rePlayerInfo[site])) {
			theSeat = RegExp.$1;
			thePlayer = RegExp.$2;
			theStack = RegExp.$3;
			if (!((playerLines[i].match(/sitting out/i) && (handin.gameType == "C") && (theSeat != handin.button)))){
				handin.seatNumbers[j] = theSeat;
				handin.players[j] = thePlayer;
				handin.stacks[j] = theStack;
				j++;
			}
		}
	}
	if (j > 0) { handin.numPlayers = j; }

	//find cards
	handin.holeCards = new Array;
	var myRegEx = new RegExp("");

	//get hero
	for (x = 0; x < handin.numPlayers; x++) {
		handin.holeCards[x] = new Array;
		myRegEx.compile(reGetHandPre[site] + handin.players[x] + reTDGetHandPost[site], "g");
		result = handin.unformattedNoBreaks.match(myRegEx);
		if (result) {
			handin.hero = handin.players[x];
			heropos = x;
			x = handin.numplayers;
		}
	}

	//initialize 2D arrays
	handin.action_types = new Array;
	handin.action_players = new Array;
	handin.action_values = new Array;
	handin.showdown_types = new Array;
	handin.action_addedToPot = new Array;
	handin.action_playersPot = new Array;

	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	handin.antesTotal = 0;
	anteLines = new Array;
	anteText = handin.unformattedNoBreaks.match(/(.*?)\*\*\* DEAL/);
	anteLines = anteText[0].split(/■/);
	for (j in anteLines) {
		if (anteLines[j].match(/posts the ante [\$|](\d+\.\d+|\d+)/)) {
			handin.antesTotal = parseFloat(handin.antesTotal) + parseFloat(result[1]);
		}
	}
	// regexstring = /(.+)\: posts small blind [\$|](\d+|\d+\.\d+)/;
	result = handin.unformatted.match(/(.+)\: posts small blind [\$|](\d+\.\d+|\d+)/i);
	if (result) {
		handin.smallBlindPostedBy = result[1];
		handin.smallBlindPostedAmount = result[2];
		playerIndex = findIndex(handin.players, handin.smallBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.smallBlindPostedAmount;
		//handin.action_addedToPot[0] = handin.smallBlindPostedAmount;
	}

	// regexstring = /(.+)\: posts big blind [\$|](\d+\.\d+|\d+)/;
	result = handin.unformatted.match(/(.+)\: posts big blind [\$|](\d+\.\d+|\d+)/i);
	if (result) {
		handin.bigBlindPostedBy = result[1];
		handin.bigBlindPostedAmount = result[2];
		playerIndex = findIndex(handin.players, handin.bigBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.bigBlindPostedAmount;
		//handin.action_addedToPot[0] += handin.bigBlindPostedAmount;
	}

	//get street cards named desire
	//streetRegEx = new Array(/DEALING HANDS \*\*\*\|(.*)\|(?:.*?): (?:stands|draws)/i, /FIRST DRAW \*\*\*\|(.*)\*\*\* SECOND/i, /SECOND DRAW \*\*\*\|(.*)\*\*\* THIRD/i, /THIRD DRAW \*\*\*\|(.*)\*\*\* SHOW/i);
	//streetRegExAlt = new Array(/DEALING HANDS \*\*\*\|(.*)\*\*\* sum/i, /FIRST DRAW \*\*\*\|(.*)\*\*\* sum/i, /SECOND DRAW \*\*\*\|(.*)\*\*\* sum/i, /THIRD DRAW \*\*\*\|(.*)\*\*\* sum/i);
	handin.communityCards = new Array;
	handin.communityCards[1] = new Array;
	cardCount = 0;
	var thisRegEx = new RegExp;
	for (x in reSDStreetMatch[site]) {
		thisRegEx.compile(reSDStreetMatch[site][x]);
		outerresult = thisRegEx.exec(handin.unformattedNoBreaks);
		if (!outerresult) {
			thisRegEx.compile(reTDStreetMatchAlt[site][x]);
			outerresult = thisRegEx.exec(handin.unformattedNoBreaks);
		}
		if (outerresult) {
			//alert(outerresult[1]);
			//alert(outerresult[2]);
			//alert(outerresult[3]);
			//alert(outerresult[4]);
			handin = pokerStarsParseAction(handin, outerresult[1], x);
			myRegEx.compile("Dealt to " + handin.hero + "( \\[(.*)\\])");
			outerLines = outerresult[1].split(/■/);
			result = outerresult[1].match(myRegEx);
			if (!result) {
				myRegEx.compile(handin.hero + ": stands pat on (\\[(.*)\\])");
				result = outerresult[1].match(myRegEx);
			}
			if (result) {
				subresult = result[1].match(/([2-9TJQKA][hdsc])/g);
				for (y in subresult) {
					handin.holeCards[heropos][handin.holeCards[heropos].length] = subresult[y];
				}
			}
		}
		//zero out player contributions to pot for next street
		for (r in handin.players) {
			handin.action_playersPot[r] = 0;
		}
	}

	//summary
	if (handin.unformattedNoBreaks.match(reMatchSummary[site])) {
		handin.showdownText = RegExp.$1;

		//if (handin.showdownText.match(reMatchSummary[site])) {
		//	handin.showdownText = RegExp.$1;
		//}
		handin.showdownLines = handin.showdownText.split(/■/);

		//initialize 2D arrays
		handin.showdown_hands = new Array;   // two pair, Fives and Fours
		handin.showdown_players = new Array; // <nick>
		handin.showdown_cards = new Array;   //  Jh Qs etc
		handin.showdown_types = new Array;   // won, lost, mucked, collected
		handin.result_players = new Array;
		handin.result_values = new Array;

		//loop through showdown lines
		playerCount = -1;
		resultCount = -1;
		for (i = 0; i < handin.showdownLines.length; i = i + 1) {
			if (site == HEM) {
				if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
					m = findIndex(handin.showdown_players,RegExp.$1);
					if (m == -1) { m = ++playercount; }
					//playerCount++;
					handin.showdown_players[m] = RegExp.$1;
					handin.showdown_types[m] = "won";
					if (handin.showdownLines[i].match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[m];
						handin.result_values[resultCount] = RegExp.$1;
					}
				}
				else if (result = handin.showdownLines[i].match(reTDSummaryExtraction2[site])) {
					m = findIndex(handin.showdown_players,result[1]);
					if (m > -1) {
						handin.showdown_cards[m] = new Array;
						handin.showdown_cards[m][0] = result[2];
						handin.showdown_cards[m][1] = result[3];
						handin.showdown_cards[m][2] = result[4];
						handin.showdown_cards[m][3] = result[5];
						handin.showdown_cards[m][4] = result[6];
						handin.showdown_hands[m] = " ";
					}
					else {
						playerCount++;
						handin.showdown_cards[playerCount] = new Array;
						handin.showdown_players[playerCount] = result[1];
						handin.showdown_types[playerCount] = "lost";
						handin.showdown_cards[playerCount][0] = result[2];
						handin.showdown_cards[playerCount][1] = result[3];
						handin.showdown_cards[playerCount][2] = result[4];
						handin.showdown_cards[playerCount][3] = result[5];
						handin.showdown_cards[playerCount][4] = result[6];
						handin.showdown_hands[playerCount] = " ";
					}
				}
			}
			else if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
				playerCount++;
				handin.showdown_players[playerCount] = RegExp.$1;
				handin.showdown_types[playerCount] = RegExp.$2;
				partTemp = RegExp.$3;
				if (site == CEREUS) { partTemp = RegExp.$2 + RegExp.$3; }
				if (partTemp.match(/( won | collected | wins )/)) {
					handin.showdown_types[playerCount] = "won";
				}
				//else {
				//	handin.showdown_types[playerCount] = "lost";
				//}
				handin.showdown_cards[playerCount] = new Array;
				if (partTemp) {
					if (partTemp.match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[playerCount];
						handin.result_values[resultCount] = RegExp.$1;
					}
					if (partTemp.match(reTDSummaryExtraction2[site])) {
						switch(site) {
						case PSTARS:
						case FTP:
							if (RegExp.$7) {
								handin.showdown_hands[playerCount] = RegExp.$7;
							}
							handin.showdown_cards[playerCount][0] = RegExp.$1;
							handin.showdown_cards[playerCount][1] = RegExp.$2;
							handin.showdown_cards[playerCount][2] = RegExp.$3;
							handin.showdown_cards[playerCount][3] = RegExp.$4;
							handin.showdown_cards[playerCount][4] = RegExp.$5;
							break;
						case CEREUS:
							handin.showdown_cards[playerCount][0] = RegExp.$3;
							handin.showdown_cards[playerCount][1] = RegExp.$4;
							handin.showdown_cards[playerCount][2] = RegExp.$5;
							handin.showdown_cards[playerCount][3] = RegExp.$6;
							handin.showdown_cards[playerCount][4] = RegExp.$7;
							handin.showdown_hands[playerCount] = RegExp.$2;
							break;
						}
					}
				}
				else { handin.showdown_cards[playerCount][0] = 'mucks'; }
			}
		}

		//rake
		if (handin.unformatted.match(reRake[site])) {
			handin.rake = RegExp.$1;
		}
	}

	return handin;

}

function parse_stud(handin, site) {

	//Cash or tournament?
	if (handin.firstLine.match(/Tournament/)) {
		handin.gameType = "T";
		//handin.error = "Tournament hands not yet supported.";
	} else {
		handin.gameType = "C";
	}

	//find blinds
	if (handin.firstLine.match(reBlinds[site])) {
		handin.smallBlind = RegExp.$1;
		handin.bigBlind = RegExp.$2;
	}

	handin.smallBlindPostedAmount = 0;
	handin.bigBlindPostedAmount = 0;

	//find game size
	if (handin.unformatted.match(reGameSize[site])) {
		handin.gameSize = RegExp.$1 + '-max';
	}
	else {
		handin.gameSize = "";
	}

	handin.antesTotal = 0;
	anteLines = new Array;
	//find antes
	anteText = handin.unformattedNoBreaks.match(reAnteText[site]);
	anteLines = anteText[1].split(/■/);
	for (j in anteLines) {
		if (anteLines[j].match(reAnteLines[site])) {
			handin.ante = RegExp.$1;
			handin.antesTotal = parseFloat(handin.antesTotal) + parseFloat(RegExp.$1);
		}
	}

	result = handin.unformattedNoBreaks.match(reSeatingText[site]);
	if (result) {handin.seatText = result[1];}
	else {handin.seatText = " ";}

	handin.seatLines = handin.seatText.replace(/■/g, "\n");
	
	//find number of seats
	seats = handin.seatLines.match(reFindSeats[site]);
	handin.numPlayers = seats.length;
	
	// find button/bring-in?
	if (handin.unformatted.match(reButton[site])) {
		handin.button = RegExp.$1;
	}
	
	//find player names and stack sizes
	playerLines = handin.seatLines.match(reFindInfo[site]);
	handin.players = new Array;
	handin.stacks = new Array;
	handin.seatNumbers = new Array;

	j = 0;
	for (i = 0; i < handin.numPlayers; i = i + 1) {
		
		if (playerLines[i].match(rePlayerInfo[site])) {
			theSeat = RegExp.$1;
			thePlayer = RegExp.$2;
			theStack = RegExp.$3;
			if (!((playerLines[i].match(/sitting out/i) && (handin.gameType == "C") && (theSeat != handin.button)))){
				handin.seatNumbers[j] = theSeat;
				handin.players[j] = thePlayer;
				handin.stacks[j] = theStack;
				j++;
			}
		}
	}
	if (j > 0) { handin.numPlayers = j; }

	// find button/bring-in?
	if (handin.unformatted.match(reButton[site])) {
		handin.button = RegExp.$1;
	}

	//find cards
	handin.holeCards = new Array;
	var myRegEx = new RegExp("");

	//get hero
	var thisRegEx = new RegExp;
	thisRegEx.compile(reStreetMatch[site][0]);
	dealtCards = thisRegEx.exec(handin.unformattedNoBreaks);
	if (!dealtCards) { 
		thisRegEx.compile(reStreetMatchAlt[site][0]);
		dealtCards = thisRegEx.exec(handin.unformattedNoBreaks);
	}
	for (x = 0; x < handin.numPlayers; x++) {
		handin.holeCards[x] = new Array;
		myRegEx.compile(reGetHandPre[site] + handin.players[x] + reGetHandPost[site], "g");
		subresult = dealtCards.join("■").match(myRegEx);
		if (subresult) {
			handin.hero = handin.players[x];
		}
		myRegEx.compile(reGetHandPre[site] + escapeText(handin.players[x]) + reGetHandPost2[site], "g");
		result = handin.unformatted.match(myRegEx);
		if (result) {
			z = result.length - 1;
		} else {
			z = -1;
		}
		w = 0;
		if (z >= 0) {
			subresult = result[z].match(reMatchCard[site]);
			handOffset = 0;
			if ((handin.players[x] != handin.hero) && (subresult.length < 7)) {
				handOffset = 2;
				handin.holeCards[x][0] = '1s';
				handin.holeCards[x][1] = '1s';
			}
			else if ((handin.players[x] == handin.hero) && (subresult.length == 7) && (result[z-1].match(reMatchCard[site]).length == 7)) {
				subresult = result[z-1].match(reMatchCard[site]);
			}
			for (y in subresult) {
				handin.holeCards[x][w + handOffset] = subresult[y];
				w++;
			}
			z--;
		}
	}

	//initialize 2D arrays
	handin.action_types = new Array;
	handin.action_players = new Array;
	handin.action_values = new Array;
	handin.showdown_types = new Array;
	handin.action_addedToPot = new Array;
	handin.action_playersPot = new Array;

	//get street cards named desire
	handin.communityCards = new Array;
	handin.communityCards[1] = new Array;
	cardCount = 0;
	var thisRegEx = new RegExp;
	for (x = 0; x < 5; x++) {
		//zero out player contributions to pot for this street
		for (r in handin.players) {
			handin.action_playersPot[r] = 0;
		}
		thisRegEx.compile(reStreetMatch[site][x]);
		result = thisRegEx.exec(handin.unformattedNoBreaks);
		if (!result) {
			thisRegEx.compile(reStreetMatchAlt[site][x]);
			result = thisRegEx.exec(handin.unformattedNoBreaks);
		}
		if (result) {
			if (site == PSTARS) {
				handin = pokerStarsParseAction(handin, result[1], x);
			}
			else if (site == FTP) {
				handin = ftpParseAction(handin, result[1], x);
			}
			else if (site == CEREUS) {
				handin = cereusParseAction(handin, result[1], x);
			}
		}
	}

	//summary
	if (handin.unformattedNoBreaks.match(reMatchSummary[site])) {
		handin.showdownText = RegExp.$1;

		//if (handin.showdownText.match(reMatchSummary[site])) {
		//	handin.showdownText = RegExp.$1;
		//}
		handin.showdownLines = handin.showdownText.split(/■/);

		//initialize 2D arrays
		handin.showdown_hands = new Array;   // two pair, Fives and Fours
		handin.showdown_players = new Array; // <nick>
		handin.showdown_cards = new Array;   //  Jh Qs etc
		handin.showdown_types = new Array;   // won, lost, mucked, collected
		handin.result_players = new Array;
		handin.result_values = new Array;

		//loop through showdown lines
		playerCount = -1;
		resultCount = -1;
		for (i = 0; i < handin.showdownLines.length; i = i + 1) {
			if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
				playerCount++;
				handin.showdown_players[playerCount] = RegExp.$1;
				handin.showdown_types[playerCount] = RegExp.$2;
				partTemp = RegExp.$3;
				if (site == CEREUS) { partTemp = RegExp.$2 + RegExp.$3; }
				if (partTemp.match(/( won | collected )/)) {
					handin.showdown_types[playerCount] = "won";
				}
				//else {
				//	handin.showdown_types[playerCount] = "lost";
				//}
				handin.showdown_cards[playerCount] = new Array;
				if (partTemp) {
					if (partTemp.match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[playerCount];
						handin.result_values[resultCount] = RegExp.$1;
					}
					if (partTemp.match(reStudSummaryExtraction2[site])) {
						switch(site) {
						case PSTARS:
						case FTP:
							if (RegExp.$9) {
								handin.showdown_hands[playerCount] = RegExp.$9;
							}
							else { handin.showdown_hands[playerCount] = " "; }
							break;
						case CEREUS:
							handin.showdown_hands[playerCount] = RegExp.$2;
							break;
						}
					}
				}
				else { handin.showdown_cards[playerCount][0] = 'mucks'; }
			}
		}

		//rake
		if (handin.unformatted.match(reRake[site])) {
			handin.rake = RegExp.$1;
		}
	}

	return handin;

}

function parse_holdem(handin, site) {

	//Cash or tournament?
	if (handin.unformatted.match(reGameType[site])) {
		handin.gameType = "T";
	} else {
		handin.gameType = "C";
	}


	//find blinds
	if (handin.firstLine.match(reBlinds[site])) {
		handin.smallBlind = RegExp.$1;
		handin.bigBlind = RegExp.$2;
	}

	handin.smallBlindPostedAmount = 0;
	handin.bigBlindPostedAmount = 0;

	//find game size
	if (handin.unformatted.match(reGameSize[site])) {
		handin.gameSize = RegExp.$1 + '-max';
	}
	else {
		handin.gameSize = "";
	}

	handin.antesTotal = 0;
	anteLines = new Array;
	//find antes
	anteText = handin.unformattedNoBreaks.match(reAnteText[site]);
   if (anteText) {
		anteLines = anteText[1].split(/■/);
		for (j in anteLines) {
			if (anteLines[j].match(reAnteLines[site])) {
				handin.ante = RegExp.$1;
				handin.antesTotal = parseFloat(handin.antesTotal) + parseFloat(RegExp.$1);
			}
		}
	}
	
	result = handin.unformattedNoBreaks.match(reSeatingText[site]);
	if (result) {handin.seatText = result[1];}
	else {handin.seatText = " ";}

	handin.seatLines = handin.seatText.replace(/■/g, "\n");
	
	//find number of seats
	seats = handin.seatLines.match(reFindSeats[site]);
	handin.numPlayers = seats.length;
	
	// find button/bring-in?
	if (handin.unformatted.match(reButton[site])) {
		handin.button = RegExp.$1;
	}
	
	//find player names and stack sizes
	playerLines = handin.seatLines.match(reFindInfo[site]);
	handin.players = new Array;
	handin.stacks = new Array;
	handin.seatNumbers = new Array;

	j = 0;
	for (i = 0; i < handin.numPlayers; i = i + 1) {
		
		if (playerLines[i].match(rePlayerInfo[site])) {
			theSeat = RegExp.$1;
			thePlayer = RegExp.$2;
			theStack = RegExp.$3;
			if (!((playerLines[i].match(/sitting out/i) && (handin.gameType == "C") && (theSeat != handin.button)))){
				handin.seatNumbers[j] = theSeat;
				handin.players[j] = thePlayer;
				handin.stacks[j] = theStack;
				j++;
			}
		}
	}
	if (j > 0) { handin.numPlayers = j; }


	//find hole cards
	handin.holeCards = new Array;
	handin.holeCards[0] = new Array;
	if (handin.unformatted.match(reHEHoleCards[site])) {
		handin.hero = RegExp.$1
		handin.holeCards[0][0] = RegExp.$2;
		handin.holeCards[0][1] = RegExp.$3;
		//handin.holeCards[0][2] = RegExp.$4;
		//handin.holeCards[0][3] = RegExp.$5;
	}

	//initialize 2D arrays
	handin.action_types = new Array;
	handin.action_players = new Array;
	handin.action_values = new Array;
	handin.action_addedToPot = new Array;
	handin.action_playersPot = new Array;

	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//but add in SB
	if (handin.unformatted.match(reSmallBlind[site])) {
		handin.smallBlindPostedBy = RegExp.$1;
		handin.smallBlindPostedAmount = RegExp.$2;
		//playerIndex = handin.players.indexOf(handin.smallBlindPostedBy);
		playerIndex = findIndex(handin.players, handin.smallBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.smallBlindPostedAmount;
	}
	//and BB
	if (handin.unformatted.match(reBigBlind[site])) {
		handin.bigBlindPostedBy = RegExp.$1;
		handin.bigBlindPostedAmount = RegExp.$2;
		//playerIndex = handin.players.indexOf(handin.bigBlindPostedBy);
		playerIndex = findIndex(handin.players, handin.bigBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.bigBlindPostedAmount;
	}
	
	if (!handin.smallBlind) {
		handin.smallBlind = handin.smallBlindPostedAmount;
		handin.bigBlind = handin.bigBlindPostedAmount;
	}	
	//find preflop action
	result = handin.unformattedNoBreaks.match(rePreflopAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(rePreflopActionAlt[site]); }
	if (result) {
		handin.preflopText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.preflopText, 0); }
		if (site == FTP) { handin = ftpParseAction(handin, handin.preflopText, 0); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.preflopText, 0); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.preflopText,0);}
	}

	//get flop cards
	handin.communityCards = new Array;
	handin.communityCards[1] = new Array;
	if (handin.unformatted.match(reFlop[site])) {
		handin.communityCards[1][0] = RegExp.$1;
		handin.communityCards[1][1] = RegExp.$2;
		handin.communityCards[1][2] = RegExp.$3;
	}
	else {
		myRegEx = new RegExp;
		myRegEx = myRegEx.compile(reFlopRunIt[site],"g");
	   result = handin.unformatted.match(myRegEx);
		if (result) {
		   i = 0; j = 0;
			myRegEx = myRegEx.compile(reFlopRunIt[site]);
			while (result[i]) {
			   subresult = result[i].match(myRegEx);
			   handin.communityCards[1][j++] = subresult[2];
			   handin.communityCards[1][j++] = subresult[3];
			   handin.communityCards[1][j++] = subresult[4];
				i++;
			}
		}
	}

	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//find flop action
	result = handin.unformattedNoBreaks.match(reFlopAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(reFlopActionAlt[site]); }
	if (result) {
		handin.flopText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.flopText, 1); }
		else if (site == FTP) { handin = ftpParseAction(handin, handin.flopText, 1); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.flopText, 1); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.flopText,1);}
	}

	//get turn card
	handin.communityCards[2] = new Array;
	if (handin.unformatted.match(reTurn[site])) {
		handin.communityCards[2][0] = RegExp.$1;
	}
	else {
		myRegEx = new RegExp;
		myRegEx = myRegEx.compile(reTurnRunIt[site],"g");
	   result = handin.unformatted.match(myRegEx);
		if (result) {
		   i = 0; j = 0;
			myRegEx = myRegEx.compile(reTurnRunIt[site]);
			while (result[i]) {
			   subresult = result[i].match(myRegEx);
			   handin.communityCards[2][j++] = subresult[2];
				i++;
			}
		}
	}
	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//find turn action
	result = handin.unformattedNoBreaks.match(reTurnAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(reTurnActionAlt[site]); }
	if (result) {
		handin.turnText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.turnText, 2); }
		else if (site == FTP) { handin = ftpParseAction(handin, handin.turnText, 2); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.turnText, 2); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.turnText,2);}
	}

	//get river card
	handin.communityCards[3] = new Array;
	if (handin.unformatted.match(reRiver[site])) {
		handin.communityCards[3][0] = RegExp.$1;
	}
	else {
		myRegEx = new RegExp;
		myRegEx = myRegEx.compile(reRiverRunIt[site],"g");
	   result = handin.unformatted.match(myRegEx);
		if (result) {
		   i = 0; j = 0;
			myRegEx = myRegEx.compile(reRiverRunIt[site]);
			while (result[i]) {
				//myRegEx = myRegEx.compile(reRiverRunIt[site]);
			   subresult = result[i].match(myRegEx);
			   handin.communityCards[3][j++] = subresult[2];
				i++;
			}
		}
	}
	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//find river action
	result = handin.unformattedNoBreaks.match(reRiverAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(reRiverActionAlt[site]); }
	if (result) {
		handin.riverText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.riverText, 3); }
		else if (site == FTP) { handin = ftpParseAction(handin, handin.riverText, 3); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.riverText, 3); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.riverText,3);}
	}

	//summary
	if (handin.unformattedNoBreaks.match(reMatchSummary[site])) {
		handin.showdownText = RegExp.$1;

		//if (handin.showdownText.match(reMatchSummary[site])) {
		//	handin.showdownText = RegExp.$1;
		//}
		handin.showdownLines = handin.showdownText.split(/■/);

		//initialize 2D arrays
		handin.showdown_hands = new Array;   // two pair, Fives and Fours
		handin.showdown_players = new Array; // <nick>
		handin.showdown_cards = new Array;   //  Jh Qs etc
		handin.showdown_types = new Array;   // won, lost, mucked, collected
		handin.result_players = new Array;
		handin.result_values = new Array;

		//loop through showdown lines
		playerCount = -1;
		resultCount = -1;
		
		for (i = 0; i < handin.showdownLines.length; i = i + 1) {
			if (site == HEM) {
				
				if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
					m = findIndex(handin.showdown_players,RegExp.$1);
					if (m == -1) { m = ++playerCount; }
					//playerCount++;
					handin.showdown_players[m] = RegExp.$1;
					handin.showdown_types[m] = "won";
					if (handin.showdownLines[i].match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[m];
						handin.result_values[resultCount] = RegExp.$1;
					}
					

				}
				else if (result = handin.showdownLines[i].match(reHESummaryExtraction2[site])) {
					
					m = findIndex(handin.showdown_players,result[1]);
					if (m > -1) {
						handin.showdown_cards[m] = new Array;
						handin.showdown_cards[m][0] = result[2];
						handin.showdown_cards[m][1] = result[3];
						handin.showdown_hands[m] = " ";
					}
					else {
						playerCount++;
						handin.showdown_cards[playerCount] = new Array;
						handin.showdown_players[playerCount] = result[1];
						handin.showdown_types[playerCount] = "lost";
						handin.showdown_cards[playerCount][0] = result[2];
						handin.showdown_cards[playerCount][1] = result[3];
						handin.showdown_hands[playerCount] = " ";
					}
					
				}
			}
			else if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
				playerCount++;
				handin.showdown_players[playerCount] = RegExp.$1;
				handin.showdown_types[playerCount] = RegExp.$2;
				partTemp = RegExp.$3;
				if (site == CEREUS) { partTemp = RegExp.$2 + RegExp.$3; }
				if (partTemp.match(/( won | collected )/)) {
					handin.showdown_types[playerCount] = "won";
				}
				//else {
				//	handin.showdown_types[playerCount] = "lost";
				//}
				handin.showdown_cards[playerCount] = new Array;
				if (partTemp) {
					if (partTemp.match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[playerCount];
						handin.result_values[resultCount] = RegExp.$1;
					}
					if (partTemp.match(reHESummaryExtraction2[site])) {
						switch(site) {
						case PSTARS:
						case FTP:
							handin.showdown_cards[playerCount][0] = RegExp.$1;
							handin.showdown_cards[playerCount][1] = RegExp.$2;
							if (RegExp.$4) {
								handin.showdown_hands[playerCount] = RegExp.$4;
							}
							break;
						case CEREUS:
							handin.showdown_cards[playerCount][0] = RegExp.$3;
							handin.showdown_cards[playerCount][1] = RegExp.$4;
							handin.showdown_hands[playerCount] = RegExp.$2;
							break;
						}
					}
				}
				else { handin.showdown_cards[playerCount][0] = 'mucks'; }
			}
		}

		//rake
		if (handin.unformatted.match(reRake[site])) {
			handin.rake = RegExp.$1;
		}
	}

	return handin;

}

function parse_omaha(handin, site) {

	//Cash or tournament?
	if (handin.firstLine.match(/\$\d/)) {
		handin.gameType = "C";
		//handin.error = "Tournament hands not yet supported.";
	} else {
		handin.gameType = "T";
	}

	//find blinds
	if (handin.firstLine.match(reBlinds[site])) {
		handin.smallBlind = RegExp.$1;
		handin.bigBlind = RegExp.$2;
	}

	handin.smallBlindPostedAmount = 0;
	handin.bigBlindPostedAmount = 0;

	//find game size
	if (handin.unformatted.match(reGameSize[site])) {
		handin.gameSize = RegExp.$1 + '-max';
	}
	else {
		handin.gameSize = "";
	}

	handin.antesTotal = 0;
	anteLines = new Array;
	//find antes
	anteText = handin.unformattedNoBreaks.match(reAnteText[site]);
   if (anteText) {
		anteLines = anteText[1].split(/■/);
		for (j in anteLines) {
			if (anteLines[j].match(reAnteLines[site])) {
				handin.ante = RegExp.$1;
				handin.antesTotal = parseFloat(handin.antesTotal) + parseFloat(RegExp.$1);
			}
		}
	}
	
	result = handin.unformattedNoBreaks.match(reSeatingText[site]);
	if (result) {handin.seatText = result[1];}
	else {handin.seatText = " ";}

	handin.seatLines = handin.seatText.replace(/■/g, "\n");
	
	//find number of seats
	seats = handin.seatLines.match(reFindSeats[site]);
	handin.numPlayers = seats.length;
	
	// find button/bring-in?
	if (handin.unformatted.match(reButton[site])) {
		handin.button = RegExp.$1;
	}
	
	//find player names and stack sizes
	playerLines = handin.seatLines.match(reFindInfo[site]);
	handin.players = new Array;
	handin.stacks = new Array;
	handin.seatNumbers = new Array;

	j = 0;
	for (i = 0; i < handin.numPlayers; i = i + 1) {
	
		if (playerLines[i].match(rePlayerInfo[site])) {
			theSeat = RegExp.$1;
			thePlayer = RegExp.$2;
			theStack = RegExp.$3;
			if (!((playerLines[i].match(/sitting out/i) && (handin.gameType == "C") && (theSeat != handin.button)))){
				handin.seatNumbers[j] = theSeat;
				handin.players[j] = thePlayer
				handin.stacks[j] = theStack;
				j++;
			}
		}
	}
	if (j > 0) { handin.numPlayers = j; }


	//find hole cards
	handin.holeCards = new Array;
	handin.holeCards[0] = new Array;
	if (handin.unformatted.match(reOHoleCards[site])) {
		handin.hero = RegExp.$1
		handin.holeCards[0][0] = RegExp.$2;
		handin.holeCards[0][1] = RegExp.$3;
		handin.holeCards[0][2] = RegExp.$4;
		handin.holeCards[0][3] = RegExp.$5;
	}

	//initialize 2D arrays
	handin.action_types = new Array;
	handin.action_players = new Array;
	handin.action_values = new Array;
	handin.action_addedToPot = new Array;
	handin.action_playersPot = new Array;

	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//but add in SB
	if (handin.unformatted.match(reSmallBlind[site])) {
		handin.smallBlindPostedBy = RegExp.$1;
		handin.smallBlindPostedAmount = RegExp.$2;
		//playerIndex = handin.players.indexOf(handin.smallBlindPostedBy);
		playerIndex = findIndex(handin.players, handin.smallBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.smallBlindPostedAmount;
	}
	//and BB
	if (handin.unformatted.match(reBigBlind[site])) {
		handin.bigBlindPostedBy = RegExp.$1;
		handin.bigBlindPostedAmount = RegExp.$2;
		//playerIndex = handin.players.indexOf(handin.bigBlindPostedBy);
		playerIndex = findIndex(handin.players, handin.bigBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.bigBlindPostedAmount;
	}
	
	if (!handin.smallBlind) {
		handin.smallBlind = handin.smallBlindPostedAmount;
		handin.bigBlind = handin.bigBlindPostedAmount;
	}	
	//find preflop action
	result = handin.unformattedNoBreaks.match(rePreflopAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(rePreflopActionAlt[site]); }
	if (result) {
		handin.preflopText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.preflopText, 0); }
		if (site == FTP) { handin = ftpParseAction(handin, handin.preflopText, 0); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.preflopText, 0); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.preflopText,0);}
	}

	//get flop cards
	handin.communityCards = new Array;
	handin.communityCards[1] = new Array;
	if (handin.unformatted.match(reFlop[site])) {
		handin.communityCards[1][0] = RegExp.$1;
		handin.communityCards[1][1] = RegExp.$2;
		handin.communityCards[1][2] = RegExp.$3;
	}

	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//find flop action
	result = handin.unformattedNoBreaks.match(reFlopAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(reFlopActionAlt[site]); }
	if (result) {
		handin.flopText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.flopText, 1); }
		else if (site == FTP) { handin = ftpParseAction(handin, handin.flopText, 1); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.flopText, 1); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.flopText,1);}
	}

	//get turn card
	handin.communityCards[2] = new Array;
	if (handin.unformatted.match(reTurn[site])) {
		handin.communityCards[2][0] = RegExp.$1;
	}

	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//find turn action
	result = handin.unformattedNoBreaks.match(reTurnAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(reTurnActionAlt[site]); }
	if (result) {
		handin.turnText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.turnText, 2); }
		else if (site == FTP) { handin = ftpParseAction(handin, handin.turnText, 2); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.turnText, 2); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.turnText,2);}
	}

	//get river card
	handin.communityCards[3] = new Array;
	if (handin.unformatted.match(reRiver[site])) {
		handin.communityCards[3][0] = RegExp.$1;
	}

	//zero out player contributions to pot for this street
	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	//find river action
	result = handin.unformattedNoBreaks.match(reRiverAction[site]);
	if (!result) { result = handin.unformattedNoBreaks.match(reRiverActionAlt[site]); }
	if (result) {
		handin.riverText = RegExp.$1;
		if (site == PSTARS) { handin = pokerStarsParseAction(handin, handin.riverText, 3); }
		else if (site == FTP) { handin = ftpParseAction(handin, handin.riverText, 3); }
		else if (site == CEREUS) { handin = cereusParseAction(handin, handin.riverText, 3); }
		else if (site == HEM) {handin = HEMParseAction(handin,handin.riverText,3);}
	}

	//summary
	if (handin.unformattedNoBreaks.match(reMatchSummary[site])) {
		handin.showdownText = RegExp.$1;

		//if (handin.showdownText.match(reMatchSummary[site])) {
		//	handin.showdownText = RegExp.$1;
		//}
		handin.showdownLines = handin.showdownText.split(/■/);

		//initialize 2D arrays
		handin.showdown_hands = new Array;   // two pair, Fives and Fours
		handin.showdown_players = new Array; // <nick>
		handin.showdown_cards = new Array;   //  Jh Qs etc
		handin.showdown_types = new Array;   // won, lost, mucked, collected
		handin.result_players = new Array;
		handin.result_values = new Array;

		//loop through showdown lines
		playerCount = -1;
		resultCount = -1;
		for (i = 0; i < handin.showdownLines.length; i = i + 1) {
			if (site == HEM) {
				if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
					m = findIndex(handin.showdown_players,RegExp.$1);
					if (m == -1) { m = ++playerCount; }
					//playerCount++;
					handin.showdown_players[m] = RegExp.$1;
					handin.showdown_types[m] = "won";
					if (handin.showdownLines[i].match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[m];
						handin.result_values[resultCount] = RegExp.$1;
					}
				}
				else if (result = handin.showdownLines[i].match(reOSummaryExtraction2[site])) {
					m = findIndex(handin.showdown_players,result[1]);
					if (m > -1) {
						handin.showdown_cards[m] = new Array;
						handin.showdown_cards[m][0] = result[2];
						handin.showdown_cards[m][1] = result[3];
						handin.showdown_cards[m][2] = result[4];
						handin.showdown_cards[m][3] = result[5];
						handin.showdown_hands[m] = " ";
					}
					else {
						playerCount++;
						handin.showdown_cards[playerCount] = new Array;
						handin.showdown_players[playerCount] = result[1];
						handin.showdown_types[playerCount] = "lost";
						handin.showdown_cards[playerCount][0] = result[2];
						handin.showdown_cards[playerCount][1] = result[3];
						handin.showdown_cards[playerCount][2] = result[4];
						handin.showdown_cards[playerCount][3] = result[5];
						handin.showdown_hands[playerCount] = " ";
					}
				}
			}
			else if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
				playerCount++;
				handin.showdown_players[playerCount] = RegExp.$1;
				handin.showdown_types[playerCount] = RegExp.$2;
				partTemp = RegExp.$3;
				if (site == CEREUS) { partTemp = RegExp.$2 + RegExp.$3; }
				if (partTemp.match(/( won | collected | wins )/)) {
					handin.showdown_types[playerCount] = "won";
				}
				//else {
				//	handin.showdown_types[playerCount] = "lost";
				//}
				handin.showdown_cards[playerCount] = new Array;
				if (partTemp) {
					if (partTemp.match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[playerCount];
						handin.result_values[resultCount] = RegExp.$1;
					}
					if (partTemp.match(reOSummaryExtraction2[site])) {
						switch(site) {
						case PSTARS:
						case FTP:
							if (RegExp.$6) {
								handin.showdown_hands[playerCount] = RegExp.$6;
							}
							handin.showdown_cards[playerCount][0] = RegExp.$1;
							handin.showdown_cards[playerCount][1] = RegExp.$2;
							handin.showdown_cards[playerCount][2] = RegExp.$3;
							handin.showdown_cards[playerCount][3] = RegExp.$4;
							break;
						case CEREUS:
							handin.showdown_cards[playerCount][0] = RegExp.$3;
							handin.showdown_cards[playerCount][1] = RegExp.$4;
							handin.showdown_cards[playerCount][2] = RegExp.$5;
							handin.showdown_cards[playerCount][3] = RegExp.$6;
							handin.showdown_hands[playerCount] = RegExp.$2;
							break;
						}
					}
				}
				else { handin.showdown_cards[playerCount][0] = 'mucks'; }
			}
		}
		

		//rake
		if (handin.unformatted.match(reRake[site])) {
			handin.rake = RegExp.$1;
		}
	}

	return handin;

}

function parse_pokerstars_draw(handin, site) {

	//Cash or tournament?
	if (handin.firstLine.match(/\$\d/)) {
		handin.gameType = "C";
		//handin.error = "Tournament hands not yet supported.";
	} else {
		handin.gameType = "T";
	}

	//find blinds
	if (handin.firstLine.match(reBlinds[site])) {
		handin.smallBlind = RegExp.$1;
		handin.bigBlind = RegExp.$2;
	}

	handin.smallBlindPostedAmount = 0;
	handin.bigBlindPostedAmount = 0;

	//find game size
	if (handin.unformatted.match(reGameSize[site])) {
		handin.gameSize = RegExp.$1 + '-max';
	}
	else {
		handin.gameSize = "";
	}

	handin.antesTotal = 0;
	anteLines = new Array;
	//find antes
	anteText = handin.unformattedNoBreaks.match(reAnteText[site]);
   if (anteText) {
		anteLines = anteText[1].split(/■/);
		for (j in anteLines) {
			if (anteLines[j].match(reAnteLines[site])) {
				handin.ante = RegExp.$1;
				handin.antesTotal = parseFloat(handin.antesTotal) + parseFloat(RegExp.$1);
			}
		}
	}
	
	result = handin.unformattedNoBreaks.match(reSeatingText[site]);
	if (result) {handin.seatText = result[1];}
	else {handin.seatText = " ";}

	handin.seatLines = handin.seatText.replace(/■/g, "\n");
	
	//find number of seats
	seats = handin.seatLines.match(reFindSeats[site]);
	handin.numPlayers = seats.length;
	
	// find button/bring-in?
	if (handin.unformatted.match(reButton[site])) {
		handin.button = RegExp.$1;
	}
	
	//find player names and stack sizes
	playerLines = handin.seatLines.match(reFindInfo[site]);
	handin.players = new Array;
	handin.stacks = new Array;
	handin.seatNumbers = new Array;

	j = 0;
	for (i = 0; i < handin.numPlayers; i = i + 1) {
		
		if (playerLines[i].match(rePlayerInfo[site])) {
			theSeat = RegExp.$1;
			thePlayer = RegExp.$2;
			theStack = RegExp.$3;
			if (!((playerLines[i].match(/sitting out/i) && (handin.gameType == "C") && (theSeat != handin.button)))){
				handin.seatNumbers[j] = theSeat;
				handin.players[j] = thePlayer;
				handin.stacks[j] = theStack;
				j++;
			}
		}
	}
	if (j > 0) { handin.numPlayers = j; }

	//find cards
	handin.holeCards = new Array;
	var myRegEx = new RegExp("");

	//get hero
	for (x = 0; x < handin.numPlayers; x++) {
		handin.holeCards[x] = new Array;
		myRegEx.compile(reGetHandPre[site] + handin.players[x] + reTDGetHandPost[site], "g");
		result = handin.unformattedNoBreaks.match(myRegEx);
		if (result) {
			handin.hero = handin.players[x];
			heropos = x;
			x = handin.numplayers;
		}
	}

	//initialize 2D arrays
	handin.action_types = new Array;
	handin.action_players = new Array;
	handin.action_values = new Array;
	handin.showdown_types = new Array;
	handin.action_addedToPot = new Array;
	handin.action_playersPot = new Array;

	for (r in handin.players) {
		handin.action_playersPot[r] = 0;
	}

	handin.antesTotal = 0;
	anteLines = new Array;
	anteText = handin.unformattedNoBreaks.match(/(.*?)\*\*\* DEAL/);
	anteLines = anteText[0].split(/■/);
	for (j in anteLines) {
		if (anteLines[j].match(/posts the ante [\$|](\d+\.\d+|\d+)/)) {
			handin.antesTotal = parseFloat(handin.antesTotal) + parseFloat(result[1]);
		}
	}
	// regexstring = /(.+)\: posts small blind [\$|](\d+|\d+\.\d+)/;
	result = handin.unformatted.match(/(.+)\: posts small blind [\$|](\d+\.\d+|\d+)/i);
	if (result) {
		handin.smallBlindPostedBy = result[1];
		handin.smallBlindPostedAmount = result[2];
		playerIndex = findIndex(handin.players, handin.smallBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.smallBlindPostedAmount;
		//handin.action_addedToPot[0] = handin.smallBlindPostedAmount;
	}

	// regexstring = /(.+)\: posts big blind [\$|](\d+\.\d+|\d+)/;
	result = handin.unformatted.match(/(.+)\: posts big blind [\$|](\d+\.\d+|\d+)/i);
	if (result) {
		handin.bigBlindPostedBy = result[1];
		handin.bigBlindPostedAmount = result[2];
		playerIndex = findIndex(handin.players, handin.bigBlindPostedBy);
		handin.action_playersPot[playerIndex] = handin.bigBlindPostedAmount;
		//handin.action_addedToPot[0] += handin.bigBlindPostedAmount;
	}

	//get street cards named desire
	//streetRegEx = new Array(/DEALING HANDS \*\*\*\|(.*)\*\*\* FIRST/i, /FIRST DRAW \*\*\*\|(.*)\*\*\* SECOND/i, /SECOND DRAW \*\*\*\|(.*)\*\*\* THIRD/i, /THIRD DRAW \*\*\*\|(.*)\*\*\* SHOW/i);
	//streetRegExAlt = new Array(/DEALING HANDS \*\*\*\|(.*)\*\*\* sum/i, /FIRST DRAW \*\*\*\|(.*)\*\*\* sum/i, /SECOND DRAW \*\*\*\|(.*)\*\*\* sum/i, /THIRD DRAW \*\*\*\|(.*)\*\*\* sum/i);
	handin.communityCards = new Array;
	handin.communityCards[1] = new Array;
	cardCount = 0;
	var thisRegEx = new RegExp;
	for (x in reTDStreetMatch[site]) {
		thisRegEx.compile(reTDStreetMatch[site][x]);
		outerresult = thisRegEx.exec(handin.unformattedNoBreaks);
		if (!outerresult) {
			thisRegEx.compile(reTDStreetMatchAlt[site][x]);
			outerresult = thisRegEx.exec(handin.unformattedNoBreaks);
		}
		if (outerresult) {
			handin = pokerStarsParseAction(handin, outerresult[1], x);
			myRegEx.compile("Dealt to " + handin.hero + "( \\[(.*)\\])");
			outerLines = outerresult[1].split(/■/);
			result = outerresult[1].match(myRegEx);
			if (!result) {
				myRegEx.compile(handin.hero + ": stands pat on (\\[(.*)\\])");
				result = outerresult[1].match(myRegEx);
			}
			if (result) {
				subresult = result[1].match(/([2-9TJQKA][hdsc])/g);
				for (y in subresult) {
					handin.holeCards[heropos][handin.holeCards[heropos].length] = subresult[y];
				}
			}
		}
		//zero out player contributions to pot for next street
		for (r in handin.players) {
			handin.action_playersPot[r] = 0;
		}
	}

	//summary
	if (handin.unformattedNoBreaks.match(reMatchSummary[site])) {
		handin.showdownText = RegExp.$1;

		//if (handin.showdownText.match(reMatchSummary[site])) {
		//	handin.showdownText = RegExp.$1;
		//}
		handin.showdownLines = handin.showdownText.split(/■/);

		//initialize 2D arrays
		handin.showdown_hands = new Array;   // two pair, Fives and Fours
		handin.showdown_players = new Array; // <nick>
		handin.showdown_cards = new Array;   //  Jh Qs etc
		handin.showdown_types = new Array;   // won, lost, mucked, collected
		handin.result_players = new Array;
		handin.result_values = new Array;

		//loop through showdown lines
		playerCount = -1;
		resultCount = -1;
		for (i = 0; i < handin.showdownLines.length; i = i + 1) {
			if (site == HEM) {
				if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
					m = findIndex(handin.showdown_players,RegExp.$1);
					if (m == -1) { m = ++playercount; }
					//playerCount++;
					handin.showdown_players[m] = RegExp.$1;
					handin.showdown_types[m] = "won";
					if (handin.showdownLines[i].match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[m];
						handin.result_values[resultCount] = RegExp.$1;
					}
				}
				else if (result = handin.showdownLines[i].match(reTDSummaryExtraction2[site])) {
					m = findIndex(handin.showdown_players,result[1]);
					if (m > -1) {
						handin.showdown_cards[m] = new Array;
						handin.showdown_cards[m][0] = result[2];
						handin.showdown_cards[m][1] = result[3];
						handin.showdown_cards[m][2] = result[4];
						handin.showdown_cards[m][3] = result[5];
						handin.showdown_cards[m][4] = result[6];
						handin.showdown_hands[m] = " ";
					}
					else {
						playerCount++;
						handin.showdown_cards[playerCount] = new Array;
						handin.showdown_players[playerCount] = result[1];
						handin.showdown_types[playerCount] = "lost";
						handin.showdown_cards[playerCount][0] = result[2];
						handin.showdown_cards[playerCount][1] = result[3];
						handin.showdown_cards[playerCount][2] = result[4];
						handin.showdown_cards[playerCount][3] = result[5];
						handin.showdown_cards[playerCount][4] = result[6];
						handin.showdown_hands[playerCount] = " ";
					}
				}
			}
			else if (handin.showdownLines[i].match(reSummaryExtraction1[site])) {
				playerCount++;
				handin.showdown_players[playerCount] = RegExp.$1;
				handin.showdown_types[playerCount] = RegExp.$2;
				partTemp = RegExp.$3;
				if (site == CEREUS) { partTemp = RegExp.$2 + RegExp.$3; }
				if (partTemp.match(/( won | collected | wins )/)) {
					handin.showdown_types[playerCount] = "won";
				}
				//else {
				//	handin.showdown_types[playerCount] = "lost";
				//}
				handin.showdown_cards[playerCount] = new Array;
				if (partTemp) {
					if (partTemp.match(reTheMoney[site])) {
						resultCount++;
						handin.result_players[resultCount] = handin.showdown_players[playerCount];
						handin.result_values[resultCount] = RegExp.$1;
					}
					if (partTemp.match(reTDSummaryExtraction2[site])) {
						switch(site) {
						case PSTARS:
						case FTP:
							if (RegExp.$7) {
								handin.showdown_hands[playerCount] = RegExp.$7;
							}
							handin.showdown_cards[playerCount][0] = RegExp.$1;
							handin.showdown_cards[playerCount][1] = RegExp.$2;
							handin.showdown_cards[playerCount][2] = RegExp.$3;
							handin.showdown_cards[playerCount][3] = RegExp.$4;
							handin.showdown_cards[playerCount][4] = RegExp.$5;
							break;
						case CEREUS:
							handin.showdown_cards[playerCount][0] = RegExp.$3;
							handin.showdown_cards[playerCount][1] = RegExp.$4;
							handin.showdown_cards[playerCount][2] = RegExp.$5;
							handin.showdown_cards[playerCount][3] = RegExp.$6;
							handin.showdown_cards[playerCount][4] = RegExp.$7;
							handin.showdown_hands[playerCount] = RegExp.$2;
							break;
						}
					}
				}
				else { handin.showdown_cards[playerCount][0] = 'mucks'; }
			}
		}
		

		//rake
		if (handin.unformatted.match(reRake[site])) {
			handin.rake = RegExp.$1;
		}
	}

	return handin;

}

String.prototype.capitalize = function(){ //v1.0
    return this.replace(/\w+/g, function(a){
        return a.charAt(0).toUpperCase() + a.substr(1).toLowerCase();
    });
};

function handToText(handin, outputType,showNames,showResults) {

	//call ev calculator for debugging
	//var EVresults = fcp_EV_Calculator(handin,10);
	
	// this function takes the hand structure and formats the text output
	
	skipshowdown = 0;

	//output Formats
	var FCO = 0; // Feral Cow Original / 4betbluff.com
	var FCP = 1; //Full Contact Poker
	var TPT = 2; //Two Plus Two
	var IRC = 4; //IRC
	var HTML = 5; //html
	var AIM = 7; //AIM
	var FCONC = 20; // Feral Cow Original with new cards
	ot = outputType;
    if (outputType == 3) {ot = 2;}; //poker road
	if (outputType == 6) {ot = 5;}; //html formatted same as HTML
	if (outputType == 8)  {ot =5;}; //Pocket 5's takes HTML
	if (outputType == 9) {ot = 2;}; //generic bbcode
	if (outputType ==10) {ot=7;}; //text-only HTML is unformatted AIM
	
	
	//color settings
	titleColor = '#0000AA';
	betColor = '#AA0000';
	textColor = '#000000';
	foldColor = '#888888';
	playersLeftColor = '#006600';
	
	//format-specific text
	var lineBreaks = new Array();
	lineBreaks[FCO] = "\n";
	lineBreaks[FCP] = "\n";
	lineBreaks[TPT] = "\n";
	lineBreaks[IRC] = "\n";
	lineBreaks[HTML] = "<br>";
	lineBreaks[AIM] = "<br>";
	lineBreaks[FCONC] = "\n";
	
	var feralcowicon = new Array();
	feralcowicon[FCO] = "[img]http://www.feralcowpoker.com/images/feral_cow_icon.gif[/img]";
	feralcowicon[FCONC] = "[img]http://www.feralcowpoker.com/images/feral_cow_icon.gif[/img]";
	feralcowicon[FCP] = "[img]http://www.feralcowpoker.com/images/feral_cow_icon.gif[/img]";
	feralcowicon[TPT] = "[img]http://www.feralcowpoker.com/images/feral_cow_icon.gif[/img]";
	feralcowicon[IRC] = "`O.o' ";
	feralcowicon[HTML] = "<img src=http://www.feralcowpoker.com/images/feral_cow_icon.gif>";
	feralcowicon[AIM] = "";
	
	var cardPrefix = new Array();
	var cardPostfix = new Array();
	cardPrefix[FCO] = ':';
	cardPostfix[FCO] = ':';
	cardPrefix[FCONC] = '[img]http://www.feralcowpoker.com/images/cards/' + cardFolder + '/';
	cardPostfix[FCONC] = '.gif[/img]';
	cardPrefix[FCP] = ':';
	cardPostfix[FCP] = '';
	cardPrefix[TPT] = '[img]http://www.feralcowpoker.com/images/cards/'+ cardFolder + '/';
	cardPostfix[TPT] = '.gif[/img]';
	cardPrefix[IRC] = String.fromCharCode(2);;
	cardPostfix[IRC] = String.fromCharCode(2);;
	cardPrefix[HTML] = '<img src=http://www.feralcowpoker.com/images/cards/'+ cardFolder + '/';
	cardPostfix[HTML] = '.gif>';
	cardPrefix[AIM] = '';
	cardPostfix[AIM] = '';


	
	var tagLinePrefix = new Array();
	var tagLinePostfix = new Array();
	tagLinePrefix[FCO] = '[color=' +  titleColor + '][size=1]v'+version+'[/size][/color]';
	tagLinePostfix[FCO] = '';
	tagLinePrefix[FCONC] = '[color=' +  titleColor + '][size=1]v'+version+'[/size][/color]';
	tagLinePostfix[FCONC] = '';
	tagLinePrefix[FCP] = '[url=http://www.feralcowpoker.com/converter.php?version=' + version +']';
	tagLinePostfix[FCP] = '[/url]';
	tagLinePrefix[TPT] = '[url=http://www.feralcowpoker.com/converter.php?version=' + version +']';
	tagLinePostfix[TPT] = '[/url]';
	tagLinePrefix[IRC] = String.fromCharCode(2);
	tagLinePostfix[IRC] = String.fromCharCode(2);
	tagLinePrefix[HTML] = '<a href=http://www.feralcowpoker.com/converter.php?version='+version+'>';
	tagLinePostfix[HTML] = '</a>';
	tagLinePrefix[AIM] = '<a href=http://www.feralcowpoker.com/converter.php?version='+version+'>';
	tagLinePostfix[AIM] = '</a>';
	
	var gameInfoPre = new Array();
	var gameInfoPost = new Array();
	gameInfoPre[FCO] = "";
	gameInfoPost[FCO] = "";
	gameInfoPre[FCONC] = "";
	gameInfoPost[FCONC] = "";
	gameInfoPre[FCP] = "";
	gameInfoPost[FCP] = "";
	gameInfoPre[TPT] = "";
	gameInfoPost[TPT] = "";
	gameInfoPre[IRC] = String.fromCharCode(3) + "0,14" + String.fromCharCode(2) + String.fromCharCode(31);
	gameInfoPost[IRC] = String.fromCharCode(3) + "1" + String.fromCharCode(2) + String.fromCharCode(31);
	gameInfoPre[HTML] = "<b>";
	gameInfoPost[HTML] = "</b>";
	gameInfoPre[AIM] = "<b>";
	gameInfoPost[AIM] = "</b>";

	var holecardPre = new Array();
	var holecardPost = new Array();
	holecardPre[FCO] = "[holecard]";
	holecardPost[FCO] = "[/holecard]";
	holecardPre[FCONC] = "[holecard]";
	holecardPost[FCONC] = "[/holecard]";
	holecardPre[FCP] = "[:";
	holecardPost[FCP] = "]";
	holecardPre[TPT] = "[[img]http://www.feralcowpoker.com/images/cards/"+ cardFolder + '/';
	holecardPost[TPT] = ".gif[/img]]";
	holecardPre[IRC] = "[";
	holecardPost[IRC] = "]";
	holecardPre[HTML] = "[";
	holecardPost[HTML] = "]";
	holecardPre[AIM] = "[";
	holecardPost[AIM] = "]";
	
	var unknownCard = new Array();
	unknownCard[FCO] = ":1s:";
	unknownCard[FCONC] = ":1s:";
	unknownCard[FCP] = "[X]";
	unknownCard[TPT] = "[X]";
	unknownCard[IRC] = "[X]";
	unknownCard[HTML] = "[X]";
	unknownCard[AIM] = "[X]";
	
	var positionPre = new Array();
	var positionPost = new Array();
	positionPre[FCO] = "";
	positionPost[FCO] = "";
	positionPre[FCONC] = "";
	positionPost[FCONC] = "";
	positionPre[FCP] = "";
	positionPost[FCP] = "";
	positionPre[TPT] = "";
	positionPost[TPT] = "";
	positionPre[IRC] = String.fromCharCode(2);
	positionPost[IRC] = String.fromCharCode(2);	
	positionPre[HTML] = "";
	positionPost[HTML] = "";
	positionPre[AIM] = "";
	positionPost[AIM] = "";
	
	var playerNamePre = new Array();
	var playerNamePost = new Array();
	playerNamePre[FCO] = "[color=#4B0082]";
	playerNamePost[FCO] = "[/color]";
	playerNamePre[FCONC] = "[color=#4B0082]";
	playerNamePost[FCONC] = "[/color]";
	playerNamePre[FCP] = "[color=#4B0082]";
	playerNamePost[FCP] = "[/color]";
	playerNamePre[TPT] = "[color=#4B0082]";
	playerNamePost[TPT] = "[/color]";
	playerNamePre[IRC] = "";
	playerNamePost[IRC] = "";	
	playerNamePre[HTML] = "<font color=#4B0082>";
	playerNamePost[HTML] = "</font>";
	playerNamePre[AIM] = "<font color=#4B0082>";
	playerNamePost[AIM] = "</font>";
	
	var endStackLine = new Array();
	endStackLine[FCO] = "\n";
	endStackLine[FCONC] = "\n";
	endStackLine[FCP] = "\n";
	endStackLine[TPT] = "\n";
	endStackLine[IRC] = " | ";
	endStackLine[HTML] = "<br>";
	endStackLine[AIM] = "<br>";
	
	var streetNamePre = new Array();
	var streetNamePost = new Array();
	streetNamePre[FCO] = "[b]";
	streetNamePost[FCO] = "[/b]";
	streetNamePre[FCONC] = "[b]";
	streetNamePost[FCONC] = "[/b]";
	streetNamePre[FCP] = "[b]";
	streetNamePost[FCP] = "[/b]";
	streetNamePre[TPT] = "[b]";
	streetNamePost[TPT] = "[/b]";
	streetNamePre[IRC] = String.fromCharCode(2) + String.fromCharCode(31);
	streetNamePost[IRC] = String.fromCharCode(2) + String.fromCharCode(31);
	streetNamePre[HTML] = "<b>";
	streetNamePost[HTML] = "</b>";
	streetNamePre[AIM] = "<b>";
	streetNamePost[AIM] = "</b>";
	
	var playersLeftPre = new Array();
	var playersLeftPost = new Array();
	playersLeftPre[FCO] = "[color=" + playersLeftColor + "]";
	playersLeftPost[FCO] = "[/color]";
	playersLeftPre[FCONC] = "[color=" + playersLeftColor + "]";
	playersLeftPost[FCONC] = "[/color]";
	playersLeftPre[FCP] = "[color=" + playersLeftColor + "]";
	playersLeftPost[FCP] = "[/color]";
	playersLeftPre[TPT] = "[color=" + playersLeftColor + "]";
	playersLeftPost[TPT] = "[/color]";
	playersLeftPre[IRC] = String.fromCharCode(3) + "6";
	playersLeftPost[IRC] = String.fromCharCode(3) + "1";
	playersLeftPre[HTML] = "<font color=" + playersLeftColor + ">";
	playersLeftPost[HTML] = "</font>";
	playersLeftPre[AIM] = "<font color=" + playersLeftColor + ">";
	playersLeftPost[AIM] = "</font>";


	var foldsPre = new Array();
	var foldsPost = new Array();
	foldsPre[FCO] = "[i][color=" + foldColor + "]";
	foldsPost[FCO] = "[/i][/color]";
	foldsPre[FCONC] = "[i][color=" + foldColor + "]";
	foldsPost[FCONC] = "[/i][/color]";
	foldsPre[FCP] = "[i][color=" + foldColor + "]";
	foldsPost[FCP] = "[/i][/color]";
	foldsPre[TPT] = "[i][color=" + foldColor + "]";
	foldsPost[TPT] = "[/i][/color]";
	foldsPre[IRC] = "";
	foldsPost[IRC] = "";
	foldsPre[HTML] = "<i><font color =" + foldColor + ">";
	foldsPost[HTML] = "</i></font>";
	foldsPre[AIM] = "<i><font color =" + foldColor + ">";
	foldsPost[AIM] = "</i></font>";
	
	var betActionPre = new Array();
	var betActionPost = new Array();
	betActionPre[FCO] = "[color=" + betColor + "]"; 
	betActionPost[FCO] = "[/color]";
	betActionPre[FCONC] = "[color=" + betColor + "]"; 
	betActionPost[FCONC] = "[/color]";
	betActionPre[FCP] = "[color=" + betColor + "]"; 
	betActionPost[FCP] = "[/color]";
	betActionPre[TPT] = "[color=" + betColor + "]"; 
	betActionPost[TPT] = "[/color]";
	betActionPre[IRC] = ""; 
	betActionPost[IRC] = "";
	betActionPre[HTML] = "<font color=" + betColor + ">"; 
	betActionPost[HTML] = "</font>";
	betActionPre[AIM] = "<font color=" + betColor + ">"; 
	betActionPost[AIM] = "</font>";
	
	var regActionPre = new Array();
	var regActionPost = new Array();
	regActionPre[FCO] = "[color=" + textColor + "]"; 
	regActionPost[FCO] = "[/color]";
	regActionPre[FCONC] = "[color=" + textColor + "]"; 
	regActionPost[FCONC] = "[/color]";
	regActionPre[FCP] = "[color=" + textColor + "]"; 
	regActionPost[FCP] = "[/color]";
	regActionPre[TPT] = "[color=" + textColor + "]"; 
	regActionPost[TPT] = "[/color]";
	regActionPre[IRC] = ""; 
	regActionPost[IRC] = "";
	regActionPre[HTML] = "<font color=" + textColor + ">"; 
	regActionPost[HTML] = "</font>";
	regActionPre[AIM] = "<font color=" + textColor + ">"; 
	regActionPost[AIM] = "</font>";

	
	var suitPre = new Array();
	var suitPost = new Array();
	suitPre['h'] = new Array();
	suitPost['h'] = new Array();
	suitPre['h'][FCO] = "";
	suitPost['h'][FCO] = ""; 
	suitPre['h'][FCONC] = "";
	suitPost['h'][FCONC] = ""; 
	suitPre['h'][FCP] = "";
	suitPost['h'][FCP] = ""; 
	suitPre['h'][TPT] = "";
	suitPost['h'][TPT] = ""; 
	suitPre['h'][IRC] = String.fromCharCode(3) + "4 ";
	suitPost['h'][IRC] = String.fromCharCode(3) + "1 ";
	suitPre['h'][HTML] = "";
	suitPost['h'][HTML] = ""; 
	suitPre['h'][AIM] = "<b><font color=#AA0000>";
	suitPost['h'][AIM] = "</font></b>"; 
	suitPre['c'] = new Array();
	suitPost['c'] = new Array();
	suitPre['c'][FCO] = "";
	suitPost['c'][FCO] = ""; 
	suitPre['c'][FCONC] = "";
	suitPost['c'][FCONC] = "";
	suitPre['c'][FCP] = "";
	suitPost['c'][FCP] = ""; 
	suitPre['c'][TPT] = "";
	suitPost['c'][TPT] = ""; 
	suitPre['c'][IRC] = String.fromCharCode(3) + "3 ";
	suitPost['c'][IRC] = String.fromCharCode(3) + "1 ";
	suitPre['c'][HTML] = "";
	suitPre['c'][AIM] = "<b><font color=#00AA00>"; 
	suitPost['c'][AIM] = "</font></b>";
	suitPost['c'][HTML] = "";
	suitPre['s'] = new Array();
	suitPost['s'] = new Array();
	suitPre['s'][FCO] = "";
	suitPost['s'][FCO] = ""; 
	suitPre['s'][FCONC] = "";
	suitPost['s'][FCONC] = ""; 
	suitPre['s'][FCP] = "";
	suitPost['s'][FCP] = ""; 
	suitPre['s'][TPT] = "";
	suitPost['s'][TPT] = ""; 
	suitPre['s'][IRC] = String.fromCharCode(3) + "14 ";
	suitPost['s'][IRC] = String.fromCharCode(3) + "1 ";
	suitPre['s'][HTML] = "";
	suitPost['s'][HTML] = ""; 
	suitPre['s'][AIM] = "<b>";
	suitPost['s'][AIM] = "</b>";
	suitPre['d'] = new Array();
	suitPost['d'] = new Array();
	suitPre['d'][FCO] = "";
	suitPost['d'][FCO] = "";
	suitPre['d'][FCONC] = "";
	suitPost['d'][FCONC] = ""; 
	suitPre['d'][FCP] = "";
	suitPost['d'][FCP] = ""; 
	suitPre['d'][TPT] = "";
	suitPost['d'][TPT] = ""; 
	suitPre['d'][IRC] = String.fromCharCode(3) + "12 ";
	suitPost['d'][IRC] = String.fromCharCode(3) + "1 ";
	suitPre['d'][HTML] = "";
	suitPost['d'][HTML] = ""; 
	suitPre['d'][AIM] = "<b><font color=#0000AA>";
	suitPost['d'][AIM] = "</font></b>"; 
	
	var whiteResultsPre = new Array();
	var whiteResultsPost = new Array();
	whiteResultsPre[FCO] = "[spoiler]";
	whiteResultsPost[FCO] = "[/spoiler]";
	whiteResultsPre[FCONC] = "[spoiler]";
	whiteResultsPost[FCONC] = "[/spoiler]";
	whiteResultsPre[FCP] = "[spoiler]";
	whiteResultsPost[FCP] = "[/spoiler]";
	whiteResultsPre[TPT] = "[color=#FFFFFF]";
	whiteResultsPost[TPT] = "[/color]";
	whiteResultsPre[IRC] = String.fromCharCode(3) + "0 ";
	whiteResultsPost[IRC] = String.fromCharCode(3) + "1 ";
	whiteResultsPre[HTML] = "<font color=#FFFFFF>";
	whiteResultsPost[HTML] = "</font>";
	whiteResultsPre[AIM] = "<font color=#FFFFFF>";
	whiteResultsPost[AIM] = "</font>";
	
	var whiteCardsPre = new Array();
	var whiteCardsPost = new Array();
	whiteCardsPre[FCO] = "";
	whiteCardsPost[FCO] = "";
	whiteCardsPre[FCONC] = "";
	whiteCardsPost[FCONC] = "";
	whiteCardsPre[FCP] = "";
	whiteCardsPost[FCP] = "";
	whiteCardsPre[TPT] = "";
	whiteCardsPost[TPT] = "";
	whiteCardsPre[IRC] = "";
	whiteCardsPost[IRC] = "";
	whiteCardsPre[HTML] = "";
	whiteCardsPost[HTML] = "";
	whiteCardsPre[AIM] = "";
	whiteCardsPost[AIM] = "";

	
	
	if (handin.error) {

		tx = handin.error;

	} else if (debug) {

		//for firebug
		
		
		//print out all the info unformatted for debugging purposes
		tx = '[b]Feral Converter[/b]\n';
		tx = tx + 'site: \n' + handin.site;
		tx = tx + '\ngamelong: ' + handin.gameLong;
		tx = tx + '\ngamesize: ' + handin.gameSize;
		tx = tx + '\nblinds: ' + handin.smallBlind + '/' + handin.bigBlind + '\n';
		tx = tx + 'Gametype: ' + handin.gameType + '\n';
		tx = tx + 'Players: ' + handin.numPlayers;
		tx = tx + '\nPlayers: ' + handin.players;
		tx = tx + '\nseat numbers: ' + handin.seatNumbers;
		tx = tx + '\nStacks: ' + handin.stacks;
		tx = tx + '\nButton: Seat ' + handin.button;
		tx = tx + '\nHole cards: '
		for (x in handin.holeCards) {
			for (y in handin.holeCards[x]) {
				tx = tx + handin.holeCards[x][y];
			}
			tx = tx + '\n';
		}
		tx = tx + '\n\npf names: ' + handin.action_players[0];
		tx = tx + '\nhero: ' + handin.hero;
		tx = tx + '\nbig blind posted by ' + handin.bigBlindPostedBy + ', amount = ' + handin.bigBlindPostedAmount;
		tx = tx + '\nsmall blind posted by ' + handin.smallBlindPostedBy + ', amount = ' + handin.smallBlindPostedAmount;
		tx = tx + '\nante: ' + handin.ante;
		tx = tx + '\nantestotal: ' + handin.antesTotal;
		tx = tx + '\npf actions: ' + handin.action_types[0];
		tx = tx + '\npf values: ' + handin.action_values[0];
		tx = tx + '\npf added: ' + handin.action_addedToPot[0];
		tx = tx + '\n\nflop: ' + handin.communityCards[1];
		tx = tx + '\nf names: ' + handin.action_players[1];
		tx = tx + '\nf actions: ' + handin.action_types[1];
		tx = tx + '\nf values: ' + handin.action_values[1];
		tx = tx + '\nf added: ' + handin.action_addedToPot[1];
		tx = tx + '\n\nturn: ' + handin.communityCards[2];
		tx = tx + '\nt names: ' + handin.action_players[2];
		tx = tx + '\nt actions: ' + handin.action_types[2];
		tx = tx + '\nt values: ' + handin.action_values[2];
		tx = tx + '\nt added: ' + handin.action_addedToPot[2];
		tx = tx + '\n\nriver: ' + handin.communityCards[3];
		tx = tx + '\nr names: ' + handin.action_players[3];
		tx = tx + '\nr actions: ' + handin.action_types[3];
		tx = tx + '\nr values: ' + handin.action_values[3];
		tx = tx + '\nr added: ' + handin.action_addedToPot[3];
		tx = tx + '\n\nsd players: ' + handin.showdown_players;
		tx = tx + '\nsd cards: ' + handin.showdown_cards;
		tx = tx + '\nsd hands: ' + handin.showdown_hands;
		tx = tx + '\nresult players: ' + handin.result_players;
		tx = tx + '\nresult players: ' + handin.result_values;
		tx = tx + '\nrake: ' + handin.rake;

		tx = tx + '\n\nmessage: ' + handin.message;
	} else {

		if (handin.gameType == "C") {
			chipPrefix = '$';
		}
		else {
			chipPrefix = 't';
		}

		//are we playing a limit game? 
		if (handin.gameShort == 'LHE' || handin.gameLong == 'Limit Omaha' || handin.gameLong == 'Limit Omaha Hi/Lo') {
			isLimitGame = 1;
		} else {
			isLimitGame = 0;
		}
		
		//any garbage that was rejected prior to first line
		tx = handin.prefix;
		if (handin.prefix.length > 0) {tx = tx + '\n';}
		
		//tagline
		tagLine = getRandomTagLine();
		tx = tx + feralcowicon[ot] + tagLinePrefix[ot] + tagLine + tagLinePostfix[ot] + lineBreaks[ot];

		//game info
		if (handin.HEMOriginalSite) {
			tx = tx + gameInfoPre[ot] + 'HEM/' + handin.HEMOriginalSite + ' ' + handin.gameLong + ' ';
		} else {
			tx = tx + gameInfoPre[ot] + handin.site + ' ' + handin.gameLong + ' ';
		}
		
		//tourney buyin
		if (handin.tourneyBuyin) {
			tx = tx + '(' + handin.tourneyBuyin + ') ';
		}

		//blinds
		tx = tx + chipPrefix + handin.smallBlind + '/' + chipPrefix + handin.bigBlind + ' ';

		//antes
		if (handin.ante) {
			tx = tx + 'ante ' + chipPrefix + handin.ante + ' ';
		}

		//number of players
		tx = tx + '- ' + handin.numPlayers + ' players' + gameInfoPost[ot] + lineBreaks[ot];

		//street & position names
		handin.streetName = new Array;
		if (handin.gameShort == 'NLHE' | handin.gameShort == 'LHE' | handin.gameShort == 'OMAHA' | handin.gameShort == 'PLHE') {
			handin.streetName[0] = 'Preflop';
			handin.streetName[1] = 'Flop';
			handin.streetName[2] = 'Turn';
			handin.streetName[3] = 'River';

			//figure out position labels
			getPositionNames(handin);
		}
		else if (handin.gameShort == 'STUD' | handin.gameShort == 'RAZZ') {
			handin.streetName[0] = '3rd Street';
			handin.streetName[1] = '4th Street';
			handin.streetName[2] = '5th Street';
			handin.streetName[3] = '6th Street';
			handin.streetName[4] = 'River';

			//figure out position labels
			getPositionNamesStud(handin);
		}
		else if (handin.gameShort == 'DRAW') {
			handin.streetName[0] = 'Dealing Hands';
			handin.streetName[1] = 'First Draw';
			handin.streetName[2] = 'Second Draw';
			handin.streetName[3] = 'Third Draw';

			//figure out position labels
			getPositionNames(handin);
		}
	
		
		numDigits = 0;
		//number of digits to print out pot sizes to
		if (handin.gameType == "C") {
			numDigits = 2;
			numDigitsPot = 2;
		} else {
			numDigits = 0;
			if (isLimitGame) {
				numDigitsPot = 2;
			} else {
				numDigitsPot = 0;
			}
		}

		//stack sizes
		tx = tx + lineBreaks[ot];
		for (i in handin.players) {
			if (handin.players[i] == handin.hero) {
				if (!showNames) {
					herotext = ' (Hero)';
				} else {
					herotext = '';
				}
			} else {
				herotext = '';
			}
			
			var tempStack = cleanNum(handin.stacks[i]);
						
			// tempStack.toFloat(handin.stacks[i]);
			tx = tx + positionPre[ot] + handin.positions[i] + positionPost[ot];
			if (showNames) {
				if (handin.players[i] == handin.hero) {
					//even though we show names, we hide hero's name
					tx = tx + playerNamePre[ot]+ " Hero" + playerNamePost[ot]; 
				} else {
					tx = tx + playerNamePre[ot]+ " " + handin.players[i] + playerNamePost[ot];
				}
			}
			tx = tx + ': ' + chipPrefix + addCommas(tempStack.toFixed(numDigits));
			if (handin.gameShort == 'STUD' | handin.gameShort == 'RAZZ') {
				for (k in handin.holeCards[i]) {
					if ((handin.holeCards[i].length == 7) && (herotext == '') && ((k < 2) || (k == 6))) {
						tx = tx + ' ' + holecardPre[ot] + handin.holeCards[i][k].capitalize() + holecardPost[ot];
						
					}
					else {
						if (handin.holeCards[i][k] == '1s') {
							tx = tx + ' ' + unknownCard[ot];
						} else {
							tx = tx + ' ' + cardPrefix[ot] + handin.holeCards[i][k].capitalize() + cardPostfix[ot];
						}
					}
				}
			}
			tx = tx + ' ' + herotext + endStackLine[ot];
		}

		tx = tx + lineBreaks[ot];

		

		handin.potSize = cleanNum(handin.antesTotal);

		numPlayersLeft = handin.numPlayers;

		//actions by street    
		cardout = 0;
		for (x in handin.action_players) {

			dpDisco = 1
			//street name and street-specific stuff    
			tx = tx + streetNamePre[ot] + handin.streetName[x] + ':' + streetNamePost[ot];

			if ((handin.streetName[x] == 'Preflop') || (handin.streetName[x] == 'Dealing Hands')) {
				//preflop has special headings
				handin.potSize = cleanNum(handin.potSize) + cleanNum(handin.smallBlindPostedAmount) + cleanNum(handin.bigBlindPostedAmount);
				if (isLimitGame) {
					//for limit games convert pot size to SB
					potsizeinbets = handin.potSize/handin.smallBlind;
					tx = tx + ' (' + potsizeinbets.toFixed(numDigitsPot) + ' SB) ';
				} else {
					tx = tx + ' (' + chipPrefix + addCommas(handin.potSize.toFixed(numDigitsPot)) + ') ';
				}
				if (handin.hero) {
					if (handin.gameShort == 'DRAW') {
						for (countCard = 0; countCard < 5; countCard++) {
							tx = tx + ' ' +cardPrefix[ot] + handin.holeCards[findIndex(handin.players, handin.hero)][cardout] + cardPostfix[ot];
							cardout++
						}
					}
					else {
						//tx = tx + ' Hero is ' + handin.positions[handin.players.indexOf(handin.hero)];
						tx = tx + ' Hero is ' + handin.positions[findIndex(handin.players, handin.hero)];
						tx = tx + ' with';
						for (w in handin.holeCards) {
							for (v in handin.holeCards[w]) {
								;
								tx = tx + ' ' + cardPrefix[ot] + suitPre[handin.holeCards[w][v].substring(1)][ot] + handin.holeCards[w][v].capitalize() +suitPost[handin.holeCards[w][v].substring(1)][ot]+ cardPostfix[ot];
							}
						}
					}
				}
				tx = tx + playersLeftPre[ot]+ ' (' + numPlayersLeft + ' players)' + playersLeftPost[ot];

			} else {

				//for other streets we just print out name of street, pot size, cards, and number of players
				//for limit games, convert pot size to number of bets
				if (isLimitGame) {
					if (x<2) {
						potsizeinbets = handin.potSize/handin.smallBlind;
						bettext = "SB";
					} else {
						potsizeinbets = handin.potSize/handin.bigBlind;
						bettext = "BB";
					}
					
					tx = tx + ' (' + potsizeinbets.toFixed(numDigitsPot) + ' ' + bettext+ ') ';
				} else {
					tx = tx + ' (' + chipPrefix + addCommas(handin.potSize.toFixed(numDigitsPot)) + ') ';
				}
				
				for (y in handin.communityCards[x]) {

					tx = tx + ' ' + cardPrefix[ot] + suitPre[handin.communityCards[x][y].substring(1)][ot]+ handin.communityCards[x][y].capitalize()  + suitPost[handin.communityCards[x][y].substring(1)][ot] + cardPostfix[ot];

				}
				tx = tx + playersLeftPre[ot] + ' (' + numPlayersLeft + ' players)' + playersLeftPost[ot];
			}

			tx = tx + lineBreaks[ot];

			//action on this street
			numFolds = 0;
			foldsDone = 0;
			dpDiscoNum = 0;

			for (i in handin.action_players[x]) {

				if ((handin.action_players[x][i] == handin.hero) && (handin.action_types[x][i] == 'discards')) {
					dpDiscoNum = handin.action_values[x][i];
				}

				if ((handin.gameShort == 'DRAW') && (handin.hero) && (handin.action_types[x][i] != 'discards') && (handin.action_types[x][i] != 'stands') && (dpDisco == 1) && (x > 0)) {
					tx = tx + lineBreaks[ot];
					for (countCard = 0; countCard < 5; countCard++) {
						if ((dpDiscoNum > 0) && (countCard == (5 - dpDiscoNum))) {
							tx = tx + ' ||';
						}
						tx = tx + ' ' + cardPrefix[ot] + handin.holeCards[findIndex(handin.players, handin.hero)][cardout].capitalize() + cardPostfix[ot];
						cardout++
					}
					dpDisco = 0;
					tx = tx + lineBreaks[ot];
				}

				//the action
				if (handin.action_types[x][i] == 'raises' | handin.action_types[x][i] == 'bets') {
					
					actionPre = betActionPre[ot];
					actionPost = betActionPost[ot];
					
					if (isLimitGame) {
						//convert to 3bet and 4bet
						if (handin.action_types[x][i]=='raises') {
							raisecounter = 0;
							for (b = 0; b <= i; ++b) {
								if (handin.action_types[x][b] == 'raises' || handin.action_types[x][b] == '3-bets' || handin.action_types[x][b] == '4-bets'|| handin.action_types[x][b] == '5-bets') {++raisecounter;}
								
							}
							if (raisecounter==2) {handin.action_types[x][i] = '3-bets';}
							if (raisecounter==3) {handin.action_types[x][i] = '4-bets';}
							if (raisecounter==4) {handin.action_types[x][i] = '5-bets';}
							if (raisecounter==5) {handin.action_types[x][i] = '6-bets';}							
						}
					}
					
				} else if (handin.action_types[x][i] == 'folds') {
					//multiple consecutive folds will be collapsed
					numPlayersLeft = numPlayersLeft - 1;
					numFolds = numFolds + 1;
					actionColor = foldColor;
					stylestart = '[i]';
					styleend = '[/i]';
					if (handin.action_types[x][parseInt(i) + 1] == 'folds') {
						//if we are hero, it doesn't get collapsed
						if (handin.action_players[x][i] == handin.hero) {
							foldsDone = 1;
						} else {
							//there's another fold coming up    
							if (handin.action_players[x][parseInt(i) + 1] == handin.hero) {
								//but its hero, so we're done
								foldsDone = 1;
							} else {
								//its not hero, collapse this one in
								foldsDone = 0;
							}
						}
					} else {
						//no more folds, were done
						foldsDone = 1;
					}

				} else {
					actionPre = regActionPre[ot];
					actionPost = regActionPost[ot];
				}

				//the actor
				//actor = handin.positions[handin.players.indexOf(handin.action_players[x][i])];
				if (showNames) {
					actor = handin.action_players[x][i];
				} else {
					actor = handin.positions[findIndex(handin.players, handin.action_players[x][i])];
				}

				if (handin.action_players[x][i] == handin.hero) {
					actor = "Hero";
				}

				//print player and action
				//collapse folds
				if (handin.action_types[x][i] == 'folds') {
					if (foldsDone) {
						//print out folds
						if (numFolds == 1) {
							//just a single one
							tx = tx + foldsPre[ot] + actor + ' ' + handin.action_types[x][i];
							numFolds = 0;
						} else {
							//several
							tx = tx + foldsPre[ot]  + numFolds + ' folds';
							numFolds = 0;
						}
						tx = tx + foldsPost[ot];

						//if this is the last action we want a new line, otherwise a comma
						if (i < handin.action_players[x].length - 1 && handin.action_types[x][parseFloat(i) + 1] != 'collected') {
							tx = tx + ', ';
						} else if (handin.action_types[x][parseFloat(i) + 1] == 'collected') {
							tx = tx + lineBreaks[ot] + lineBreaks[ot];
							if (handin.site !='Holdem Manager') {skipshowdown = 1;}

						} else {
							tx = tx + lineBreaks[ot];
						}

					} else {
						//do nothing -- folds collapsed
					}
				} else {
					//nonfold action
					tx = tx + actionPre + actor + ' ' + handin.action_types[x][i];
					//the values
					if (handin.action_values[x][i]) {
						if (!isLimitGame) {
							//for limit games we dont print the values
							if (handin.action_types[x][i] == 'raises') {
								tx = tx + ' to ' + chipPrefix + handin.action_values[x][i];
	
							} else if (handin.action_types[x][i] == 'discards') {
								tx = tx + ' ' + handin.action_values[x][i];
							} else {
								tx = tx + ' ' + chipPrefix + handin.action_values[x][i];
							}
							
					   } else {
					   	  	//for limit games we do show values collected
					   	  	if (handin.action_types[x][i] == 'collected') {
					   	  		tx = tx + ' ' + chipPrefix + handin.action_values[x][i];
					   	  	}
					   
					   }
					}
					tx = tx + actionPost;

					//if this is the last action we want a new line, otherwise a comma
					if (i < handin.action_players[x].length - 1 && handin.action_types[x][parseInt(i) + 1] != 'collected') {
						tx = tx + ', ';
					} else if (handin.action_types[x][parseInt(i) + 1] == 'collected') {
						tx = tx + lineBreaks[ot] + lineBreaks[ot];
						if (handin.site !='Holdem Manager') {skipshowdown = 1;}

					} else {
						tx = tx + lineBreaks[ot];
					}

				}

			}

			tx = tx + lineBreaks[ot];

			//update pot size
			handin.potSize = cleanNum(handin.potSize) + cleanNum(handin.action_addedToPot[x]);
		}
		
		if (showResults == 2) {skipshowdown=1;}

		//showdown
		if (!skipshowdown) {
			
			if (showResults==1) {
				tx = tx + whiteResultsPre[ot];
				cardsPre = whiteCardsPre[ot];
				cardsPost = whiteCardsPost[ot];
			} else {
				cardsPre = cardPrefix[ot];
				cardsPost = cardPostfix[ot];
			}
			for (i in handin.showdown_players) {
				// convert player name to position/hero for showdown
				if (handin.showdown_players[i] == handin.hero) {
					showdownplayer = 'Hero';
				}
				else {
					if (showNames) {
						showdownplayer = handin.showdown_players[i];
					} else {
						showdownplayer = handin.positions[findIndex(handin.players, handin.showdown_players[i])];
					}
				}
				if (handin.showdown_cards[i]){
					if (handin.showdown_cards[i][0] == 'mucks') {
						tx = tx + showdownplayer + ' mucked' + lineBreaks[ot];
					} else {
						if (handin.showdown_types[i] == 'mucked') {
							typetext = "mucked";
						} else {
							typetext = "showed";
						}
						if (handin.showdown_types[i] != 'collected') {
							tx = tx + showdownplayer + ' ' + typetext;
							if (handin.showdown_cards[i][1]) {
								for (w in handin.showdown_cards[i]) {
									tx = tx + ' ' + cardsPre + suitPre[handin.showdown_cards[i][w].substring(1)][ot]+ handin.showdown_cards[i][w].capitalize()  + suitPost[handin.showdown_cards[i][w].substring(1)][ot] + cardsPost;
								}
							}
							if (handin.showdown_types[i] != "mucked") {
								tx = tx + ', ' + handin.showdown_hands[i];
							}
							tx = tx + lineBreaks[ot];
						}
					}
				}
				//}
			}
			//results
			for (i in handin.result_players) {
				//convert player name to position/hero for showdown
				if (handin.result_players[i] == handin.hero) {
					resultplayer = 'Hero';
				} else {
					if (showNames) {
						resultplayer = handin.result_players[i];
					} else {
						resultplayer = handin.positions[findIndex(handin.players, handin.result_players[i])];
					}

				}
				tx = tx + resultplayer + ' won ' + chipPrefix + handin.result_values[i] + lineBreaks[ot];
			}
			if (showResults==1) {
				tx = tx + whiteResultsPost[ot];
			}
		}
		if (handin.rake && handin.gameType == "C") {
			tx = tx + '(Rake: ' + chipPrefix + handin.rake + ')' + lineBreaks[ot];
		}

		if (handin.error) {
			tx = tx + '\n\n' + handin.error;
		}

	}

	return tx;

}




function getPositionNamesStud(handin) {
	//takes list of players and seats and figures out position labels
	handin.positions = new Array;
	for (x in handin.seatNumbers) {
		handin.positions[x] = "Seat " + handin.seatNumbers[x];
	}
	return handin;
}

function getPositionNames(handin) {

	//takes list of players and seats and figures out position labels
	//buttonIndex = handin.seatNumbers.indexOf(handin.button);
	buttonIndex = findIndex(handin.seatNumbers, handin.button)
	handin.positions = new Array;
	handin.positions[buttonIndex] = 'Button';
	maxIndex = handin.numPlayers - 1;

	if (handin.numPlayers == 2) {
		//heads up the guy not on button is BB
		bbIndex = buttonIndex + 1;
		if (bbIndex > maxIndex) {
			bbIndex = 0;
		}
		handin.positions[bbIndex] = 'BB';

	} else {

		sbIndex = buttonIndex + 1;
		if (sbIndex > maxIndex) {
			sbIndex = 0;
		}
		handin.positions[sbIndex] = 'SB';

		bbIndex = sbIndex + 1;
		if (bbIndex > maxIndex) {
			bbIndex = 0;
		}
		handin.positions[bbIndex] = 'BB';

		if (handin.numPlayers > 3) {

			utgIndex = bbIndex + 1;
			if (utgIndex > maxIndex) {
				utgIndex = 0;
			}
			handin.positions[utgIndex] = 'UTG';

			if (handin.numPlayers > 4) {

				coIndex = buttonIndex - 1;
				if (coIndex < 0) {
					coIndex = handin.numPlayers - 1;
				}
				handin.positions[coIndex] = "CO";

				if (handin.numPlayers > 5) {
					utg1Index = utgIndex + 1;
					if (utg1Index > maxIndex) {
						utg1Index = 0;
					}
					handin.positions[utg1Index] = "UTG+1";

					if (handin.numPlayers > 6) {
						hjIndex = coIndex - 1;
						if (hjIndex < 0) {
							hjIndex = maxIndex;
						}
						handin.positions[hjIndex] = "HJ";

						if (handin.numPlayers > 7) {
							mpIndex = utg1Index + 1;
							if (mpIndex > maxIndex) {
								mpIndex = 0;
							}
							handin.positions[mpIndex] = "MP";

							if (handin.numPlayers > 8) {
								mp2Index = mpIndex + 1;
								if (mp2Index > maxIndex) {
									mp2Index = 0;
								}
								handin.positions[mp2Index] = "MP2";

								if (handin.numPlayers > 9) {
									mp3Index = mp2Index + 1;
									if (mp3Index > maxIndex) {
										mp3Index = 0;
									}
									handin.positions[mp3Index] = "MP3";

									if (handin.numPlayers > 10) {

										handin.error = "WTF, more than 10 players?! I cannot handle this.";

									}
								}
							}
						}
					}
				}
			}
		}
	}

	return handin;

}

function getRandomTagLine() {

	//returns a random tagline from the list
	tagLines = ['Milked from the teat of a feral cow', 'Converted by a herd of feral cows', 'A pack of feral cows chewed their cuds for .0043 seconds to convert this hand', 'Moooooooooooraaawwwr.', 'Feral Cow Poker Hand Converter', 'Feral Cow Poker Hand Converter', 'Feral Cow Poker Hand Converter', 'Feral Cow Poker Hand Converter', 'Feral Cow Poker Hand Converter', 'Converting hands till the cows come home', 'Cows play poker with cow chips', 'Dont have a cow, heres your converted hand', 'This converter is going to be a cash cow...', 'Your converted hand, now with more cowbell.', 'Feral Cow Poker', 'Feral Cow Poker', 'Feral Cow Poker', 'once a cow has a taste for violence, it reverts. it becomes feral.', 'beware the feral cow packs. they hunger.', 'Converted by the cows of Feral Cow Poker', 'Feral Cow Converter: By old guys, for old guys'

	];

	rand_no = Math.floor(Math.random() * (tagLines.length - 1));
	theLine = tagLines[rand_no];

	return theLine;

}

function HEMParseAction (handin,text,street) {

		//this function parses the action lines on each street

		lines = text.split(/■/);
		
		handin.action_types[street] = new Array;
		handin.action_players[street] = new Array;
		handin.action_values[street] = new Array;
		handin.action_addedToPot[street] = new Array;
		handin.action_addedToPot[street] = 0;
		
		//loop through action lines
		playerCount = 0;
		currentMaxBet = 0;
		
		for(i = 0; i < lines.length; i = i + 1) {
			
			//skip the lines that have stuff we don't want to treat as action
			if (!lines[i].match(/Dealt to/) && !lines[i].match(/\*/) && !lines[i].match(/doesn\'t/)) { //'
				
				if (lines[i].match(/ wins/)) {
				
					//if there is an uncalled bet, subtract that amount from the pot
					regexstring = /(.*) wins [\$]?([\d|\.|\,]+)/;
					result = lines[i].match(regexstring);
					if (result) {
						uncalledAmount = result[2];
						uncalledPlayer = result[1];
										
						handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) - parseFloat(uncalledAmount);
					}
				} else {

					
					//get action names
					result=lines[i].match(/(.*) (?:folds|raises|calls|bets|checks)/);
					if (result) {handin.action_players[street][playerCount] = result[1];}
					
					//get action types
					result=lines[i].match(/((?:folds|raises|calls|bets|checks))/);
					if (result) {handin.action_types[street][playerCount] = result[1];}
					
					if (lines[i].match(/((?:folds|raises|calls|bets|checks))/)) {
						//get action values
						regexstring=/\[[\$]?([\d|\.|\,]+).*\]/;
						result=lines[i].match(regexstring);
						if (result) {
							handin.action_values[street][playerCount] = result[1];
							actionDigits = getPrecision(handin.action_values[street][playerCount]);	
						} else if (handin.action_types[street][playerCount] == 'discards') {
		                    // discards
		                    regexstring=/discards (\d+)/;
		                    result=lines[i].match(regexstring);
		                    if (result) {
		                        handin.action_values[street][playerCount] = result[1];
		                    }
	                	}   					
						//get $ added to pot
						if (handin.action_values[street][playerCount]){
							
							playerIndex = findIndex(handin.players,handin.action_players[street][playerCount]);					
							
							if (handin.action_types[street][playerCount] == 'raises'){
									
									//console.log('raise -- action value is %f\n',handin.action_values[street][playerCount]);
									//console.log ('  this player has already put in: %f\n',handin.action_playersPot[playerIndex]);
									newval = parseFloat(handin.action_values[street][playerCount]) + parseFloat(handin.action_playersPot[playerIndex]);
									handin.action_playersPot[playerIndex] = newval;
									//console.log ('  so now they have put in: %f\n',handin.action_playersPot[playerIndex]);
									//console.log ('  already added to pot on this street: %f\n',handin.action_addedToPot[street]);
									handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) + parseFloat(handin.action_values[street][playerCount]);
									//console.log('  we add %f to the pot so now pot is getting %f from this street\n',handin.action_values[street][playerCount],handin.action_addedToPot[street]);
									handin.action_values[street][playerCount] = newval.toFixed(actionDigits);
								
								
							
							} else {
								//for bets and calls just add the amount bet or called
								newval = parseFloat(handin.action_playersPot[playerIndex]) + parseFloat(handin.action_values[street][playerCount]);
								handin.action_playersPot[playerIndex] = newval;
								handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) + parseFloat(handin.action_values[street][playerCount]);
								//console.log('call - adding %f to pot, now %f added to pot on this street for total of %f\n',newval,handin.action_values[street][playerCount],handin.action_addedToPot[street]);
								
								
							}
						
						}
					}
					//deal with action ending and someone collecting
					if (lines[i].match(/ wins/)) {
						result = lines[i].match(/(.+) wins/);
						if (result) {handin.action_players[street][playerCount] = result[1];}
						
						handin.action_types[street][playerCount] = 'collected';
						
						regexstring = /wins [\$]?([\d|\.|\,]+)/;
							
						result=lines[i].match(regexstring);
						if (result) {handin.action_values[street][playerCount] = result[1];}
					}
					
					playerCount = playerCount + 1;
				}
				
				
				
			}
		
		}

		return handin;
}


function pokerStarsParseAction (handin,text,street) {

		//this function parses the action lines on each street

		lines = text.split(/■/);
		
		handin.action_types[street] = new Array;
		handin.action_players[street] = new Array;
		handin.action_values[street] = new Array;
		handin.action_addedToPot[street] = new Array;
		handin.action_addedToPot[street] = 0;
		
		//loop through action lines
		playerCount = 0;
		for(i = 0; i < lines.length; i = i + 1) {
			
			//skip the lines that have stuff we don't want to treat as action
			if (!lines[i].match(/Dealt to/) && !lines[i].match(/\*/) && !lines[i].match(/doesn\'t/)) { //'
				
				if (lines[i].match(/Uncalled bet/)) {
				
					//if there is an uncalled bet, subtract that amount from the pot
					if (handin.gameType == "C") {regexstring = /Uncalled bet \(\$(\S+)\) returned to (.*)/;}
					else {regexstring = /Uncalled bet \((\S+)\) returned to (.*)/;}
					result = lines[i].match(regexstring);
					if (result) {
						uncalledAmount = result[1];
						uncalledPlayer = result[2];
										
						handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) - parseFloat(uncalledAmount);
					}
				} else {

				
					//get action names
					result=lines[i].match(/(.*)\: /);
					if (result) {handin.action_players[street][playerCount] = result[1];}
					
					//get action types
					result=lines[i].match(/\: (\S*)/);
					if (result) {handin.action_types[street][playerCount] = result[1];}
					
					//get action values
					regexstring = /(?:checks|raises|bets|folds|calls) [\$]?(.+)/;
					result=lines[i].match(regexstring);
					if (result) {handin.action_values[street][playerCount] = result[1];
					
					} else if (handin.action_types[street][playerCount] == 'discards') {
	                    // discards
	                    regexstring=/discards (\d+)/;
	                    result=lines[i].match(regexstring);
	                    if (result) {
	                        handin.action_values[street][playerCount] = result[1];
	                    }
                	}   					
					//get $ added to pot
					if (handin.action_values[street][playerCount]){
						
						//playerIndex = handin.players.indexOf(handin.action_players[street][playerCount]);
						playerIndex = findIndex(handin.players,handin.action_players[street][playerCount]);					
						
						if (handin.action_types[street][playerCount] == 'raises'){
							//for raises, we have to subtract amount already bet by the same player
							regexstring = /to [\$]?([\d|,|\.]+)/;
							result=handin.action_values[street][playerCount].match(regexstring);
							if (result) {newval = parseFloat(result[1]) - parseFloat(handin.action_playersPot[playerIndex]);
								handin.action_playersPot[playerIndex] = newval;
								handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) + parseFloat(newval);
								//take of beginning for formatting
								result = handin.action_values[street][playerCount].match(/to [\$]?(.*)/);
								if (result) {handin.action_values[street][playerCount] = result[1];}
							 }
						
						} else {
							//for bets and calls just add the amount bet or called
							regexstring = /[\$]?([\d|,|\.]+)/;
							result=handin.action_values[street][playerCount].match(regexstring);
							if (result) {
								newval = parseFloat(handin.action_playersPot[playerIndex]) + parseFloat(result[1]);
								handin.action_playersPot[playerIndex] = newval;
								handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) + parseFloat(result[1]);
							}
							
							
						}
					
					}
					//deal with action ending and someone collecting
					if (lines[i].match(/collected/)) {
						result = lines[i].match(/(.+) collected/);
						if (result) {handin.action_players[street][playerCount] = result[1];}
						handin.action_types[street][playerCount] = 'collected';
						
						regexstring = /collected [\$]?([\d|,|\.]+) from/;
						result=lines[i].match(regexstring);
						if (result) {handin.action_values[street][playerCount] = result[1];}
						
					}
					
					playerCount = playerCount + 1;
				}
				
				
				
			}
		
		}

		return handin;
}

function pokerStarsParseActionBACKUP(handin, text, street) {

	//this function parses the action lines on each street
	lines = text.split(/■/);

	handin.action_types[street] = new Array;
	handin.action_players[street] = new Array;
	handin.action_values[street] = new Array;
	handin.action_addedToPot[street] = new Array;
	handin.action_addedToPot[street] = 0;

	//loop through action lines
	playerCount = 0;
	for (i = 0; i < lines.length; i = i + 1) {

		//skip the lines that have stuff we don't want to treat as action
		if (!lines[i].match(/Dealt to/) && !lines[i].match(/\*/) && !lines[i].match(/doesn\'t/)) { //'
			if (lines[i].match(/Uncalled bet/)) {

				//if there is an uncalled bet, subtract that amount from the pot
				if (handin.gameType == "C") {
					regexstring = /Uncalled bet \[\$]?([\d|,|\.]+)\) returned to (.*)/;
				}
				else {
					regexstring = /Uncalled bet \([\$]?([\d|,|\.]+)\) returned to (.*)/;
				}
				result = lines[i].match(regexstring);
				if (result) {
					uncalledAmount = result[1];
					uncalledPlayer = result[2];

					handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) - parseFloat(uncalledAmount);
				}
			} else {

				//get action names
				result = lines[i].match(/(.*)\: /);
				if (result) {
					handin.action_players[street][playerCount] = result[1];
				}

				//get action types
				result = lines[i].match(/\: (\S*)/);
				if (result) {
					handin.action_types[street][playerCount] = result[1];
				}

				//get action values
				regexstring = /[\$]?([\d|,|\.]+)/;
				result = lines[i].match(regexstring);
				if (result) {
					handin.action_values[street][playerCount] = result[1];

				} else if (handin.action_types[street][playerCount] == 'discards') {
					// discards
					regexstring = /discards (\d+)/;
					result = lines[i].match(regexstring);
					if (result) {
						handin.action_values[street][playerCount] = result[1];
					}
				}
				//get $ added to pot
				if (handin.action_values[street][playerCount]) {

					//playerIndex = handin.players.indexOf(handin.action_players[street][playerCount]);
					playerIndex = findIndex(handin.players, handin.action_players[street][playerCount]);

					if (handin.action_types[street][playerCount] == 'raises') {
						//for raises, we have to subtract amount already bet by the same player
						regexstring = /to [\$]?([\d|,|\.]+)/;
						result = handin.action_values[street][playerCount].match(regexstring);
						if (result) {
							newval = parseFloat(result[1]) - parseFloat(handin.action_playersPot[playerIndex]);
							handin.action_playersPot[playerIndex] = newval;
							handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) + parseFloat(newval);
						}

					} else {
						//for bets and calls just add the amount bet or called
						regexstring = /[\$]?([\d|,|\.]+)/;
						result = handin.action_values[street][playerCount].match(regexstring);
						if (result) {
							newval = parseFloat(handin.action_playersPot[playerIndex]) + parseFloat(result[1]);
							handin.action_playersPot[playerIndex] = newval;
							handin.action_addedToPot[street] = parseFloat(handin.action_addedToPot[street]) + parseFloat(result[1]);
						}

					}

				}
				//deal with action ending and someone collecting
				if (lines[i].match(/collected/)) {
					result = lines[i].match(/(.+) collected/);
					if (result) {
						handin.action_players[street][playerCount] = result[1];
					}

					handin.action_types[street][playerCount] = 'collected';

					regexstring = /collected [\$]?([\d|,|\.]+) from pot/;
					result = lines[i].match(regexstring);
					if (result) {
						handin.action_values[street][playerCount] = result[1];
					}
				}

				playerCount = playerCount + 1;
			}

		}

	}

	return handin;
}

function ftpParseAction(handin, text, street) {

	//this function parses the action lines on each street
	lines = text.split(/■/);

	handin.action_types[street] = new Array;
	handin.action_players[street] = new Array;
	handin.action_values[street] = new Array;
	handin.action_addedToPot[street] = new Array;
	handin.action_addedToPot[street] = 0;

	//loop through action lines
	playerCount = 0;
	for (i = 0; i < lines.length; i = i + 1) {

		//skip the lines that have stuff we don't want to treat as action			
		if (!lines[i].match(/(?:Dealt to|\*|doesn\'t|\[|blinds|\:|mucks|sitting out|adds|disconnected|reconnected|seconds|stands up|has returned)/)) { //'
			if (lines[i].match(/Uncalled bet/)) {
								
				//console.log('UNCALLED BET\n');
				//if there is an uncalled bet, subtract that amount from the pot
				regexstring = /Uncalled bet of [?:\$]([\d|,|\.]+) returned to (.*)/;
				
				result = lines[i].match(regexstring);
				if (result) {
					//console.log('got match');
					uncalledAmount = result[1];
					uncalledPlayer = result[2];
					handin.action_addedToPot[street] = cleanNum(handin.action_addedToPot[street]) - cleanNum(uncalledAmount);
						
				}
			} else {

				//get action names
				result = lines[i].match(/(.*?) (checks|raises|bets|folds|calls)/);
				if (result) {
					handin.action_players[street][playerCount] = result[1];
				}

				//get action types
				result = lines[i].match(/ (checks|raises|bets|folds|calls)/);
				if (result) {
					handin.action_types[street][playerCount] = result[1];
				}

				//get action values
				regexstring = /(?:checks|raises|bets|folds|calls) [\$]?(.+)/;
				//	else {regexstring=/ (?:checks|raises to|bets|folds|calls) (.+)/;}
				result = lines[i].match(regexstring);
				if (result) {
					handin.action_values[street][playerCount] = result[1];
				}

				
				//adjust for lhe
				if (handin.gameShort == "LHE") {
					if (handin.action_types[street][playerCount] == "raises") {
						handin.action_values[street][playerCount] = "to " + handin.action_values[street][playerCount];
					}
				}

				//get $ added to pot
				if (handin.action_values[street][playerCount]) {

					//playerIndex = handin.players.indexOf(handin.action_players[street][playerCount]);
					playerIndex = findIndex(handin.players, handin.action_players[street][playerCount]);

					if (handin.action_types[street][playerCount] == 'raises') {
						//for raises, we have to subtract amount already bet by the same player
						
						result = handin.action_values[street][playerCount].match(/to [\$]?([\d|,|\.]+)/);
						if (result) {
							newval = cleanNum(result[1]) - cleanNum(handin.action_playersPot[playerIndex]);
							handin.action_playersPot[playerIndex] = newval;
							handin.action_addedToPot[street] = cleanNum(handin.action_addedToPot[street]) + cleanNum(newval);
							result = handin.action_values[street][playerCount].match(/to [\$]?(.*)/);
							if (result) {handin.action_values[street][playerCount] = result[1];}
						}

					} else {
						//for bets and calls just add the amount bet or called
						regexstring = /([\d|,|\.]+)/;
						
						result = handin.action_values[street][playerCount].match(regexstring);
						if (result) {
							newval = cleanNum(handin.action_playersPot[playerIndex]) + cleanNum(result[1]);
							handin.action_playersPot[playerIndex] = newval;
							handin.action_addedToPot[street] = cleanNum(handin.action_addedToPot[street]) + cleanNum(result[1]);
						}

					}

				}
				//deal with action ending and someone collecting
				if (lines[i].match(/ wins/)) {
					/*
result = lines[i].match(/(.+) wins/);
						if (result) {handin.action_players[street][playerCount] = result[1];}
						
						handin.action_types[street][playerCount] = 'collected';
						
						if (handin.gameType == "C") {regexstring = /wins the pot \((\$.+)\)/;}
							else {regexstring=/wins the pot \((.+)\)/;}
						result=lines[i].match(regexstring);
						if (result) {handin.action_values[street][playerCount] = result[1];}
*/

				}

				playerCount = playerCount + 1;
			}

		}

	}

	return handin;
}

function cereusParseAction(handin, text, street) {

	//this function parses the action lines on each street
	lines = text.split(/■/);

	handin.action_types[street] = new Array;
	handin.action_players[street] = new Array;
	handin.action_values[street] = new Array;
	handin.action_addedToPot[street] = new Array;
	handin.action_addedToPot[street] = 0;

	//loop through action lines
	playerCount = 0;
	for (i = 0; i < lines.length; i = i + 1) {

		//skip the lines that have stuff we don't want to treat as action			
		if (!lines[i].match(/(?:Dealt to|\*|doesn\'t|\[|blinds|\:|mucks|sitting out|adds)/)) { //'
			if (lines[i].match(/Uncalled bet/)) {

				//if there is an uncalled bet, subtract that amount from the pot
				if (handin.gameType == "C") {
					//regexstring = /Uncalled bet \(\$(\S+)\) returned to (.*)/;
					regexstring = /(.*) \- returned \(\$(\S+)\) \: not called/;
				}
				else {
					regexstring = /(.*) \- returned \((\S+)\) \: not called/;
				}
				result = lines[i].match(regexstring);
				if (result) {
					uncalledAmount = result[2];
					uncalledPlayer = result[1];
					handin.action_addedToPot[street] = cleanNum(handin.action_addedToPot[street]) - cleanNum(uncalledAmount);
				}
			} else {

				//get action names
				result = lines[i].match(/(.*?) \- (Checks|Raises|Bets|Folds|Calls|All\-In)/);
				if (result) {
					handin.action_players[street][playerCount] = result[1];
				}

				//get action types
				result = lines[i].match(/\- (Checks|Raises|Bets|Folds|Calls|All\-In)/);
				if (result) {
					handin.action_types[street][playerCount] = result[1].toLowerCase();
				}

				//get action values
				if (handin.gameType == "C") {
					regexstring = /\$(.*)/;
				}
				else {
					regexstring = / (?:Checks|Raises|Bets|Folds|Calls|All\-In).*? (.+)/;
				}
				result = lines[i].match(regexstring);
				if (result) {
					handin.action_values[street][playerCount] = result[1];
				}

				//deal with cereus all-in nonsense
				if (handin.action_types[street][playerCount] == 'all-in') {
										
					if (playerCount > 0) {
						
						prevValue = handin.action_values[street][playerCount-1];
						currentValue = handin.action_values[street][playerCount];
						
						
						
						if (prevValue) {
					
							
							if (cleanNum(prevValue) < cleanNum(currentValue)) {
								handin.action_types[street][playerCount] = 'raises';
								handin.action_values[street][playerCount] = handin.action_values[street][playerCount] + ' and is all-in';
							} else {
								handin.action_types[street][playerCount] = 'calls';
								handin.action_values[street][playerCount] = handin.action_values[street][playerCount] + ' and is all-in';
							
							}
						} else {
							
							handin.action_types[street][playerCount] = 'bets';
							handin.action_values[street][playerCount] = handin.action_values[street][playerCount] + ' and is all-in';

						}
					} else {
						
						handin.action_types[street][playerCount] = 'bets';
						handin.action_values[street][playerCount] = handin.action_values[street][playerCount] + ' and is all-in';
					}
				
				}
			
				//get $ added to pot
				if (handin.action_values[street][playerCount]) {

					//playerIndex = handin.players.indexOf(handin.action_players[street][playerCount]);
					playerIndex = findIndex(handin.players, handin.action_players[street][playerCount]);

					if (handin.action_types[street][playerCount] == 'raises') {
						
						//for raises, we have to subtract amount already bet by the same player
						if (handin.gameType == "C") {
							regexstring = /to \$(.+)/;
						}
						else {
							regexstring = /to (\d+.*)/;
						}
						//console.log('raise: \n scanning %s',handin.action_values[street][playerCount]);
						result = handin.action_values[street][playerCount].match(regexstring);
						if (result) {
							newval = cleanNum(result[1]) - cleanNum(handin.action_playersPot[playerIndex]);
							handin.action_values[street][playerCount] = result[1];
							handin.action_playersPot[playerIndex] = newval;
							handin.action_addedToPot[street] = cleanNum(handin.action_addedToPot[street]) + cleanNum(newval);
							//console.log('raise - adding in %f, now adding %f for this street\n',newval,handin.action_addedToPot[street]);
						}

					} else {
						//for bets and calls just add the amount bet or called	
						newval = cleanNum(handin.action_playersPot[playerIndex]) + cleanNum(handin.action_values[street][playerCount]);
						handin.action_playersPot[playerIndex] = newval;
						handin.action_addedToPot[street] = cleanNum(handin.action_addedToPot[street]) + cleanNum(handin.action_values[street][playerCount]);
						//console.log('call - adding in %f, now adding %f for this street\n',handin.action_values[street][playerCount],handin.action_addedToPot[street]);

					}

				}
				//deal with action ending and someone collecting
				if (lines[i].match(/wins/)) {
					/*
result = lines[i].match(/(.+) wins/);
						if (result) {handin.action_players[street][playerCount] = result[1];}
						
						handin.action_types[street][playerCount] = 'collected';
						
						if (handin.gameType == "C") {regexstring = /wins the pot \((\$.+)\)/;}
							else {regexstring=/wins the pot \((.+)\)/;}
						result=lines[i].match(regexstring);
						if (result) {handin.action_values[street][playerCount] = result[1];}
*/

				}

				playerCount = playerCount + 1;
			}

		}

	}

	return handin;
}

function cleanNum(num) {

	if (num) {
		num = '' + num;
		num = num.replace(/\,/g, "");
		num = parseFloat(num);
	}
	return num;

}

function findIndex(theArray, theTarget) {

	targetIndex = -1;

	for (xx = 0; xx < theArray.length; xx++) {
		if (theArray[xx] == theTarget) {
			targetIndex = xx;
		}
	}

	
	return targetIndex;
}

function escapeText(str) {

	return (str + '').replace(/([\\"'\(\)])/g, "\\$1").replace(/\0/g, "\\0");
}

function addCommas(nStr)
{
	nStr += '';
	u = nStr.split('.');
	x1 = u[0];
	x2 = u.length > 1 ? '.' + u[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
	return x1 + x2;
}

function getPrecision(num) {

	numString = num.toString();
	
	result = numString.match(/\.(.*)/);
	
	if (result) {
		digs = result[1];
		numDigs = digs.length;
	} else {
		numDigs = 0;
	}
	
	return numDigs;
}