little progress
This commit is contained in:
parent
c2dfd09e9f
commit
f0a7b23efb
3
Makefile
3
Makefile
|
@ -6,3 +6,6 @@ test: *.go
|
||||||
|
|
||||||
run:
|
run:
|
||||||
cd cmd/* && go get -v && go build .
|
cd cmd/* && go get -v && go build .
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
go fmt *.go
|
||||||
|
|
42
card.go
42
card.go
|
@ -1,11 +1,8 @@
|
||||||
package poker
|
package poker
|
||||||
|
|
||||||
import "encoding/binary"
|
|
||||||
import "fmt"
|
|
||||||
import crand "crypto/rand"
|
|
||||||
import . "github.com/logrusorgru/aurora"
|
import . "github.com/logrusorgru/aurora"
|
||||||
import log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
type Suit rune
|
type Suit rune
|
||||||
|
@ -41,6 +38,30 @@ type Card struct {
|
||||||
|
|
||||||
type Cards []*Card
|
type Cards []*Card
|
||||||
|
|
||||||
|
func NewCardsFromString(input string) (*Cards, error) {
|
||||||
|
c := make(Cards, 0)
|
||||||
|
sl := strings.Split(input, ",")
|
||||||
|
for _, pc := range sl {
|
||||||
|
newCard, err := NewCardFromString(pc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c = append(c, newCard)
|
||||||
|
}
|
||||||
|
return &c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCardFromString(input string) (*Card, error) {
|
||||||
|
if len(input) != 2 {
|
||||||
|
return nil, fmt.Errorf("invalid card string: '%s'", input)
|
||||||
|
}
|
||||||
|
nc := new(Card)
|
||||||
|
pr := input[0:1]
|
||||||
|
ps := input[1:2]
|
||||||
|
panic(fmt.Sprintf("pr=%s ps=%s nc=%s\n", pr, ps, nc))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cards) formatForTerminal() (output string) {
|
func (c *Cards) formatForTerminal() (output string) {
|
||||||
var cardstrings []string
|
var cardstrings []string
|
||||||
for _, card := range *c {
|
for _, card := range *c {
|
||||||
|
@ -65,21 +86,12 @@ func (c *Card) formatForTerminal() (output string) {
|
||||||
color = Black
|
color = Black
|
||||||
}
|
}
|
||||||
|
|
||||||
rank = fmt.Sprintf("%s", BgGray(Bold(color(*c.Rank))))
|
rank = fmt.Sprintf("%s", BgGray(12, Bold(color(c.Rank))))
|
||||||
suit = fmt.Sprintf("%s", BgGray(Bold(color(*c.Suit))))
|
suit = fmt.Sprintf("%s", BgGray(12, Bold(color(c.Suit))))
|
||||||
output = fmt.Sprintf("%s%s", rank, suit)
|
output = fmt.Sprintf("%s%s", rank, suit)
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func cryptoUint64() (v uint64) {
|
|
||||||
err := binary.Read(crand.Reader, binary.BigEndian, &v)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
log.Debugf("crand cryptosource is returning Uint64: %d", v)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *Card) String() string {
|
func (self *Card) String() string {
|
||||||
return fmt.Sprintf("%s%s", string(self.Rank), string(self.Suit))
|
return fmt.Sprintf("%s%s", string(self.Rank), string(self.Suit))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/sneak/poker"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/rpc"
|
|
||||||
"net/rpc/jsonrpc"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type JSONRPCServer struct {
|
|
||||||
*rpc.Server
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewJSONRPCServer() *JSONRPCServer {
|
|
||||||
return &JSONRPCServer{rpc.NewServer()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *JSONRPCServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|
||||||
log.Println("rpc server got a request")
|
|
||||||
conn, _, err := w.(http.Hijacker).Hijack()
|
|
||||||
if err != nil {
|
|
||||||
log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
io.WriteString(conn, "HTTP/1.0 200 Connected to Go JSON-RPC\n\n")
|
|
||||||
codec := jsonrpc.NewServerCodec(conn)
|
|
||||||
log.Println("ServeCodec")
|
|
||||||
s.Server.ServeCodec(codec)
|
|
||||||
log.Println("finished serving request")
|
|
||||||
}
|
|
||||||
|
|
||||||
type Args struct {
|
|
||||||
A, B int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Quotient struct {
|
|
||||||
Quo, Rem int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Arith int
|
|
||||||
|
|
||||||
func (t *Arith) Multiply(args *Args, reply *int) error {
|
|
||||||
*reply = args.A * args.B
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Arith) Divide(args *Args, quo *Quotient) error {
|
|
||||||
if args.B == 0 {
|
|
||||||
return errors.New("divide by zero")
|
|
||||||
}
|
|
||||||
quo.Quo = args.A / args.B
|
|
||||||
quo.Rem = args.A % args.B
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
//log.SetFormatter(&log.JSONFormatter{})
|
|
||||||
|
|
||||||
// Output to stdout instead of the default stderr
|
|
||||||
// Can be any io.Writer, see below for File example
|
|
||||||
log.SetOutput(os.Stdout)
|
|
||||||
|
|
||||||
// Only log the warning severity or above.
|
|
||||||
//log.SetLevel(log.WarnLevel)
|
|
||||||
|
|
||||||
log.Infof("starting up")
|
|
||||||
|
|
||||||
go runHttpServer()
|
|
||||||
|
|
||||||
running := true
|
|
||||||
|
|
||||||
for running {
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runHttpServer() {
|
|
||||||
js := NewJSONRPCServer()
|
|
||||||
arith := new(Arith)
|
|
||||||
js.Register(arith)
|
|
||||||
|
|
||||||
port := 8080
|
|
||||||
|
|
||||||
listenaddr := fmt.Sprintf("0.0.0.0:%d", port)
|
|
||||||
|
|
||||||
s := &http.Server{
|
|
||||||
Addr: listenaddr,
|
|
||||||
Handler: js,
|
|
||||||
ReadTimeout: 10 * time.Second,
|
|
||||||
WriteTimeout: 10 * time.Second,
|
|
||||||
MaxHeaderBytes: 1 << 20,
|
|
||||||
}
|
|
||||||
log.Infof("starting up http server %s", listenaddr)
|
|
||||||
log.Fatal(s.ListenAndServe())
|
|
||||||
}
|
|
9
deck.go
9
deck.go
|
@ -1,14 +1,10 @@
|
||||||
package poker
|
package poker
|
||||||
|
|
||||||
import "encoding/binary"
|
import "encoding/binary"
|
||||||
import "fmt"
|
|
||||||
import crand "crypto/rand"
|
import crand "crypto/rand"
|
||||||
import . "github.com/logrusorgru/aurora"
|
|
||||||
import log "github.com/sirupsen/logrus"
|
import log "github.com/sirupsen/logrus"
|
||||||
import rand "math/rand"
|
import rand "math/rand"
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
type Deck struct {
|
type Deck struct {
|
||||||
Cards Cards
|
Cards Cards
|
||||||
DealIndex int
|
DealIndex int
|
||||||
|
@ -28,16 +24,17 @@ func NewShuffledDeck() *Deck {
|
||||||
d := newDeck()
|
d := newDeck()
|
||||||
d.ShuffleSeedVal = int64(cryptoUint64())
|
d.ShuffleSeedVal = int64(cryptoUint64())
|
||||||
d.Shuffle()
|
d.Shuffle()
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeckFromSeed(seed int64) *Deck {
|
func NewDeckFromSeed(seed int64) *Deck {
|
||||||
d := newDeck()
|
d := newDeck()
|
||||||
d.ShuffleSeedVal = seed
|
d.ShuffleSeedVal = seed
|
||||||
d.Shuffle()
|
d.Shuffle()
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDeck() *Deck {
|
func newDeck() *Deck {
|
||||||
|
|
||||||
self := new(Deck)
|
self := new(Deck)
|
||||||
|
|
||||||
ranks := []Rank{
|
ranks := []Rank{
|
||||||
|
@ -65,7 +62,7 @@ func newDeck() *Deck {
|
||||||
|
|
||||||
func (self *Deck) Shuffle() {
|
func (self *Deck) Shuffle() {
|
||||||
//FIXME(sneak) not sure if this is constant time or not
|
//FIXME(sneak) not sure if this is constant time or not
|
||||||
rnd := rand.New(rand.NewSource(self.ShuffleSeedVal)))
|
rnd := rand.New(rand.NewSource(self.ShuffleSeedVal))
|
||||||
rnd.Shuffle(len(self.Cards), func(i, j int) { self.Cards[i], self.Cards[j] = self.Cards[j], self.Cards[i] })
|
rnd.Shuffle(len(self.Cards), func(i, j int) { self.Cards[i], self.Cards[j] = self.Cards[j], self.Cards[i] })
|
||||||
self.DealIndex = 0
|
self.DealIndex = 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,19 +9,17 @@ type ShuffleTestResults []struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPokerDeck(t *testing.T) {
|
func TestPokerDeck(t *testing.T) {
|
||||||
d := NewDeck()
|
d := NewDeckFromSeed(437)
|
||||||
d.ShuffleDeterministically(437)
|
|
||||||
cards := d.Deal(7)
|
cards := d.Deal(7)
|
||||||
//expected := "7C,5S,QS,2D,6D,QC,3H"
|
|
||||||
expected := "7♣,5♠,Q♠,2♦,6♦,Q♣,3♥"
|
expected := "7♣,5♠,Q♠,2♦,6♦,Q♣,3♥"
|
||||||
assert.Equal(t, cards.String(), expected)
|
assert.Equal(t, cards.String(), expected)
|
||||||
|
|
||||||
x := d.Remaining()
|
x := d.Remaining()
|
||||||
assert.Equal(t, 45, x)
|
assert.Equal(t, 45, x)
|
||||||
|
|
||||||
d.ShuffleDeterministically(123456789)
|
d = NewDeckFromSeed(123456789)
|
||||||
cards = d.Deal(10)
|
cards = d.Deal(10)
|
||||||
expected = "2♣,T♠,4♥,Q♣,9♦,7♥,7♠,6♥,5♥,5♠"
|
expected = "5♥,4♥,5♠,2♣,6♦,6♣,3♦,Q♠,8♥,A♣"
|
||||||
assert.Equal(t, expected, cards.String())
|
assert.Equal(t, expected, cards.String())
|
||||||
x = d.Remaining()
|
x = d.Remaining()
|
||||||
assert.Equal(t, 42, x)
|
assert.Equal(t, 42, x)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
module github.com/sneak/poker
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/logrusorgru/aurora v0.0.0-20191116043053-66b7ad493a23
|
||||||
|
github.com/sirupsen/logrus v1.4.2
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
|
)
|
|
@ -0,0 +1,21 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/logrusorgru/aurora v0.0.0-20191116043053-66b7ad493a23 h1:Wp7NjqGKGN9te9N/rvXYRhlVcrulGdxnz8zadXWs7fc=
|
||||||
|
github.com/logrusorgru/aurora v0.0.0-20191116043053-66b7ad493a23/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
51
hand.go
51
hand.go
|
@ -1,7 +1,12 @@
|
||||||
package poker
|
package poker
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
type HEPokerHand struct {
|
type HEPokerHand struct {
|
||||||
Cards Cards
|
HoleCards Cards
|
||||||
|
CommCardsNotUsed Cards
|
||||||
|
CommCardsUsed Cards
|
||||||
|
CommCardsAll Cards
|
||||||
HandScore HandScore
|
HandScore HandScore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +15,8 @@ type HandScoreRanking Rank
|
||||||
|
|
||||||
type HandScore struct {
|
type HandScore struct {
|
||||||
Type HandScoreType
|
Type HandScoreType
|
||||||
Ranking HandScoreRanking
|
PrimaryRanking HandScoreRanking
|
||||||
|
SecondaryRanking HandScoreRanking
|
||||||
Kickers Cards
|
Kickers Cards
|
||||||
Description string
|
Description string
|
||||||
}
|
}
|
||||||
|
@ -31,40 +37,47 @@ func (self *HandScore) BeatsHand(v *HandScore) bool {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *HEPokerHand) IsReducedYet() bool {
|
func (self *HEPokerHand) IsPair() bool {
|
||||||
if len(self.Cards) == 5 {
|
panic("not implemented")
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *HEPokerHand) IsPair() bool {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *HEPokerHand) IsTwoPair() bool {
|
func (self *HEPokerHand) IsTwoPair() bool {
|
||||||
|
panic("not implemented")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *HEPokerHand) IsSet() bool {
|
func (self *HEPokerHand) IsSet() bool {
|
||||||
|
panic("not implemented")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *HEPokerHand) IsStraight() bool {
|
func (self *HEPokerHand) IsStraight() bool {
|
||||||
|
panic("not implemented")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *HEPokerHand) IsFlush() bool {
|
func (self *HEPokerHand) IsFlush() bool {
|
||||||
|
panic("not implemented")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *HEPokerHand) IsFullHouse() bool {
|
func (self *HEPokerHand) IsFullHouse() bool {
|
||||||
|
panic("not implemented")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// this takes a list of pointers to 5 or more cards, permutes them into every
|
||||||
|
// possible five-card hand, by removing each in turn and recursing to
|
||||||
|
// itself, and then returns the best one as an *HEPokerHand
|
||||||
|
// out of all possible five-card permutations.
|
||||||
|
func ScoreCardsForHoldEm(input *Cards) (*HEPokerHand, error) {
|
||||||
|
if len(*input) < 5 {
|
||||||
|
return nil, errors.New("need at least 5 cards for an HEPokerHand")
|
||||||
|
}
|
||||||
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *HEPokerHand) ScoreHand() *HandScore {
|
func (self *HEPokerHand) ScoreHand() *HandScore {
|
||||||
|
return nil
|
||||||
}
|
|
||||||
|
|
||||||
func scoreHEPokerHand(input Cards) *HEPokerHand {
|
|
||||||
// this takes a list of pointers to 7 cards, permutes them into every
|
|
||||||
// possible five-card hand, by removing each in turn and recursing to
|
|
||||||
// itself, and then returns the best one as an *HEPokerHand
|
|
||||||
// out of all possible five-card permutations.
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package poker
|
||||||
|
|
||||||
|
//import "github.com/stretchr/testify/assert"
|
||||||
|
import "fmt"
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestPokerHand(t *testing.T) {
|
||||||
|
|
||||||
|
var v int64
|
||||||
|
for {
|
||||||
|
v = int64(cryptoUint64())
|
||||||
|
d := NewDeckFromSeed(v)
|
||||||
|
holeCards := d.Deal(2)
|
||||||
|
commCards := d.Deal(5)
|
||||||
|
fmt.Printf("%s %s\n", holeCards, commCards)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue