joker/card.go

138 lines
2.6 KiB
Go

package cards
import (
"encoding/json"
"fmt"
"strings"
)
// Invalid is the text shown when a valid face or suit is not found.
const Invalid = "?"
// Card defines a playing card with a face and suit.
type Card struct {
Face CardFace
Suit CardSuit
}
// Value returns the numeric value of a card.
func (c Card) Value() int {
return (int(c.Face) * 100) + int(c.Suit)
}
// Equal returns whether both cards have the same face and suit.
func (c Card) Equal(b Card) bool {
return b.Face == c.Face && b.Suit == c.Suit
}
// Identifier returns a machine-readable representation of a card.
func (c Card) Identifier() string {
if c.Suit.Name() == Invalid || c.Suit.Name() == Invalid {
return "??"
}
var faceidentifier string
if c.Face == FaceJoker {
faceidentifier = "!"
} else if c.Face == Face10 {
faceidentifier = c.Face.Name()
} else {
faceidentifier = string(c.Face.Name()[0])
}
var suitidentifier string
if c.Suit == SuitJoker {
suitidentifier = "!"
} else {
suitidentifier = c.Suit.Name()[0:1]
}
return strings.ToUpper(faceidentifier + suitidentifier)
}
// String returns a human-readable representation of a Card.
func (c Card) String() string {
var cardFace string
if c.Face == 14 {
cardFace = "! "
} else {
cardFace = c.Face.Name()[0:1]
if c.Face == 10 {
cardFace += "0"
} else {
cardFace += " "
}
}
return fmt.Sprintf("[%s %s %c]", cardFace, c.Suit.Symbol(), c.Suit.Name()[0])
}
// MarshalJSON marshals a Card.
func (c Card) MarshalJSON() ([]byte, error) {
return json.Marshal(c.Identifier())
}
// UnmarshalJSON unmarshals a Card.
func (c *Card) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
if sLen := len(s); sLen < 2 || sLen > 3 {
return fmt.Errorf("invalid card identifier: %s", s)
}
var cardFace CardFace
switch s[:len(s)-1] {
case "A":
cardFace = FaceAce
case "2":
cardFace = Face2
case "3":
cardFace = Face3
case "4":
cardFace = Face4
case "5":
cardFace = Face5
case "6":
cardFace = Face6
case "7":
cardFace = Face7
case "8":
cardFace = Face8
case "9":
cardFace = Face9
case "10":
cardFace = Face10
case "J":
cardFace = FaceJack
case "Q":
cardFace = FaceQueen
case "K":
cardFace = FaceKing
case "!":
cardFace = FaceJoker
default:
return fmt.Errorf("invalid face identifier %s", s)
}
var cardSuit CardSuit
switch s[len(s)-1:] {
case "H":
cardSuit = SuitHearts
case "D":
cardSuit = SuitDiamonds
case "C":
cardSuit = SuitClubs
case "S":
cardSuit = SuitSpades
case "!":
cardSuit = SuitJoker
default:
return fmt.Errorf("invalid suit identifier %s", s)
}
*c = Card{cardFace, cardSuit}
return nil
}