package pokercore import ( "fmt" "slices" "sort" "strings" "unicode/utf8" "github.com/logrusorgru/aurora/v4" ) type Card struct { Rank Rank Suit Suit } func NewCardFromString(card string) (Card, error) { // FIXME extend this later to common format strings like "9s" length := utf8.RuneCountInString(card) if length != 2 { return Card{}, fmt.Errorf("Invalid card string %s", card) } var rank Rank var suit Suit if strings.ContainsRune(card, rune(SPADE)) { suit = Suit(SPADE) } else if strings.ContainsRune(card, rune(HEART)) { suit = Suit(HEART) } else if strings.ContainsRune(card, rune(DIAMOND)) { suit = Suit(DIAMOND) } else if strings.ContainsRune(card, rune(CLUB)) { suit = Suit(CLUB) } else { return Card{}, fmt.Errorf("Invalid card string %s", card) } if strings.ContainsRune(card, rune(DEUCE)) { rank = Rank(DEUCE) } else if strings.ContainsRune(card, rune(THREE)) { rank = Rank(THREE) } else if strings.ContainsRune(card, rune(FOUR)) { rank = Rank(FOUR) } else if strings.ContainsRune(card, rune(FIVE)) { rank = Rank(FIVE) } else if strings.ContainsRune(card, rune(SIX)) { rank = Rank(SIX) } else if strings.ContainsRune(card, rune(SEVEN)) { rank = Rank(SEVEN) } else if strings.ContainsRune(card, rune(EIGHT)) { rank = Rank(EIGHT) } else if strings.ContainsRune(card, rune(NINE)) { rank = Rank(NINE) } else if strings.ContainsRune(card, rune(TEN)) { rank = Rank(TEN) } else if strings.ContainsRune(card, rune(JACK)) { rank = Rank(JACK) } else if strings.ContainsRune(card, rune(QUEEN)) { rank = Rank(QUEEN) } else if strings.ContainsRune(card, rune(KING)) { rank = Rank(KING) } else if strings.ContainsRune(card, rune(ACE)) { rank = Rank(ACE) } else { return Card{}, fmt.Errorf("Invalid card string %s", card) } if rank == Rank(0) || suit == Suit(0) { return Card{}, fmt.Errorf("Invalid card string %s", card) } return Card{Rank: rank, Suit: suit}, nil } func NewCardsFromString(cards string) (Cards, error) { // supports a string like 9♠,9♣,Q♥,Q♦,K♣ // FIXME extend this later to common format strings like "9c Qh Qd Kc" // with or without commas var newCards Cards newCards = make(Cards, 0) cardStrings := strings.Split(cards, ",") for _, cardString := range cardStrings { card, err := NewCardFromString(cardString) if err != nil { return Cards{}, err } newCards = append(newCards, card) } if len(newCards) == 0 { return Cards{}, fmt.Errorf("No cards found in string %s", cards) } return newCards, nil } func (c *Card) String() string { return fmt.Sprintf("%s%s", string(c.Rank), string(c.Suit)) } type Cards []Card func (c Cards) First() Card { return c[0] } func (c Cards) Second() Card { return c[1] } func (c Cards) Third() Card { return c[2] } func (c Cards) Fourth() Card { return c[3] } func (c Cards) Fifth() Card { return c[4] } func (c Cards) Last() Card { return c[len(c)-1] } func (c Cards) SortByRankAscending() Cards { newCards := make(Cards, len(c)) copy(newCards, c) sort.Slice(newCards, func(i, j int) bool { return newCards[i].Rank.Score() < newCards[j].Rank.Score() }) return newCards } func (c Cards) PrintToTerminal() { fmt.Printf("%s", c.FormatForTerminal()) } type SortOrder int const ( AceHighAscending SortOrder = iota AceHighDescending ) func (c Cards) FormatForTerminalSorted(order SortOrder) string { sorted := c.SortByRankAscending() // this is ascending if order == AceHighDescending { slices.Reverse(sorted) } return sorted.FormatForTerminal() } func (c Cards) FormatForTerminal() string { var cardstrings []string for i := 0; i < len(c); i++ { cardstrings = append(cardstrings, c[i].FormatForTerminal()) } return strings.Join(cardstrings, ",") } func (c Card) FormatForTerminal() string { var rank string var suit string color := aurora.Red switch c.Suit { case Suit(DIAMOND): color = aurora.Blue case Suit(HEART): color = aurora.Red case Suit(CLUB): color = aurora.Green case Suit(SPADE): color = aurora.Black } rank = fmt.Sprintf("%s", aurora.Bold(color(c.Rank.Symbol()))) suit = fmt.Sprintf("%s", aurora.Bold(color(c.Suit.Symbol()))) return fmt.Sprintf("%s%s", rank, suit) } func (c Cards) HighestRank() Rank { sorted := c.SortByRankAscending() return sorted[len(sorted)-1].Rank } func (s Cards) String() (output string) { var cardstrings []string for i := 0; i < len(s); i++ { cardstrings = append(cardstrings, s[i].String()) } output = strings.Join(cardstrings, ",") return output }