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); }
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); }
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(); }
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 ....'"); } }