Ejemplo n.º 1
0
        internal static string Translate(Bid bid, Seats source)
        {
            string bidText = SeatsExtensions.ToXMLFull(source) + " ";

            switch (bid.Special)
            {
            case SpecialBids.Pass:
                bidText += "passes";
                break;

            case SpecialBids.Double:
                bidText += "doubles";
                break;

            case SpecialBids.Redouble:
                bidText += "redoubles";
                break;

            case SpecialBids.NormalBid:
                bidText += "bids " + ((int)bid.Level).ToString() + (bid.Suit == Suits.NoTrump ? "NT" : bid.Suit.ToString().Substring(0, 1));
                break;
            }

#if Olympus
            bidText += " Infos." + this.AlertToTM(bid.Explanation, source);
#else
            if (bid.Alert)
            {
                bidText += " Alert. " + AlertToTM(bid.Explanation, source);
            }
#endif
            return(bidText);
        }
Ejemplo n.º 2
0
        public static void HandleProtocolPlay(string message, BridgeEventBus bus)
        {
            // North plays 3C
            string[] answer = message.Split(' ');
            var      player = SeatsExtensions.FromXML(answer[0]);
            var      suit   = SuitHelper.FromXML(answer[2][1]);
            var      rank   = Rank.From(answer[2][0]);

            bus.HandleCardPosition(player, suit, rank);
            bus.HandleCardPlayed(player, suit, rank);
        }
Ejemplo n.º 3
0
        public static void HandleProtocolBid(string message, BridgeEventBus bus)
        {
            // North passes
            // North doubles
            // North redoubles
            // North bids 1H
            // North bids 1H Alert. 13 to 19 total points.
            // North bids 1H Alert.C=0-8,D=4-8,H=0-5,S=0-5,HCP=17-19,Total=19-21.
            // North bids 1H.Infos.C=0-8,D=4-8,H=0-5,S=0-5,HCP=17-19,Total=19-21.
            bool   bidWasAlerted = false;
            string bidPhrase;
            string alertPhrase = string.Empty;
            int    startAlert  = message.ToLower().IndexOf("alert.");

            if (startAlert == -1)
            {
                startAlert = message.ToLower().IndexOf("infos.");
            }
            if (startAlert >= 0)
            {
                bidWasAlerted = true;
                bidPhrase     = message.Substring(0, startAlert).Trim();
                //alertPhrase = Helpers.AlertFromTM(message.Substring(startAlert + 6).Trim());
                alertPhrase = message.Substring(startAlert + 6).Trim();
            }
            else
            {
                bidWasAlerted = false;
                bidPhrase     = message.Trim();
            }

            // 24-07-09: TableMoniteur adds a . after a bid: "North doubles."
            if (bidPhrase.EndsWith("."))
            {
                bidPhrase = bidPhrase.Substring(0, bidPhrase.Length - 1);
            }

            string[] answer = bidPhrase.Split(' ');
            Seats    bidder = SeatsExtensions.FromXML(answer[0]);
            var      bid    = new Bid(answer[answer.Length - 1], alertPhrase);

            if (bidWasAlerted)      // && alertPhrase.Length == 0)
            {
                bid.NeedsAlert();
            }

            bus.HandleBidDone(bidder, bid);
        }
        public async Task TableManagerHost_Test()
        {
            Log.Level         = 2;
            this.hostEventBus = new BridgeEventBus("TM_Host");
            var host = new TestHost(this.hostEventBus);

            host.OnHostEvent += Host_OnHostEvent;

            host.State = 1;
            SeatsExtensions.ForEachSeat((s) =>
            {
                var client = new TestClient(host);
                host.Seat(client, string.Format("Connecting \"{1}\" as {0} using protocol version 19", s, s.Direction()));
            });

            host.State = 3;
            await host.WaitForCompletionAsync();

            //host.ready.WaitOne();
            host.stopped = true;
        }
Ejemplo n.º 5
0
        private void ProcessMessage(string message)
        {
#if syncTrace
            Log.Trace(2, "Client {1} processing '{0}'", message, seat);
#endif

            if (message == "End of session" ||
                message.StartsWith("NS:")               // something new from Bridge Moniteur: session ends with
                )
            {
                this.EventBus.HandleTournamentStopped();
                return;
            }

            if (Expected(message))
            {
                try
                {
                    switch (this.state)
                    {
                    case TableManagerProtocolState.WaitForSeated:
                        this.HandleSeated();
                        this.ChangeState(TableManagerProtocolState.WaitForTeams, false, false, new string[] { "Teams" }, "{0} ready for teams", this.seat);
                        break;

                    case TableManagerProtocolState.WaitForTeams:
                        this.teamNS = message.Substring(message.IndexOf("N/S : \"") + 7);
                        this.teamNS = teamNS.Substring(0, teamNS.IndexOf("\""));
                        this.teamEW = message.Substring(message.IndexOf("E/W : \"") + 7);
                        this.teamEW = teamEW.Substring(0, teamEW.IndexOf("\""));
                        if (this.team != (this.seat.IsSameDirection(Seats.North) ? this.teamNS : this.teamEW))
                        {
                            throw new ArgumentOutOfRangeException("team", "Seated in another team");
                        }

                        this.HandleTeams(teamNS, teamEW);
                        this.ChangeState(TableManagerProtocolState.WaitForStartOfBoard, false, false, new string[] { "Start of board", "End of session" }, "{0} ready to start", this.seat);
                        break;

                    case TableManagerProtocolState.WaitForStartOfBoard:
                        if (message.StartsWith("Teams"))
                        {               // bug in BridgeMoniteur when tournament is restarted
                        }
                        else if (message.StartsWith("Timing"))
                        {
                            // Timing - N/S : this board [minutes:seconds], total [hours:minutes:seconds]. E/W : this board [minutes:seconds], total [hours:minutes:seconds]".
                            // Bridge Moniteur does not send the '.' at the end of the message
                            // Timing - N/S : this board  01:36,  total  0:01:36.  E/W : this board  01:34,  total  0:01:34
                            if (!message.EndsWith("."))
                            {
                                message += ".";
                            }
                            string[] timing  = message.Split('.');
                            string[] parts   = timing[0].Split(',');
                            string   boardNS = "00:" + parts[0].Substring(parts[0].IndexOf("board") + 6).Trim();
                            string   totalNS = parts[1].Substring(parts[1].IndexOf("total") + 6).Trim();
                            parts = timing[1].Split(',');
                            string boardEW = "00:" + parts[0].Substring(parts[0].IndexOf("board") + 6).Trim();
                            string totalEW = parts[1].Substring(parts[1].IndexOf("total") + 6).Trim();

                            TimeSpan _boardNS = ParseTimeUsed(boardNS);
                            TimeSpan _totalNS = ParseTimeUsed(totalNS);
                            TimeSpan _boardEW = ParseTimeUsed(boardEW);
                            TimeSpan _totalEW = ParseTimeUsed(totalEW);
                            this.EventBus.HandleTimeUsed(_boardNS, _totalNS, _boardEW, _totalEW);
                        }
                        else
                        {
                            this.ChangeState(TableManagerProtocolState.WaitForBoardInfo, false, false, new string[] { "Board number" }, "{0} ready for deal", this.seat);
                        }
                        break;

                    case TableManagerProtocolState.WaitForBoardInfo:
                        // "Board number 1. Dealer North. Neither vulnerable."
                        string[] dealInfoParts = message.Split('.');
                        int      boardNumber   = Convert.ToInt32(dealInfoParts[0].Substring(13));
                        this.theDealer = SeatsExtensions.FromXML(dealInfoParts[1].Substring(8));
                        Vulnerable vulnerability = Vulnerable.Neither;
                        switch (dealInfoParts[2].Substring(1))
                        {
                        case "Both vulnerable":
                            vulnerability = Vulnerable.Both; break;

                        case "N/S vulnerable":
                            vulnerability = Vulnerable.NS; break;

                        case "E/W vulnerable":
                            vulnerability = Vulnerable.EW; break;
                        }

                        var board = new Board2(this.theDealer, vulnerability, new Distribution());
                        this.CurrentResult = new TMBoardResult(this, board, new SeatCollection <string>(new string[] { this.teamNS, this.teamEW, this.teamNS, this.teamEW }));

                        this.EventBus.HandleBoardStarted(boardNumber, this.theDealer, vulnerability);
                        this.ChangeState(TableManagerProtocolState.WaitForMyCards, false, false, new string[] { this.seat + "'s cards : " }, "{0} ready for cards", this.seat);
                        break;

                    case TableManagerProtocolState.WaitForMyCards:
                        // "North's cards : S J 8 5.H A K T 8.D 7 6.C A K T 3."
                        // "North's cards : S J 8 5.H A K T 8.D.C A K T 7 6 3."
                        // "North's cards : S -.H A K T 8 4 3 2.D.C A K T 7 6 3."
                        string   cardInfo = message.Substring(2 + message.IndexOf(":"));
                        string[] suitInfo = cardInfo.Split('.');
                        for (int s1 = 0; s1 < 4; s1++)
                        {
                            suitInfo[s1] = suitInfo[s1].Trim();
                            Suits s = SuitHelper.FromXML(suitInfo[s1].Substring(0, 1));
                            if (suitInfo[s1].Length > 2)
                            {
                                string cardsInSuit = suitInfo[s1].Substring(2) + " ";
                                if (cardsInSuit.Substring(0, 1) != "-")
                                {
                                    while (cardsInSuit.Length > 1)
                                    {
                                        Ranks rank = Rank.From(cardsInSuit.Substring(0, 1));
                                        this.EventBus.HandleCardPosition(this.seat, s, rank);
                                        cardsInSuit = cardsInSuit.Substring(2);
                                    }
                                }
                            }
                        }

                        //this.EventBus.WaitForEventCompletion();
                        // TM is now expecting a response: either a bid or a 'ready for bid'
                        this.EventBus.HandleCardDealingEnded();

                        break;

                    case TableManagerProtocolState.WaitForOtherBid:
                        if (message.StartsWith("Explain "))
                        {
                            message = message.Substring(8);
                            string[] answer = message.Split(' ');
                            Seats    bidder = SeatsExtensions.FromXML(answer[0]);
                            var      bid    = new Bid(answer[answer.Length - 1], "");

                            this.EventBus.HandleExplanationNeeded(bidder, bid);
                        }
                        else
                        {
                            this.WaitForBridgeEvents = true;
                            ProtocolHelper.HandleProtocolBid(message, this.EventBus);
                        }

                        break;

                    case TableManagerProtocolState.WaitForDummiesCards:
                        //Log.Trace("Client {1} processing dummies cards", message, seat);
                        string   dummiesCards = message.Substring(2 + message.IndexOf(":"));
                        string[] suitInfo2    = dummiesCards.Split('.');
                        for (Suits s = Suits.Spades; s >= Suits.Clubs; s--)
                        {
                            int suit = 3 - (int)s;
                            suitInfo2[suit] = suitInfo2[suit].Trim();
                            if (suitInfo2[suit].Length > 2)
                            {
                                string cardsInSuit = suitInfo2[suit].Substring(2) + " ";
                                if (cardsInSuit.Substring(0, 1) != "-")
                                {
                                    while (cardsInSuit.Length > 1)
                                    {
                                        Ranks rank = Rank.From(cardsInSuit.Substring(0, 1));
                                        this.EventBus.HandleCardPosition(this.CurrentResult.Play.Dummy, s, rank);
                                        cardsInSuit = cardsInSuit.Substring(2);
                                    }
                                }
                            }
                        }

                        this.WaitForProtocolSync = false;
                        this.EventBus.HandleShowDummy(this.CurrentResult.Play.Dummy);
                        break;

                    case TableManagerProtocolState.WaitForLead:
                        this.WaitForProtocolSync = false;
                        break;

                    case TableManagerProtocolState.WaitForCardPlay:
                        if (message.Contains("to lead"))
                        {
                            /// This indicates a timing issue: TM sent a '... to lead' message before TD sent its HandleTrickFinished event
                            /// Wait until I receveive the HandleTrickFinished event
                            Log.Trace(1, "TableManagerClient.ProcessMessage {0}: received 'to lead' before HandleTrickFinished", this.seat);
                            //Debugger.Break();
                        }
                        else
                        {
                            string[] cardPlay = message.Split(' ');
                            Seats    player   = SeatsExtensions.FromXML(cardPlay[0]);
                            Card     card     = new Card(SuitHelper.FromXML(cardPlay[2].Substring(1, 1)), Rank.From(cardPlay[2].Substring(0, 1)));
                            if (player != this.CurrentResult.Play.Dummy)
                            {
                                this.EventBus.HandleCardPosition(player, card.Suit, card.Rank);
                            }
                            this.WaitForBridgeEvents = true;
                            this.EventBus.HandleCardPlayed(player, card.Suit, card.Rank);
                        }

                        break;

                    case TableManagerProtocolState.WaitForDisconnect:
                        this.state = TableManagerProtocolState.Finished;
                        this.EventBus.HandleTournamentStopped();
                        break;
                    }
                }
                catch (Exception ex)
                {
                    Log.Trace(0, "Error while processing message '{0}' in state {1}: {2}", message, state, ex.ToString());
                    throw;
                }
            }
            else
            {           // unexpected message
            }
        }
            public void Verify(int state, string message)
            {
                //Log.Trace(1, "Host sends {1} {0}", message, seat);
                switch (state)
                {
                case 1:
                    if (message.Contains("seated"))
                    {
                        this.ProcessIncomingMessage("{0} ready for teams", this.seat);
                        return;
                    }
                    else if (message == "Illegal hand specified")
                    {
                        return;
                    }
                    break;

                case 2:
                    if (message == "Expected team name 'NorthSouth'")
                    {
                        return;
                    }
                    break;

                case 4:
                    if (message == "Seat already has been taken")
                    {
                        return;
                    }
                    break;

                case 3:
                    if (message.Contains("Teams : N/S : \""))
                    {
                        this.ProcessIncomingMessage("{0} ready to start", this.seat);
                        return;
                    }

                    if (message.Contains("Start of board"))
                    {
                        this.ProcessIncomingMessage("{0} ready for deal", this.seat);
                        return;
                    }

                    if (message.Contains("Board number "))
                    {
                        this.ProcessIncomingMessage("{0} ready for cards", this.seat);
                        return;
                    }

                    if (message.Contains("'s cards : "))
                    {
                        var whoseTurn = Seats.North;
                        if (this.seat == whoseTurn)
                        {
                            this.ProcessIncomingMessage("North bids 1H");
                            this.ProcessIncomingMessage("{0} ready for {1}'s bid", this.seat, whoseTurn.Next().ToString().PadLeft(5).ToUpper());
                        }
                        else
                        {
                            this.ProcessIncomingMessage("{0} ready for {1}'s bid", this.seat, whoseTurn);
                        }

                        this.passCount = 0;
                        return;
                    }

                    if (message.Contains("Explain "))
                    {
                        this.ProcessIncomingMessage("C5*D5");
                        return;
                    }

                    if (message.Contains(" bids ") || message.Contains(" passes"))
                    {
                        var parts = message.Split(' ');
                        if (parts[1] == "passes")
                        {
                            this.passCount++;
                        }
                        else
                        {
                            this.passCount = 0;
                        }
                        if (passCount == 3)
                        {
                            (this.host as TestHost).Abort();
                        }
                        else
                        {
                            var whoseBid  = SeatsExtensions.FromXML(parts[0].Substring(0, 1));
                            var whoseTurn = whoseBid.Next();
                            if (this.seat == whoseTurn)
                            {
                                Bid newBid;
                                if (message.Contains(" bids 1H"))
                                {
                                    newBid = Bid.C("2NT");
                                }
                                else
                                {
                                    newBid = Bid.C("p");
                                    this.passCount++;
                                }

                                this.ProcessIncomingMessage("{0} bids {1}", this.seat, newBid.ToXML());
                                if (this.passCount < 3)
                                {
                                    this.ProcessIncomingMessage("{0} ready for {1}'s bid", this.seat, whoseTurn.Next());
                                }
                            }
                            else
                            {
                                this.ProcessIncomingMessage("{0} ready for {1}'s bid", this.seat, whoseTurn);
                            }
                        }

                        return;
                    }

                    if (message.Contains(" to lead"))
                    {
                        return;
                    }

                    break;

                default:
                    break;
                }

                (this.host as TestHost).Abort();
                Assert.Fail();
            }
Ejemplo n.º 7
0
        public void Seat(ClientData client, string message)
        {
            if (message.ToLowerInvariant().Contains("connecting") && message.ToLowerInvariant().Contains("using protocol version"))
            {
#if syncTrace
                Log.Trace(2, "{1} processing '{0}'", message, this.Name);
#endif
                var hand = message.Substring(message.IndexOf(" as ") + 4, 5).Trim().ToLowerInvariant();
                if (hand == "north" || hand == "east" || hand == "south" || hand == "west")
                {
                    client.seat = SeatsExtensions.FromXML(hand.Substring(0, 1).ToUpperInvariant());
                    if (this.clients[client.seat] == null)
                    {
                        int p        = message.IndexOf("\"");
                        var teamName = message.Substring(p + 1, message.IndexOf("\"", p + 1) - (p + 1));
                        client.teamName = teamName;
                        client.hand     = client.seat.ToString();  //.Substring(0, 1)
                        var protocolVersion = int.Parse(message.Substring(message.IndexOf(" version ") + 9));
                        switch (protocolVersion)
                        {
                        case 18:
                            client.PauseBeforeSending   = true;
                            client.CanAskForExplanation = false;
                            break;

                        case 19:
                            client.PauseBeforeSending   = false;
                            client.CanAskForExplanation = true;
                            break;

                        default:
                            throw new ArgumentOutOfRangeException("protocolVersion", protocolVersion + " not supported");
                        }

                        var partner         = client.seat.Partner();
                        var partnerTeamName = teamName;
                        if (this.clients[partner] != null)
                        {
                            if (this.clients[partner].teamName == null)
                            {
                                this.clients[partner].teamName = teamName;
                            }
                            else
                            {
                                partnerTeamName = this.clients[partner].teamName;
                            }
                        }

                        if (teamName == partnerTeamName)
                        {
                            client.state              = TableManagerProtocolState.WaitForSeated;
                            client.seatTaken          = true;
                            this.clients[client.seat] = client;
                            client.WriteData("{1} (\"{0}\") seated", client.teamName, client.hand);
                            this.OnHostEvent(this, HostEvents.Seated, client.seat + "|" + teamName);
                        }
                        else
                        {
                            client.Refuse("Expected team name '{0}'", partnerTeamName);
                        }
                    }
                    else
                    {
                        client.Refuse("Seat already has been taken");
                    }
                }
                else
                {
                    client.Refuse("Illegal hand specified");
                }
            }
            else
            {
                client.Refuse("Expected 'Connecting ....'");
            }
        }