private void _SendToBase(CardReader reader, PlayerCard card)
        {
            var availableStation = _GetAvailableStations(card.BaseNumber).FirstOrDefault();

            if (availableStation != null)
            {
                Console.WriteLine($"Sending to base {card.BaseNumber + 1}");
                Console.WriteLine("Awaiting card write...");
                reader.Write(CardData.Create(card.ToStringNoUser()));
                var socket = _stationIds[availableStation];
                socket.SendData(card.ToString());
                _incomingCards.Remove(card);
                _takenStations.Add(availableStation);
                _cardsInSystem.Add(card.PlayerID);
                Console.WriteLine($"SEND PLAYER TO STATION {card.BaseNumber}", Color.HotPink);
                Console.WriteLine(DASHES, Color.Green);

                Console.WriteLine($"\n{DASHES}", Color.Gray);
                Console.WriteLine($"Sent {card.Printable()}", Color.Gray);
                Console.WriteLine(DASHES, Color.Gray);
            }
            else
            {
                Console.WriteLine("No available stations at this point. Please check back later", Color.Red);
            }
        }
        private PlayerCard _FormatCard(CardReader reader)
        {
            Console.WriteLine(DASHES, Color.Yellow);
            Console.WriteLine("Formatting card");
            var card = PlayerCard.Default;

            reader.Write(CardData.Create(card.ToString()));
            Console.WriteLine("Card successfully formatted", Color.Green);
            Console.WriteLine(DASHES, Color.Yellow);
            return(card);
        }
        private void _ChoseCardDestination(CardReader reader, PlayerCard card, Action sentAction)
        {
            var baseNumber = CLH.PromptNumber("What station should I send this player to? (0 to ignore)", 0, PlayerCard.MAX_BASE_NUMBER + 1);

            if (baseNumber > 0)
            {
                card.BaseNumber = baseNumber - 1;
                sentAction();
                _SendToBase(reader, card);
            }
        }
        private void _HandleCardSwipe(CardReader reader)
        {
            bool retry = true;

            while (retry)
            {
                _ProcessCard(reader).Match(
                    Ok: () => retry = false,
                    Err: () => Console.WriteLine("Retrying..."));
            }
        }
 private void _CardEnterMode()
 {
     using (var reader = new CardReader())
     {
         if (reader.Connect())
         {
             reader.Reset();
             while (true)
             {
                 _HandleCardSwipe(reader);
             }
         }
         else
         {
             Console.WriteLine("Failed to connect to card reader!", Color.Red);
         }
     }
 }
 private void _FormattingMode()
 {
     using (var reader = new CardReader())
     {
         if (reader.Connect())
         {
             reader.Reset();
             int counter = 0;
             while (true)
             {
                 _FormatCard(reader);
                 Console.WriteLine($"Formatted {++counter} cards");
             }
         }
         else
         {
             Console.WriteLine("Failed to connect to card reader!", Color.Red);
         }
     }
 }
        private Result _ProcessCard(CardReader reader)
        {
            #region Helper Methods
            Result <PlayerCard> isValidCard(string data)
            {
                var pc = new PlayerCard(data);

                return(pc.IsValid()
                    ? Result.Ok(pc)
                    : Result.Fail <PlayerCard>("Card not setup correctly!"));
            }

            Result <PlayerCard> formatCard(Result <PlayerCard> error)
            => CLH.PromptYesNo($"Error reading card data: {error.Error} Format?",
                               () => Result.Ok(_FormatCard(reader)),
                               () => error);

            Result <PlayerCard> getExistingCard(PlayerCard card)
            => _incomingCards.Contains(card)
                    ? Result.Ok(_incomingCards.Find(x => x.Equals(card)))
                    : Result.Fail <PlayerCard>($"No incoming cards with this player ID: {card.PlayerID}");

            Action <PlayerCard> handleExistingCard(PlayerCard currentCard)
            => existingCard =>
            {
                Console.WriteLine($"Found an incoming card: {existingCard}", Color.Green);
                if (existingCard.BaseNumber <= PlayerCard.MAX_BASE_NUMBER)
                {
                    _SendToBase(reader, existingCard);
                }
                else
                {
                    Console.WriteLine("Reached last base...");
                    _ChoseCardDestination(reader, currentCard, () => { });
                }
            };

            void handleNewCard(PlayerCard card, string msg, Action sentAction)
            {
                Console.WriteLine(msg);
                _ChoseCardDestination(reader, card, sentAction);
            };
            #endregion Helper Methods

            Console.WriteLine($"\n{DASHES}", Color.Green);
            Console.WriteLine("Waiting for card swipe...");
            return(reader.Read().GetReadableData()
                   .OnSuccess(isValidCard)
                   .OnFailure(formatCard)
                   .OnSuccess(card =>
                              getExistingCard(card).Match(
                                  Ok: handleExistingCard(card),
                                  Err: (err) =>
            {
                if (_cardsInSystem.Contains(card.PlayerID))
                {
                    handleNewCard(card, "This card appears to already be in the system!",
                                  () => _cardsInSystem.Remove(card.PlayerID));
                }
                else
                {
                    handleNewCard(card, err, () => { });
                }
            })));
        }