Exemplo n.º 1
0
        protected override TournamentDescriptor ParseTournament(string[] handLines)
        {
            var line = handLines[3];

            var regex = new Regex(@"Tournament #(?<tournament_id>[^\s]+) (?<buyin>[^-]+) - Table #(?<tablenum>\d+) (?<tabletype>[^\(]+) \((?<money>[^\)]+)\)");

            var match = regex.Match(line);

            if (!match.Success)
            {
                return(null);
            }

            var buyinText = match.Groups["buyin"].Value;

            var splittedBuyin = buyinText.Split('+');

            decimal prizePool = 0;

            ParserUtils.TryParseMoney(splittedBuyin[0], out prizePool);

            var rake = splittedBuyin.Length > 1 ? ParserUtils.ParseMoney(splittedBuyin[1]) : 0m;

            var currency = match.Groups["money"].Value.Contains("Real Money") ? Currency.USD : Currency.PlayMoney;

            var tournamentDescriptor = new TournamentDescriptor
            {
                TournamentId   = match.Groups["tournament_id"].Value,
                BuyIn          = Buyin.FromBuyinRake(prizePool, rake, currency),
                Speed          = TournamentSpeed.Regular,
                TournamentName = string.Format("Tournament #{0}", match.Groups["tournament_id"].Value)
            };

            return(tournamentDescriptor);
        }
Exemplo n.º 2
0
        private void ProcessSTT(TournamentDescriptor tournament, string roomName, RoomData roomData)
        {
            tournament.TournamentsTags = TournamentsTags.STT;
            tournament.TournamentId    = roomName.Substring(roomName.IndexOf('#') + 1);
            tournament.TournamentName  = roomName;

            if (string.IsNullOrEmpty(roomData.BuyinFees))
            {
                return;
            }

            var buyinFeeStrings = roomData.BuyinFees.Split('#');

            if (!int.TryParse(buyinFeeStrings[0], out int prizePool))
            {
                LogProvider.Log.Warn(this, $"Failed to parse prize pool of buyinFee {roomData.BuyinFees} of STT {roomName}. [{loggerName}]");
            }

            var fee = 0;

            if (buyinFeeStrings.Length > 1 && !string.IsNullOrEmpty(buyinFeeStrings[1]) && !int.TryParse(buyinFeeStrings[1], out fee))
            {
                LogProvider.Log.Warn(this, $"Failed to parse fee of buyinFee {roomData.BuyinFees} of STT {roomName}. [{loggerName}]");
            }

            tournament.BuyIn = Buyin.FromBuyinRake(prizePool, fee, currency);
        }
        private void setupTournamentHands(TreeNode parentNode, PokerFormat format)
        {
            DatabaseHandler databaseHandler = DatabaseHandler.getInstance();
            IAggregateFluent <TournamentSummary> tournaments = databaseHandler.GetAllTournaments()
                                                               .Aggregate().Match(Builders <TournamentSummary> .Filter.Where(h => h.SitAndGo == (format == PokerFormat.SitAndGo)));
            IAggregateFluent <HandHistory> allHands = databaseHandler.GetAllHands().Aggregate()
                                                      .Match(Builders <HandHistory> .Filter.Where(h => h.GameDescription.PokerFormat == format));
            IEnumerable <AggregateResult <Buyin> > allBuyins =
                tournaments.Group(h => h.Buyin, h => new AggregateResult <Buyin> {
                result = h.Key
            })
                .Sort(Builders <AggregateResult <Buyin> > .Sort.Ascending(b => b.result))
                .ToEnumerable();

            decimal lastBuyin = -0.01m;

            foreach (dynamic buyinObj in allBuyins)
            {
                Buyin buyin = buyinObj.result;

                if (buyin.Total == lastBuyin)
                {
                    continue;
                }
                lastBuyin = buyin.Total;
                IAggregateFluent <HandHistory> hands =
                    allHands.Match(Builders <HandHistory> .Filter.Where(h => h.GameDescription.TournamentSummary.Buyin.Total == buyin.Total));
                GroupHandTreeNode buyinNode =
                    new GroupHandTreeNode(string.Format("{0}{1} {2}", buyin.GetCurrencySymbol(),
                                                        buyin.Total,
                                                        HandCount(hands)),
                                          hands);
                dynamic allIds = hands.Group(h => h.GameDescription.TournamentId, h => new { name = h.Key }).ToEnumerable();

                foreach (dynamic idObj in allIds)
                {
                    string id = idObj.name;

                    if (!string.IsNullOrWhiteSpace(id))
                    {
                        IEnumerable <TournamentSummary> summaries = tournaments.Match(t => t.Id == id).ToEnumerable();

                        if (summaries.Count() > 0)
                        {
                            TournamentSummary summary = summaries.First();

                            IAggregateFluent <HandHistory> tournyHands =
                                allHands.Match(Builders <HandHistory> .Filter.Where(h => h.GameDescription.TournamentId == summary.Id));
                            buyinNode.Nodes.Add(new HandsTreeNode(summary.ToString(), tournyHands));
                        }
                    }
                }

                if (buyinNode.Nodes.Count > 0)
                {
                    parentNode.Nodes.Add(buyinNode);
                }
            }
        }
Exemplo n.º 4
0
        private void ProcessMTT(TournamentDescriptor tournament, string roomName)
        {
            tournament.TournamentsTags = TournamentsTags.MTT;

            var tournamentData = mttData.Values.FirstOrDefault(x =>
                                                               x.MTTTables != null && x.MTTTables.MTTTableInfo != null &&
                                                               x.MTTTables.MTTTableInfo.MTTTables != null &&
                                                               x.MTTTables.MTTTableInfo.MTTTables.Any(m => m.TableName.Equals(roomName)));

            if (tournamentData == null)
            {
                tournament.TournamentId = roomName;
                LogProvider.Log.Warn(this, $"Failed to find MTT info for {roomName}. [{loggerName}]");
            }
            else
            {
                tournament.TournamentId   = tournamentData.MTTTables.RoomName.Substring(tournamentData.MTTTables.RoomName.IndexOf('#') + 1);
                tournament.TournamentName = tournamentData.MTTPrizes?.MTTPrizeInfo?.GameDetail;

                if (DateTime.TryParseExact(tournamentData.MTTInfo?.MTTDetailedInfo?.StartDateText, "MMM dd, yyyy HH:mm:ss",
                                           CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime startDate))
                {
                    var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
                    tournament.StartDate = TimeZoneInfo.ConvertTimeToUtc(startDate, timeZoneInfo);
                }
                else
                {
                    tournament.StartDate = DateTime.UtcNow;
                }

                var entryChips = tournamentData.MTTInfo?.MTTDetailedInfo?.EntryChipInfo?.EntryChips?.FirstOrDefault(x => x.IsReal);

                if (entryChips != null)
                {
                    tournament.StartingStack = entryChips.InitialStakes;

                    var comissionRate = tournamentData.MTTInfo.MTTDetailedInfo.ComissionRate;

                    var fee = Math.Round(entryChips.Amount * comissionRate / 100, 0);
                    // it isn't correct to include bounty in prize, but currently DH doesn't show bounty as standalone field
                    var prizePool = entryChips.Amount - fee + tournamentData.MTTInfo.MTTDetailedInfo.BountyAmount;

                    tournament.BuyIn = Buyin.FromBuyinRake(prizePool, fee, currency);
                }
                else
                {
                    entryChips = tournamentData.MTTInfo?.MTTDetailedInfo?.EntryChipInfo?.EntryChips?.FirstOrDefault();

                    tournament.StartingStack = entryChips != null ? entryChips.InitialStakes : DefaultStartingStack;

                    tournament.BuyIn = Buyin.FromBuyinRake(0, 0, currency);

                    LogProvider.Log.Warn(this, $"Failed to find buyin info for {tournamentData.MTTTables.RoomName}. [{loggerName}]");
                }
            }
        }
        protected override Buyin ParseBuyin(string[] handLines)
        {
            string line            = handLines[1];
            int    buyinStartIndex = line.IndexOf('$');
            int    buyinEndIndex   = line.IndexOf(' ', buyinStartIndex);

            string buyin = line.Substring(buyinStartIndex, buyinEndIndex - buyinStartIndex);

            return(Buyin.FromBuyinRake(buyin.ParseAmount(), 0, Currency.USD));
        }
Exemplo n.º 6
0
        protected override Buyin ParseBuyin(string[] handLines)
        {
            //Expected format:
            //***** History for hand T5-556424428-1 (TOURNAMENT: "€214 ChampionChip Turbo Qualifier Rebuy", R-10093-864, buy-in: €5) *****
            string line       = handLines[0];
            int    startIndex = line.IndexOf("buy-in: ") + 8;
            int    endIndex   = line.IndexOf(")", startIndex);

            string buyinStr = line.Substring(startIndex, endIndex - startIndex);

            return(Buyin.FromBuyinRake(buyinStr.ParseAmount(), 0, Currency.USD));
        }
Exemplo n.º 7
0
        private TournamentDescriptor ParseTournamentDescriptor(GameRoomInfo gameRoomInfo)
        {
            if (!gameRoomInfo.IsTournament)
            {
                return(null);
            }

            var tournamentDescriptor = new TournamentDescriptor
            {
                BuyIn          = Buyin.FromBuyinRake(PMImporterHelper.ConvertSNGTypeToBuyIn(gameRoomInfo.SNGGameRoomBaseInfo.SNGRoomtype), 0, Currency.YUAN),
                Speed          = gameRoomInfo.SNGGameRoomBaseInfo.SNGRoomtype == SNGRoomType.QUICK_SNG ? TournamentSpeed.Turbo : TournamentSpeed.Regular,
                StartDate      = DateTimeHelper.UnixTimeToDateTime(gameRoomInfo.SNGGameRoomBaseInfo.StartTime / 1000),
                TournamentName = gameRoomInfo.SNGGameRoomBaseInfo.RoomName,
                TournamentId   = gameRoomInfo.SNGGameRoomBaseInfo.GameRoomId.ToString(),
                TotalPlayers   = (short)gameRoomInfo.SNGGameRoomBaseInfo.GameRoomUserMaxNums
            };

            return(tournamentDescriptor);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Parses tournament description from the specified HH lines
        /// </summary>
        /// <param name="handLines">Lines to parse</param>
        /// <returns>Description of tournament</returns>
        protected override TournamentDescriptor ParseTournament(string[] handLines)
        {
            Buyin buyIn;

            if (handLines[0].Contains("Freeroll"))
            {
                buyIn = Buyin.FromBuyinRake(0, 0, DefaultCurrency);
            }
            else
            {
                var prizePoolText = handLines[0].TakeBetween("buyIn: ", " +");
                var entryFeeText  = handLines[0].TakeBetween(" + ", " ");

                if (!ParserUtils.TryParseMoney(prizePoolText, out decimal prizePoolValue))
                {
                    throw new BuyinException(handLines[0], "Could not parse buyin.");
                }

                if (!ParserUtils.TryParseMoney(entryFeeText, out decimal entryFee))
                {
                    throw new BuyinException(handLines[0], "Could not parse entry fee.");
                }

                buyIn = Buyin.FromBuyinRake(prizePoolValue, entryFee, DefaultCurrency);
            }

            var tableInfoLine = GetTableInfoLine(handLines);

            var tournamentName = handLines[0].TakeBetween("Tournament \"", "\"");
            var tournamentId   = tableInfoLine.TakeBetween("(", ")");

            var tournamentDescriptor = new TournamentDescriptor
            {
                TournamentId   = tournamentId,
                TournamentName = tournamentName,
                BuyIn          = buyIn
            };

            return(tournamentDescriptor);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Parses tournament description from the specified HH lines
        /// </summary>
        /// <param name="handLines">Lines to parse</param>
        /// <returns>Description of tournament</returns>
        protected override TournamentDescriptor ParseTournament(string[] handLines)
        {
            var header = ParseHeader(handLines);

            var tournamentHeader = header[0].Replace("Table", string.Empty)
                                   .Replace("Turbo", string.Empty);

            var tournamentId = tournamentHeader.Substring(tournamentHeader.IndexOf(" T") + 2).Trim();

            var buyIn = Buyin.FromBuyinRake(0, 0, DefaultCurrency);

            if (header.Length == 7 && header[2].Contains("+"))
            {
                var buyInHeaders = header[2].Split('+');

                if (buyInHeaders.Length == 2)
                {
                    if (!ParserUtils.TryParseMoney(buyInHeaders[0].Trim(), out decimal prizePoolValue))
                    {
                        throw new BuyinException(handLines[0], "Could not parse buyin.");
                    }

                    if (!ParserUtils.TryParseMoney(buyInHeaders[1].Trim(), out decimal entryFee))
                    {
                        throw new BuyinException(handLines[0], "Could not parse entry fee.");
                    }

                    buyIn.PrizePoolValue = prizePoolValue;
                    buyIn.Rake           = entryFee;
                }
            }

            var tournamentName = header[0].Replace($" T{tournamentId}", string.Empty).Trim();

            if (tournamentName.StartsWith("- ", StringComparison.Ordinal))
            {
                tournamentName = tournamentName.Substring(2);
            }

            var tournamentDescriptor = new TournamentDescriptor
            {
                TournamentId   = tournamentId,
                Speed          = ParserUtils.ParseTournamentSpeed(header[0]),
                TournamentName = tournamentName,
                BuyIn          = buyIn
            };

            for (var i = handLines.Length - 1; i > 0; i--)
            {
                if (handLines[i].Contains(" finished "))
                {
                    var totalPlayersText = handLines[i].TakeBetween(" out of ", " players");

                    if (int.TryParse(totalPlayersText, out int totalPlayers))
                    {
                        tournamentDescriptor.TotalPlayers = totalPlayers;

                        if (totalPlayers > 1)
                        {
                            var placeText = handLines[i].TakeBetween(" finished ", " out of ");

                            if (int.TryParse(placeText, out int place))
                            {
                                tournamentDescriptor.FinishPosition = place;
                            }
                        }
                    }
                }
                else if (handLines[i].StartsWith("***SHOW", StringComparison.OrdinalIgnoreCase))
                {
                    break;
                }
            }

            return(tournamentDescriptor);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Parses summary hand
        /// </summary>
        /// <param name="handLines">Lines to parse</param>
        /// <param name="handHistory">Handhistory to update</param>
        /// <returns>Handhistory with summary data</returns>
        protected override HandHistory ParseSummaryHand(string[] handLines, HandHistory handHistory)
        {
            var tournament = new TournamentDescriptor
            {
                Summary = string.Join(Environment.NewLine, handLines)
            };

            var gameType = GameType.Unknown;

            foreach (var handLine in handLines)
            {
                if (handLine.ContainsIgnoreCase("Tournament summary"))
                {
                    var tournamentName = handLine.TakeBetween(" : ", "(");
                    var tournamentId   = handLine.TakeBetween("(", ")", true);

                    if (string.IsNullOrEmpty(tournamentId))
                    {
                        throw new TournamentIdException(handLine, "Couldn't parse tournament id");
                    }

                    tournament.TournamentId   = tournamentId;
                    tournament.TournamentName = tournamentName;
                }
                else if (handLine.StartsWith("Player :", StringComparison.OrdinalIgnoreCase))
                {
                    var playerName = handLine.TakeBetween(" : ", string.Empty);
                    handHistory.Hero = new Player(playerName, 0, 0);
                }
                else if (handLine.StartsWith("Buy-In :", StringComparison.OrdinalIgnoreCase))
                {
                    var prizePoolText = handLine.TakeBetween(": ", " +");
                    var entryFeeText  = handLine.TakeBetween(" + ", string.Empty);

                    if (!ParserUtils.TryParseMoney(prizePoolText, out decimal prizePoolValue))
                    {
                        throw new BuyinException(handLines[0], "Could not parse buyin.");
                    }

                    if (!ParserUtils.TryParseMoney(entryFeeText, out decimal entryFee))
                    {
                        throw new BuyinException(handLines[0], "Could not parse entry fee.");
                    }

                    tournament.BuyIn = Buyin.FromBuyinRake(prizePoolValue, entryFee, DefaultCurrency);
                }
                else if (handLine.StartsWith("Registered players :", StringComparison.OrdinalIgnoreCase))
                {
                    var totalPlayersText = handLine.TakeBetween(" : ", string.Empty);

                    if (int.TryParse(totalPlayersText, out int totalPlayers))
                    {
                        tournament.TotalPlayers = totalPlayers;
                    }
                }
                else if (handLine.StartsWith("Speed : ", StringComparison.OrdinalIgnoreCase))
                {
                    var speedText = handLine.TakeBetween(": ", string.Empty);

                    tournament.Speed = speedText.Equals("turbo", StringComparison.OrdinalIgnoreCase) ?
                                       TournamentSpeed.Turbo :
                                       TournamentSpeed.Regular;
                }
                else if (handLine.StartsWith("Levels :", StringComparison.OrdinalIgnoreCase))
                {
                    var levelLine = handLine.Replace('-', ' ');

                    try
                    {
                        gameType = ParseGameType(new[] { levelLine });
                    }
                    catch
                    {
                        // do nothing, type will be set in importer
                    }
                }
                else if (handLine.StartsWith("Tournament started", StringComparison.OrdinalIgnoreCase))
                {
                    var dateText = handLine.TakeBetween("started ", string.Empty);

                    try
                    {
                        tournament.StartDate = ParseDateFromText(dateText);
                    }
                    catch
                    {
                        // do nothing, date will be set in importer
                    }
                }
                else if (handLine.StartsWith("You finished in", StringComparison.OrdinalIgnoreCase))
                {
                    var finishedPositionText = handLine
                                               .TakeBetween("finished in ", " place")
                                               .Replace("th", string.Empty)
                                               .Replace("st", string.Empty)
                                               .Replace("nd", string.Empty)
                                               .Replace("rd", string.Empty);

                    if (int.TryParse(finishedPositionText, out int finishPosition))
                    {
                        tournament.FinishPosition = finishPosition;
                    }
                }
                else if (handLine.StartsWith("You won", StringComparison.OrdinalIgnoreCase))
                {
                    var wonText = handLine.TakeBetween("You won ", string.Empty);

                    if (ParserUtils.TryParseMoney(wonText, out decimal won))
                    {
                        tournament.Winning = won;
                    }
                }
                else if (handLine.StartsWith("Your rebuys", StringComparison.OrdinalIgnoreCase))
                {
                    var rebuysText = handLine.TakeBetween(":", string.Empty);

                    if (ParserUtils.TryParseMoney(rebuysText, out decimal rebuy))
                    {
                        tournament.Rebuy = rebuy;
                    }
                }
                else if (handLine.StartsWith("Your addons", StringComparison.OrdinalIgnoreCase))
                {
                    var addonsText = handLine.TakeBetween(":", string.Empty);

                    if (ParserUtils.TryParseMoney(addonsText, out decimal addon))
                    {
                        tournament.Addon = addon;
                    }
                }
            }

            handHistory.GameDescription = new GameDescriptor(SiteName,
                                                             gameType,
                                                             null,
                                                             TableType.FromTableTypeDescriptions(),
                                                             SeatType.AllSeatType(),
                                                             tournament);

            return(handHistory);
        }
        private void ProcessDealerInfoRSP(DealerInfoRSP message, ClientRecord record, HandHistory history)
        {
            if (!TryParseHandID(message.GameID, out long handId))
            {
                //throw new DHInternalException(new NonLocalizableString($"Failed to parse hand id from '{noticeResetGame.GameId}'."));
                throw new Exception($"Failed to parse hand id from '{message.GameID}'.");
            }

            LogProvider.Log.Info($"Parsed GameID = {message.GameID} into HandID = {handId}");

            history.HandId = handId;

            TournamentDescriptor tournament = null;

            if (record.IsTournament)
            {
                const int RakeProportion = 10;

                long rake           = record.TournamentHasFixedRewards ? 0 : record.TournamentBuyIn / RakeProportion;
                long prizePoolValue = record.TournamentBuyIn - rake - record.TournamentBounty;

                tournament = new TournamentDescriptor
                {
                    TournamentId   = record.TournamentID,
                    TournamentName = record.TournamentName,
                    StartDate      = record.TournamentStartDate,
                    BuyIn          = Buyin.FromBuyinRake(prizePoolValue, rake, Currency.All, record.TournamentBounty > 0, record.TournamentBounty),
                    Rebuy          = record.TournamentReBuy,
                    Addon          = record.TournamentAddOn,
                    Speed          = TournamentSpeed.Regular, // I didn't discover any reliable way to determine tournament speed from protocol messages
                };
            }

            history.GameDescription = new GameDescriptor(
                EnumPokerSites.PPPoker,
                record.IsOmaha ? GameType.PotLimitOmaha : GameType.NoLimitHoldem,
                Limit.FromSmallBlindBigBlind(record.SmallBlind, record.BigBlind, Currency.All, record.Ante > 0, record.Ante),
                TableType.FromTableTypeDescriptions(record.Ante > 0 ? TableTypeDescription.Ante : TableTypeDescription.Regular),
                SeatType.FromMaxPlayers(record.MaxPlayers),
                tournament
                );

            history.GameDescription.Identifier = record.RoomID;
            history.TableName = $"{record.RoomName}-{record.TableID}";

            foreach (var stackInfo in message.Stacks)
            {
                if (!record.Players.ContainsKey(stackInfo.SeatID))
                {
                    throw new Exception($"Can't find a player sitting on seat #{stackInfo.SeatID} for hand {handId}. Total known players: {record.Players.Count}. Total participating players: {message.Stacks.Length}.");
                }

                var roomPlayer = record.Players[stackInfo.SeatID];

                var player = new Player
                {
                    PlayerName    = roomPlayer.ID.ToString(),
                    PlayerNick    = roomPlayer.Name,
                    StartingStack = stackInfo.Chips,
                    SeatNumber    = stackInfo.SeatID + 1,
                    IsSittingOut  = false
                };

                history.Players.Add(player);
            }

            history.DealerButtonPosition = message.Dealer + 1;
        }
 protected override Buyin ParseBuyin(string[] handLines)
 {
     return(Buyin.FromBuyinRake(0, 0, Currency.CHIPS));
 }
Exemplo n.º 13
0
        protected override HandHistory ParseSummaryHand(string[] handLines, HandHistory handHistory)
        {
            var tournament = new TournamentDescriptor
            {
                Summary = string.Join(Environment.NewLine, handLines)
            };

            foreach (var handLine in handLines)
            {
                // parse tournament id
                if (handLine.StartsWith("Tournament ID", StringComparison.InvariantCultureIgnoreCase))
                {
                    var indexOfColon = handLine.IndexOf(":");
                    tournament.TournamentId = handLine.Substring(indexOfColon + 1).Trim();
                }
                else if (handLine.StartsWith("Buy-In", StringComparison.InvariantCultureIgnoreCase))
                {
                    var buyInText = ParseTournamentSummaryMoneyLine(handLine);

                    var buyInSplit = buyInText.Split('+');

                    decimal  buyIn    = 0;
                    decimal  rake     = 0;
                    Currency currency = Currency.USD;

                    if (ParserUtils.TryParseMoney(buyInSplit[0], out buyIn, out currency))
                    {
                        if (buyInSplit.Length > 1)
                        {
                            ParserUtils.TryParseMoney(buyInSplit[1], out rake, out currency);
                        }
                    }

                    tournament.BuyIn = Buyin.FromBuyinRake(buyIn, rake, currency);
                }
                else if (handLine.StartsWith("Rebuy", StringComparison.InvariantCultureIgnoreCase))
                {
                    var rebuyText = ParseTournamentSummaryMoneyLine(handLine);

                    decimal  rebuy    = 0;
                    Currency currency = Currency.USD;

                    if (ParserUtils.TryParseMoney(rebuyText, out rebuy, out currency))
                    {
                        tournament.Rebuy = rebuy;
                    }
                }
                else if (handLine.StartsWith("Add-On", StringComparison.InvariantCultureIgnoreCase))
                {
                    var addonText = ParseTournamentSummaryMoneyLine(handLine);

                    decimal  addon    = 0;
                    Currency currency = Currency.USD;

                    if (ParserUtils.TryParseMoney(addonText, out addon, out currency))
                    {
                        tournament.Addon = addon;
                    }
                }
                else if (handLine.Contains("finished"))
                {
                    var match = SummaryFinishedRegex.Match(handLine);

                    if (!match.Success)
                    {
                        LogProvider.Log.Error(string.Format("'{0}' wasn't parsed", handLine));
                        continue;
                    }

                    var playerName       = match.Groups["player"].Value;
                    var positionText     = match.Groups["position"].Value;
                    var totalPlayersText = match.Groups["total"].Value;
                    var wonText          = match.Groups["won"] != null ? match.Groups["won"].Value.Replace(",", ".").Trim() : string.Empty;

                    handHistory.Hero = new Player(playerName, 0, 0);

                    short    position     = 0;
                    short    totalPlayers = 0;
                    decimal  won          = 0;
                    Currency wonCurrency  = Currency.USD;

                    if (!short.TryParse(positionText, out position))
                    {
                        LogProvider.Log.Error(string.Format("'{0}' position wasn't parsed", handLine));
                        continue;
                    }

                    if (!short.TryParse(totalPlayersText, out totalPlayers))
                    {
                        LogProvider.Log.Error(string.Format("'{0}' total players weren't parsed", handLine));
                        continue;
                    }

                    if (!string.IsNullOrWhiteSpace(wonText) && !ParserUtils.TryParseMoney(wonText, out won, out wonCurrency))
                    {
                        LogProvider.Log.Error(string.Format("'{0}' won data wasn't parsed", handLine));
                        continue;
                    }

                    tournament.FinishPosition = position;
                    tournament.TotalPlayers   = totalPlayers;
                    tournament.Winning        = won;
                }
            }

            handHistory.GameDescription = new GameDescriptor(EnumPokerSites.Poker888,
                                                             GameType.Unknown,
                                                             null,
                                                             TableType.FromTableTypeDescriptions(),
                                                             SeatType.AllSeatType(),
                                                             tournament);

            return(handHistory);
        }
        protected override Buyin ParseBuyin(string[] handLines)
        {
            // Expect the first line to look like:
            // PokerStars Hand #121723607468: Tournament #973955807, $2.30+$2.30+$0.40 USD Hold'em No Limit - Level XIII (600/1200)
            // PokerStars Hand #121732709812: Tournament #974092011, $55.56+$4.44 USD Hold'em No Limit - Level VI (100/200) - 2014/09/18 17:02:21 ET
            // this is obviously not needed for CashGame
            var TournamentIdStartindex = GetTournamentIdStartIndex(handLines[0]);

            int startIndex = handLines[0].IndexOf(',', TournamentIdStartindex) + 2;
            int endIndex   = handLines[0].IndexOf(' ', startIndex);

            string buyinSubstring = handLines[0].Substring(startIndex, endIndex - startIndex);

            Currency currency;

            if (buyinSubstring.EndsWithFast("FPP"))
            {
                currency = Currency.RAKE_POINTS;
            }
            else if (buyinSubstring.Contains("Freeroll"))
            {
                currency = Currency.SATELLITE;
            }
            else
            {
                currency = ParseCurrency(handLines[0], buyinSubstring[0]);
            }

            decimal prizePoolValue;
            decimal rake;
            decimal knockoutValue = 0m;

            var buyinSplit = buyinSubstring.Split('+');

            if (buyinSplit.Length == 3)
            {
                prizePoolValue = buyinSplit[0].ParseAmount();
                knockoutValue  = buyinSplit[1].ParseAmount();
                rake           = buyinSplit[2].ParseAmount();
            }
            else if (buyinSplit.Length == 2)
            {
                prizePoolValue = buyinSplit[0].ParseAmount();
                rake           = buyinSplit[1].ParseAmount();
            }
            else if (buyinSplit.Length == 1)
            {
                if (buyinSplit[0].EndsWithFast("FPP"))
                {
                    prizePoolValue = 0;
                    rake           = 0;
                }
                else if (buyinSplit[0] == "Freeroll")
                {
                    prizePoolValue = 0;
                    rake           = 0;
                }
                else
                {
                    throw new BuyinException(handLines[0], "Expected FPP/Freeroll Buyin Format");
                }
            }
            else
            {
                throw new BuyinException(handLines[0], "Unrecognized Buyin Format");
            }

            return(Buyin.FromBuyinRake(prizePoolValue, rake, currency, knockoutValue != 0m, knockoutValue));
        }