//Note that lines is only passed for efficiency, it could be obtained by just splitting handText private PokerHand parseHand(List<string> lines, string handText) { PokerHand hand = new PokerHand(); #region setup variables int start; int end; int curLine; char currencySymbol; List<Round> rounds = new List<Round>(); #endregion // Edited #region Make sure it's a PokerStars hand if (!handText.StartsWith("PokerStars")) throw new InvalidHandFormatException(handText); #endregion #region Skip partial hands if(lines[0].EndsWith("(partial)")) return null; #endregion // Edited hand.Context.Online = true; hand.Context.Site = "PokerStars"; #if DEBUG Console.WriteLine("Hand Number"); #endif // Edited #region Get the hand number start = handText.IndexOf('#') + 1; end = handText.IndexOf(':'); hand.Context.ID = handText.Substring(start, end - start); //Console.WriteLine("ID: {0}", hand.Context.ID); if (printed < 2) { Console.WriteLine("Hand Text: {0}", handText); printed++; } #endregion #if DEBUG Console.WriteLine("Table Name"); #endif // Edited #region Get the table name start = lines[1].IndexOf('\''); end = lines[1].IndexOf('\'', 7); hand.Context.Table = (lines[1].Substring(start + 1, end - start - 1)); #endregion #if DEBUG Console.WriteLine("Blinds"); #endif // Edited #region Get the blinds, antes and currency start = handText.IndexOf('('); end = handText.IndexOf('/'); string smallBlind = handText.Substring(start + 1, end - start - 1); start = end; end = handText.IndexOf(' ', start); string bigBlind = handText.Substring(start + 1, end - start - 1); if (smallBlind[0].Equals('$') || smallBlind[0].Equals('€')) { if (smallBlind[0].Equals('$')) { hand.Context.Currency = "USD"; currencySymbol = '$'; } else { hand.Context.Currency = "EUR"; currencySymbol = '€'; } hand.Context.SmallBlind = Decimal.Parse(smallBlind.Substring(1).Trim()); hand.Context.BigBlind = Decimal.Parse(bigBlind.Substring(1).Trim()); } else { currencySymbol = 'T'; hand.Context.SmallBlind = Decimal.Parse(smallBlind.Trim()); hand.Context.BigBlind = Decimal.Parse(bigBlind.Substring(0,bigBlind.Length-1).Trim()); } // Antes are not written on the first line in PokerStars hand histories // Ante amount will have to be extracted from post blind lines. // Smallest possible post blind line index is 4 curLine = 4; while(!lines[curLine].Equals("*** HOLE CARDS ***")) { if (lines[curLine].Contains(" posts the ante ")) { start = lines[curLine].IndexOf("ante"); string anteText = lines[curLine].Substring(start+5); if (anteText[0].Equals(currencySymbol)) anteText = anteText.Substring(1); hand.Context.Ante = Decimal.Parse(anteText.Trim()); break; } curLine++; } #endregion #if DEBUG Console.WriteLine("Game Format"); #endif #region Get the game format // Stars does not have different notations for Sit&Go's and MTTs. // All tournament hand histories are of the same format. if (currencySymbol.Equals('T')) { if (lines[0].Contains(": Tournament #")) hand.Context.Format = GameFormat.Tournament; else hand.Context.Format = GameFormat.PlayMoney; } else hand.Context.Format = GameFormat.CashGame; #endregion #if DEBUG Console.WriteLine("Poker Variant and Betting Type"); #endif #region Get the betting type and poker variant if(hand.Context.Format==GameFormat.CashGame && handText.Contains(" Cap - ")) { start = handText.IndexOf(" - ")+3; end = handText.IndexOf(" Cap "); string capAmountText = handText.Substring(start, end - start); hand.Context.CapAmount = Decimal.Parse(capAmountText.Substring(1).Trim()); hand.Context.CapAmountSpecified = true; hand.Context.Capped = true; } else { hand.Context.CapAmountSpecified = false; hand.Context.Capped = false; } string typeAndVariant; if (hand.Context.Format == GameFormat.CashGame) { start = handText.IndexOf(": ") + 3; end = handText.IndexOf(" (", start); typeAndVariant = handText.Substring(start, end - start); } else { start = handText.IndexOf(hand.Context.Currency) + 4; end = handText.IndexOf(" - ", start); typeAndVariant = handText.Substring(start, end - start); } if(typeAndVariant.Contains("Pot Limit")) hand.Context.BettingType = BettingType.PotLimit; else if(typeAndVariant.Contains("No Limit")) hand.Context.BettingType = BettingType.NoLimit; else hand.Context.BettingType = BettingType.FixedLimit; if (typeAndVariant.Contains("Hold'em")) hand.Context.PokerVariant = PokerVariant.TexasHoldEm; else if(typeAndVariant.Contains("Omaha Hi")) hand.Context.PokerVariant = PokerVariant.OmahaHi; else hand.Context.PokerVariant = PokerVariant.OmahaHiLo; #endregion #if DEBUG Console.WriteLine("Time Stamp"); #endif #region Get the date and time start = lines[0].LastIndexOf(" - ") + 3; end = lines[0].IndexOf(' ', start); string dateText = lines[0].Substring(start, end-start); string[] dateTokens = dateText.Split('/'); int year = Int32.Parse(dateTokens[0]); int month = Int32.Parse(dateTokens[1]); int day = Int32.Parse(dateTokens[2]); start = end; end = lines[0].IndexOf(' ', start + 1); string timeText = lines[0].Substring(start, end-start); string[] timeTokens = timeText.Split(':'); int hour = Int32.Parse(timeTokens[0]); int minute = Int32.Parse(timeTokens[1]); int second = Int32.Parse(timeTokens[2]); hand.Context.TimeStamp = new DateTime(year, month, day, hour, minute, second); #endregion #if DEBUG Console.WriteLine("Players"); #endif #region Create the players List<Player> players = new List<Player>(); curLine = 2; for (Match m = stacksExp.Match(lines[curLine]); m.Success; m = stacksExp.Match(lines[curLine])) { if (m.Success) { GroupCollection gc = m.Groups; Player p = new Player(); p.Seat = Int32.Parse(gc[1].Value); p.Name = gc[2].Value; p.Stack = Decimal.Parse(gc[4].Value); players.Add(p); curLine++; } } hand.Players = players.ToArray(); #endregion #if DEBUG Console.WriteLine("Blinds and Antes Posted"); #endif #region Terminate parsing of unsupported poker type if ((!typeAndVariant.Contains("Hold'em") && (!typeAndVariant.Contains("Omaha")))) { return hand; } #endregion #region Get the blinds and antes posted List<Blind> blinds = new List<Blind>(); for (; !lines[curLine].StartsWith("*** HOLE CARDS ***"); curLine++) { for (Match m = actionExp.Match(lines[curLine]); m.Success; m = m.NextMatch()) { GroupCollection gc = m.Groups; Blind blind = new Blind(); blind.Player = gc[1].Value; String a = gc[2].Value + "" + gc[3].Value + "" + gc[4].Value + "" + gc[5].Value + "" + gc[6].Value + "" + gc[7].Value + "" + gc[8].Value + "" + gc[9].Value + "" + gc[10].Value + "" + gc[11].Value + "" + gc[12].Value; if (gc[2].Value.Contains("ante")) blind.Type = BlindType.Ante; else if (gc[2].Value.Contains("small")) blind.Type = BlindType.SmallBlind; else if (gc[2].Value.Contains("big")) blind.Type = BlindType.BigBlind; else throw new Exception("Unknown blind type: " + lines[curLine]); if (lines[curLine].Contains("dead")) { for (int i = 0; i < gc.Count; i++) Console.WriteLine("{0}: \"{1}\"", i, gc[i].Value); Console.WriteLine("Found as {0}", blind.Type.ToString()); } blind.Amount = Decimal.Parse(gc[4].Value); blind.AllIn = !gc[12].Value.Equals(""); blinds.Add(blind); } } hand.Blinds = blinds.ToArray(); #endregion #if DEBUG Console.WriteLine("Button"); #endif #region Get the button string buttonText = lines[1].Substring(lines[1].IndexOf('#') + 1,1); hand.Context.Button = Int32.Parse(buttonText); curLine++; #endregion #if DEBUG Console.WriteLine("Hole Cards and Hero"); #endif #region Get the hole cards and the name of the hero int tempIndex = curLine; bool heroType = true; while (!lines[curLine].StartsWith("Dealt to ")) { if (lines[curLine].Equals("*** FLOP ***") || lines[curLine].Equals("*** SUMMARY ***")) { curLine = tempIndex; heroType = false; break; } else curLine++; } if(heroType) { start = "Dealt to ".Length; end = lines[curLine].IndexOf(" [", start); hand.Hero = lines[curLine].Substring(start, end - start); start = end + 2; List<Card> holecards = new List<Card>(); holecards.Add(new Card(lines[curLine].Substring(start, 2))); holecards.Add(new Card(lines[curLine].Substring(start + 3, 2))); if (hand.Context.PokerVariant != PokerVariant.TexasHoldEm) { holecards.Add(new Card(lines[curLine].Substring(start + 6, 2))); holecards.Add(new Card(lines[curLine].Substring(start + 9, 2))); } hand.HoleCards = holecards.ToArray(); curLine++; } #endregion #if DEBUG Console.WriteLine("Preflop Actions"); #endif #region Preflop Actions rounds.Add(new Round()); rounds[0].Actions = getRoundActions(lines, ref curLine); #endregion #if DEBUG Console.WriteLine("Flop Actions"); #endif #region Flop Actions and Community Cards if (lines[curLine].StartsWith("*** FLOP ***")) { rounds.Add(new Round()); start = lines[curLine].IndexOf('[') + 1; Card[] flop = new Card[3]; flop[0] = new Card(lines[curLine].Substring(start, 2)); flop[1] = new Card(lines[curLine].Substring(start + 3, 2)); flop[2] = new Card(lines[curLine].Substring(start + 6, 2)); rounds[1].CommunityCards = flop; curLine++; rounds[1].Actions = getRoundActions(lines, ref curLine); } #endregion #if DEBUG Console.WriteLine("Turn Actions"); #endif #region Turn Actions and Community Card if (lines[curLine].StartsWith("*** TURN ***")) { rounds.Add(new Round()); start = lines[curLine].LastIndexOf('[') + 1; Card[] turn = new Card[1]; turn[0] = new Card(lines[curLine].Substring(start, 2)); rounds[2].CommunityCards = turn; curLine++; rounds[2].Actions = getRoundActions(lines, ref curLine); } #endregion #if DEBUG Console.WriteLine("River Actions"); #endif #region River Actions and Community Card if (lines[curLine].StartsWith("*** RIVER ***")) { rounds.Add(new Round()); start = lines[curLine].LastIndexOf('[') + 1; Card[] river = new Card[1]; river[0] = new Card(lines[curLine].Substring(start, 2)); rounds[3].CommunityCards = river; curLine++; rounds[3].Actions = getRoundActions(lines, ref curLine); } #endregion #region Set rounds hand.Rounds = rounds.ToArray(); #endregion #if DEBUG Console.WriteLine("Results"); #endif #region Get pots won List<HandResult> results = new List<HandResult>(); List<List<Pot>> pots = new List<List<Pot>>(); for (; !lines[curLine].StartsWith("*** SUMMARY"); curLine++) { Match m = potsExp.Match(lines[curLine]); if (m.Success) { GroupCollection gc = m.Groups; Pot p = new Pot(); p.Amount = Decimal.Parse(gc[3].Value); if (gc[7].Value.Length > 0) p.Number = Int32.Parse(gc[7].Value.Substring(1)); else if ((gc[5].Value.Length == 0 && gc[3].Value == "the pot") || gc[5].Value == "main ") p.Number = 0; else if (gc[5].Length > 0) p.Number = 1; HandResult result = null; List<Pot> potList = null; for (int i = 0; i < results.Count; i++) { if (results[i].Player == gc[1].Value) { result = results[i]; potList = pots[i]; break; } } if (result == null) { result = new HandResult(gc[1].Value); potList = new List<Pot>(); results.Add(result); pots.Add(potList); } potList.Add(p); } } //add the pots to the model for (int i = 0; i < results.Count; i++) { results[i].WonPots = pots[i].ToArray(); } //get the rake, if any if (hand.Context.Format == GameFormat.CashGame) { for (; !lines[curLine].StartsWith("Total pot") || lines[curLine].Contains(":") || !lines[curLine].Contains("| Rake "); curLine++) { } int rakeStart = lines[curLine].LastIndexOf("| Rake ") + "| Rake ".Length; string rakeText = lines[curLine].Substring(rakeStart).Replace(currencySymbol+"", ""); hand.Rake = Decimal.Parse(rakeText.Trim()); } #endregion #if DEBUG Console.WriteLine("Shown Hands"); #endif #region Get the shown down hands for (; curLine < lines.Count; curLine++) { Match m = shownHandsExp.Match(lines[curLine]); if (m.Success) { GroupCollection gc = m.Groups; List<Card> shownCards = new List<Card>(); shownCards.Add(new Card(gc[5].Value)); shownCards.Add(new Card(gc[6].Value)); if (hand.Context.PokerVariant != PokerVariant.TexasHoldEm) { shownCards.Add(new Card(gc[8].Value)); shownCards.Add(new Card(gc[9].Value)); } string player = gc[2].Value; HandResult hr = null; foreach (HandResult curResult in results) if (curResult.Player == player) { hr = curResult; break; } if (hr == null) { hr = new HandResult(player); results.Add(hr); } hr.HoleCards = shownCards.ToArray(); } } #endregion #region Set the results hand.Results = results.ToArray(); #endregion #if DEBUG Console.WriteLine("Done"); #endif return hand; }
/// <summary> /// Creates a list of the hand's players ordered by their seat relative to the button. /// 0 = immediately after the button /// N = button, where N is the number of players /// </summary> public static IEnumerable<Player> ButtonRelativeSeats(this PokerHand hand) { Player[] players = new Player[hand.Players.Length]; int maxSeat = hand.Players.Max(p => p.Seat); int minSeat = hand.Players.Min(p => p.Seat); for (int i = hand.Context.Button == maxSeat ? minSeat : hand.Context.Button + 1, relIdx = 0; relIdx < players.Length;) { var player = hand.Players.FirstOrDefault(p => p.Seat == i); if (player != null) players[relIdx++] = player; i++; if (i > maxSeat) i = minSeat; } return players; }
//Note that lines is only passed for efficiency, it could be obtained //by just splitting handText private PokerHand parseHand(List<string> lines, string handText) { PokerHand hand = new PokerHand(); #region setup variables int start; int end; int curLine; List<Round> rounds = new List<Round>(); #endregion #region Make sure it's a Full Tilt hand if (!handText.StartsWith("Full Tilt Poker")) throw new InvalidHandFormatException(handText); #endregion #region Skip partial hands if(lines[0].EndsWith("(partial)")) return null; #endregion hand.Context.Online = true; hand.Context.Site = "Full Tilt Poker"; #if DEBUG Console.WriteLine("Hand Number"); #endif #region Get the hand number start = handText.IndexOf('#') + 1; end = handText.IndexOf(':'); hand.Context.ID = handText.Substring(start, end - start); //Console.WriteLine("ID: {0}", hand.Context.ID); if (printed < 2) { Console.WriteLine("Hand Text: {0}", handText); printed++; } #endregion #if DEBUG Console.WriteLine("Table Name"); #endif #region Get the table name start = end + 2; end = handText.IndexOf('-', start); hand.Context.Table = handText.Substring(start, end - start - 1); #endregion #if DEBUG Console.WriteLine("Blinds"); #endif #region Get the blinds and game format start = end + 2; end = handText.IndexOf('-', start); string blindsAndAntes = handText.Substring(start, end - start); int blindSeparator = blindsAndAntes.IndexOf('/'); string smallBlindText = blindsAndAntes.Substring(0, blindSeparator); if (smallBlindText[0] == '$') smallBlindText = smallBlindText.Substring(1); hand.Context.SmallBlind = Decimal.Parse(smallBlindText.Trim()); int bigBlindStart = blindSeparator + 1; int bigBlindEnd = blindsAndAntes.IndexOf(' ', bigBlindStart); string bigBlindText = blindsAndAntes.Substring(bigBlindStart, bigBlindEnd - bigBlindStart); if (bigBlindText[0] == '$') bigBlindText = bigBlindText.Substring(1); hand.Context.BigBlind = Decimal.Parse(bigBlindText.Trim()); int anteIndex = blindsAndAntes.IndexOf("Ante"); if (anteIndex != -1) { int anteStart = anteIndex + 5; string anteText = blindsAndAntes.Substring(anteStart); if (anteText[0] == '$') anteText = anteText.Substring(1); hand.Context.Ante = Decimal.Parse(anteText.Trim()); } #endregion #if DEBUG Console.WriteLine("Game Format"); #endif #region Get the game format if (hand.Context.Table.Contains("Sit & Go")) hand.Context.Format = GameFormat.SitNGo; else if (blindsAndAntes.Contains("$")) hand.Context.Format = GameFormat.CashGame; else hand.Context.Format = GameFormat.MultiTableTournament; #endregion #if DEBUG Console.WriteLine("Poker Variant and Betting Type"); #endif #region Get the betting type and poker variant start = end + 2; end = handText.IndexOf('-', start); string typeAndVariant = handText.Substring(start, end - start); int capIndex = typeAndVariant.IndexOf(" Cap "); if (capIndex != -1) { string capAmountText = handText.Substring(start, capIndex - start); hand.Context.CapAmount = Decimal.Parse(capAmountText.Trim().Replace("$", "")); hand.Context.CapAmountSpecified = true; hand.Context.Capped = true; } else { hand.Context.CapAmountSpecified = false; hand.Context.Capped = false; } if(typeAndVariant.Contains("Pot Limit")) hand.Context.BettingType = BettingType.PotLimit; else if(typeAndVariant.Contains("No Limit")) hand.Context.BettingType = BettingType.NoLimit; else hand.Context.BettingType = BettingType.FixedLimit; if (typeAndVariant.Contains("Hold'em")) hand.Context.PokerVariant = PokerVariant.TexasHoldEm; else if(typeAndVariant.Contains("Omaha Hi")) hand.Context.PokerVariant = PokerVariant.OmahaHi; else hand.Context.PokerVariant = PokerVariant.OmahaHiLo; #endregion #if DEBUG Console.WriteLine("Time Stamp"); #endif #region Get the date and time start = end + 2; end = handText.IndexOf(' ', start); string timeText = handText.Substring(start, end - start); string[] timeTokens = timeText.Split(':'); int hour = Int32.Parse(timeTokens[0]); int minute = Int32.Parse(timeTokens[1]); int second = Int32.Parse(timeTokens[2]); start = handText.IndexOf('-', end) + 2; string dateText = lines[0].Substring(start); string[] dateTokens = dateText.Split('/'); int year = Int32.Parse(dateTokens[0]); int month = Int32.Parse(dateTokens[1]); int day = Int32.Parse(dateTokens[2]); hand.Context.TimeStamp = new DateTime(year, month, day, hour, minute, second); #endregion #if DEBUG Console.WriteLine("Players"); #endif #region Create the players List<Player> players = new List<Player>(); curLine = 1; for (Match m = stacksExp.Match(lines[curLine]); m.Success; m = stacksExp.Match(lines[curLine])) { if (m.Success) { GroupCollection gc = m.Groups; Player p = new Player(); p.Seat = Int32.Parse(gc[1].Value); p.Name = gc[2].Value; p.Stack = Decimal.Parse(gc[3].Value); players.Add(p); curLine++; } } hand.Players = players.ToArray(); #endregion #if DEBUG Console.WriteLine("Blinds and Antes Posted"); #endif #region Get the blinds and antes posted List<Blind> blinds = new List<Blind>(); for (; !lines[curLine].StartsWith("The button is in seat #"); curLine++) { for (Match m = actionExp.Match(lines[curLine]); m.Success; m = m.NextMatch()) { GroupCollection gc = m.Groups; Blind blind = new Blind(); blind.Player = gc[1].Value; if (gc[2].Value == "antes") blind.Type = BlindType.Ante; else if (gc[6].Value == "small") blind.Type = gc[5].Value.Trim() == "dead" ? BlindType.DeadBlind : BlindType.SmallBlind; else if (gc[6].Value == "big") blind.Type = gc[5].Value.Trim() == "dead" ? BlindType.DeadBlind : BlindType.BigBlind; else if (gc[2].Value == "posts") blind.Type = BlindType.LateBlind; else throw new Exception("Unknown blind type: " + lines[curLine]); if (lines[curLine].Contains("dead")) { for (int i = 0; i < gc.Count; i++) Console.WriteLine("{0}: \"{1}\"", i, gc[i].Value); Console.WriteLine("Found as {0}", blind.Type.ToString()); } blind.Amount = Decimal.Parse(gc[7].Value); blind.AllIn = gc[9].Value.Length == 15; blinds.Add(blind); } } hand.Blinds = blinds.ToArray(); #endregion #if DEBUG Console.WriteLine("Button"); #endif #region Get the button string buttonText = lines[curLine].Substring(lines[curLine].IndexOf('#') + 1); hand.Context.Button = Int32.Parse(buttonText); curLine++; #endregion #if DEBUG Console.WriteLine("Hole Cards and Hero"); #endif #region Get the hole cards and the name of the hero while (!lines[curLine].StartsWith("Dealt to ")) curLine++; start = "Dealt to ".Length; end = lines[curLine].IndexOf(" [", start); hand.Hero = lines[curLine].Substring(start, end - start); start = end + 2; List<Card> holecards = new List<Card>(); holecards.Add(new Card(lines[curLine].Substring(start, 2))); holecards.Add(new Card(lines[curLine].Substring(start + 3, 2))); if (hand.Context.PokerVariant != PokerVariant.TexasHoldEm) { holecards.Add(new Card(lines[curLine].Substring(start + 6, 2))); holecards.Add(new Card(lines[curLine].Substring(start + 9, 2))); } hand.HoleCards = holecards.ToArray(); curLine++; #endregion #if DEBUG Console.WriteLine("Preflop Actions"); #endif #region Preflop Actions rounds.Add(new Round()); rounds[0].Actions = getRoundActions(lines, ref curLine); #endregion #if DEBUG Console.WriteLine("Flop Actions"); #endif #region Flop Actions and Community Cards if (lines[curLine].StartsWith("*** FLOP ***")) { rounds.Add(new Round()); start = lines[curLine].IndexOf('[') + 1; Card[] flop = new Card[3]; flop[0] = new Card(lines[curLine].Substring(start, 2)); flop[1] = new Card(lines[curLine].Substring(start + 3, 2)); flop[2] = new Card(lines[curLine].Substring(start + 6, 2)); rounds[1].CommunityCards = flop; curLine++; rounds[1].Actions = getRoundActions(lines, ref curLine); } #endregion #if DEBUG Console.WriteLine("Turn Actions"); #endif #region Turn Actions and Community Card if (lines[curLine].StartsWith("*** TURN ***")) { rounds.Add(new Round()); start = lines[curLine].LastIndexOf('[') + 1; Card[] turn = new Card[1]; turn[0] = new Card(lines[curLine].Substring(start, 2)); rounds[2].CommunityCards = turn; curLine++; rounds[2].Actions = getRoundActions(lines, ref curLine); } #endregion #if DEBUG Console.WriteLine("River Actions"); #endif #region River Actions and Community Card if (lines[curLine].StartsWith("*** RIVER ***")) { rounds.Add(new Round()); start = lines[curLine].LastIndexOf('[') + 1; Card[] river = new Card[1]; river[0] = new Card(lines[curLine].Substring(start, 2)); rounds[3].CommunityCards = river; curLine++; rounds[3].Actions = getRoundActions(lines, ref curLine); } #endregion #region Set rounds hand.Rounds = rounds.ToArray(); #endregion #if DEBUG Console.WriteLine("Results"); #endif #region Get pots won List<HandResult> results = new List<HandResult>(); List<List<Pot>> pots = new List<List<Pot>>(); for (; !lines[curLine].StartsWith("*** SUMMARY"); curLine++) { Match m = potsExp.Match(lines[curLine]); if (m.Success) { GroupCollection gc = m.Groups; Pot p = new Pot(); p.Amount = Decimal.Parse(gc[8].Value); if (gc[7].Value.Length > 0) p.Number = Int32.Parse(gc[7].Value); else if ((gc[5].Value.Length == 0 && gc[3].Value == "the pot") || gc[5].Value == "main ") p.Number = 0; else if (gc[5].Length > 0) p.Number = 1; HandResult result = null; List<Pot> potList = null; for (int i = 0; i < results.Count; i++) { if (results[i].Player == gc[1].Value) { result = results[i]; potList = pots[i]; break; } } if (result == null) { result = new HandResult(gc[1].Value); potList = new List<Pot>(); results.Add(result); pots.Add(potList); } potList.Add(p); } } //add the pots to the model for (int i = 0; i < results.Count; i++) { results[i].WonPots = pots[i].ToArray(); } //get the rake, if any if (hand.Context.Format == GameFormat.CashGame) { for (; !lines[curLine].StartsWith("Total pot") || lines[curLine].Contains(":") || !lines[curLine].Contains("| Rake "); curLine++) { } int rakeStart = lines[curLine].LastIndexOf("| Rake ") + "| Rake ".Length; string rakeText = lines[curLine].Substring(rakeStart).Replace("$", ""); hand.Rake = Decimal.Parse(rakeText); } #endregion #if DEBUG Console.WriteLine("Shown Hands"); #endif #region Get the shown down hands for (; curLine < lines.Count; curLine++) { Match m = shownHandsExp.Match(lines[curLine]); if (m.Success) { GroupCollection gc = m.Groups; List<Card> shownCards = new List<Card>(); shownCards.Add(new Card(gc[5].Value)); shownCards.Add(new Card(gc[6].Value)); if (hand.Context.PokerVariant != PokerVariant.TexasHoldEm) { shownCards.Add(new Card(gc[8].Value)); shownCards.Add(new Card(gc[9].Value)); } string player = gc[2].Value; HandResult hr = null; foreach (HandResult curResult in results) if (curResult.Player == player) { hr = curResult; break; } if (hr == null) { hr = new HandResult(player); results.Add(hr); } hr.HoleCards = shownCards.ToArray(); } } #endregion #region Set the results hand.Results = results.ToArray(); #endregion #if DEBUG Console.WriteLine("Done"); #endif return hand; }