type Deck interface { Discard(cards ...*Card) Pop() *Card PopMulti(n int) []*Card Reset()}
type Table struct { Deck Deck `json:"deck"`}
type Deck interface { Discard(cards ...*Card) Pop() *Card PopMulti(n int) []*Card Reset()
// added to support deserialization
Cards() []*Card Discards() []*Card FromCards(cards, discards []*Card) Deck}
// register the implemenation
func RegisterDeck(d Deck) { registeredDeck = d}
var ( registeredDeck Deck)
type Table struct { Deck Deck `json:"deck"`}
type tableJSON struct {
Cards []*Card
Discards []*Card
}
func (t *Table) MarshalJSON() ([]byte, error) {
tJSON := &tableJSON{ Cards: t.Deck.Cards(), Discards: t.Deck.Discards(), } return json.Marshal(tJSON)}
func (t *Table) UnmarshalJSON(b []byte) error {
tJSON := &tableJSON{} if err := json.Unmarshal(b, tJSON); err != nil { return err } t.Deck = registeredDeck.FromCards(tJSON.Cards, tJSON.Discards) return nil
}I am writing logic for a poker engine to deal and manage table state. I have to support JSON serialization and deserialization because I intent to communicate the state of the table over the wire. I am having an issue deserializing the Deck interface because it doesn't "remember" the concrete type to use (serialization doesn't have any issues). Also I need Deck to be an interface so my tests can use prearranged decks.
On Sunday, 30 November 2014 17:35:00 UTC+2, lo...@syntropy.io wrote:I am writing logic for a poker engine to deal and manage table state. I have to support JSON serialization and deserialization because I intent to communicate the state of the table over the wire. I am having an issue deserializing the Deck interface because it doesn't "remember" the concrete type to use (serialization doesn't have any issues). Also I need Deck to be an interface so my tests can use prearranged decks.Make Deck a concrete type i.e. add some constructor that allows for specifying the card order. I suspect a lot of code will get simpler from this change.
type Deck []*CardI actually had:type Deck []*Cardpreviously, but I needed to keep track of discards. Draw games require managing discards because if no more cards are available they are shuffled and put back into the deck.
// Player represents a player at a table.type Player interface { ID() string FromID(id string) (Player, error) Action() (a Action, chips int)}
/ RegisterPlayer stores the player implementation for json deserialization.func RegisterPlayer(p Player) { registeredPlayer = p}
var ( // mapping to player implemenation registeredPlayer Player)
// PlayerState is the state of a player at a table.type PlayerState struct { player Player}
type playerStateJSON struct { ID string `json:"id"`}
// MarshalJSON implements the json.Marshaler interface.func (state *PlayerState) MarshalJSON() ([]byte, error) { tpJSON := &playerStateJSON{ ID: state.Player().ID(), } return json.Marshal(tpJSON)}
// UnmarshalJSON implements the json.Unmarshaler interface.func (state *PlayerState) UnmarshalJSON(b []byte) error { tpJSON := &playerStateJSON{} if err := json.Unmarshal(b, tpJSON); err != nil { return err }
p, err := registeredPlayer.FromID(tpJSON.ID) if err != nil { return fmt.Errorf("table PlayerState json deserialization failed because of player %s FromID - %s", tpJSON.ID, err) }
state.player = p return nil}