package main import ( "fmt" "time" "git.eeqj.de/sneak/pokercore" "github.com/rcrowley/go-metrics" "github.com/schollz/progressbar/v3" ) var gameCount = 50_000 var playerCount = 2 type Player struct { Hand pokercore.Cards ScoredHand *pokercore.PokerHand Position int } type Game struct { Deck *pokercore.Deck Players []*Player Community pokercore.Cards Street int } func NewGame() *Game { g := &Game{} g.Street = 0 g.Deck = pokercore.NewDeck() g.Deck.ShuffleRandomly() return g } func (g *Game) StreetAsString() string { switch g.Street { case 0: return "pre-flop" case 1: return "flop" case 2: return "turn" case 3: return "river" } return "unknown" } func (g *Game) DealPlayersIn() { for i := 0; i < playerCount; i++ { p := Player{Hand: g.Deck.Deal(2), Position: i + 1} g.Players = append(g.Players, &p) } } func (g *Game) DealFlop() { g.Community = g.Deck.Deal(3) g.Street = 1 } func (g *Game) DealTurn() { g.Community = append(g.Community, g.Deck.Deal(1)...) g.Street = 2 } func (g *Game) DealRiver() { g.Community = append(g.Community, g.Deck.Deal(1)...) g.Street = 3 } func (g *Game) ShowWinner() int { var winner *Player var winningHand *pokercore.PokerHand for _, p := range g.Players { if p != nil { ac := append(p.Hand, g.Community...) ph, err := ac.PokerHand() if err != nil { panic(err) } if winner == nil { winner = p winningHand = ph } else { if ph.Score > winningHand.Score { winner = p winningHand = ph } } } } return winner.Position } func main() { oneWins := 0 twoWins := 0 registry := metrics.NewRegistry() timer := metrics.NewTimer() registry.Register("pokerGame", timer) bar := progressbar.NewOptions(gameCount, progressbar.OptionSetDescription("Gambling..."), progressbar.OptionShowCount(), progressbar.OptionShowIts(), progressbar.OptionSetPredictTime(true), progressbar.OptionClearOnFinish(), progressbar.OptionThrottle(100*time.Millisecond), // Update every 100ms ) for i := 0; i < gameCount; i++ { start := time.Now() w := runFlip() duration := time.Since(start) timer.Update(duration) bar.Add(1) if w == 1 { oneWins++ } else { twoWins++ } } fmt.Printf("%d games played\n", gameCount) fmt.Printf("Min: %d ns\n", timer.Min()) fmt.Printf("Max: %d ns\n", timer.Max()) fmt.Printf("Mean: %0.2f ns\n", timer.Mean()) fmt.Printf("StdDev: %0.2f ns\n", timer.StdDev()) fmt.Printf("Percentiles: 50%%: %0.2f ns, 75%%: %0.2f ns, 95%%: %0.2f ns, 99%%: %0.2f ns\n", timer.Percentile(0.50), timer.Percentile(0.75), timer.Percentile(0.95), timer.Percentile(0.99)) oneWinPercentage := float64(oneWins) / float64(gameCount) * 100 twoWinPercentage := float64(twoWins) / float64(gameCount) * 100 fmt.Printf("Player 1 won: %d (%0.2f%%)\n", oneWins, oneWinPercentage) fmt.Printf("Player 2 won: %d (%0.2f%%)\n", twoWins, twoWinPercentage) } func runFlip() int { g := NewGame() g.DealPlayersIn() g.DealFlop() g.DealTurn() g.DealRiver() winnerPosition := g.ShowWinner() return winnerPosition }