dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit 281a51d21b42c730ce02bd4c4b79173ce27827f3
parent adcbe002b68dcc6a7ee0ed317d8695f8f280ec84
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Mon, 18 Dec 2023 03:30:56 -0500

buy-in when joining room

Diffstat:
Mpkg/database/tablePokerTables.go | 5+++++
Mpkg/database/tableUsers.go | 20++++++++++++++++++++
Mpkg/web/handlers/data.go | 4+++-
Mpkg/web/handlers/handlers.go | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mpkg/web/handlers/poker/poker.go | 77+++++++----------------------------------------------------------------------
Mpkg/web/public/views/pages/poker.gohtml | 16++++++++++++++--
6 files changed, 123 insertions(+), 87 deletions(-)

diff --git a/pkg/database/tablePokerTables.go b/pkg/database/tablePokerTables.go @@ -89,6 +89,11 @@ func (d *DkfDB) GetPokerTableAccount(userID UserID, pokerTableID int64) (out Pok return } +func (d *DkfDB) GetPokerTableAccounts(userID UserID) (out []PokerTableAccount, err error) { + err = d.db.Find(&out, "user_id = ?", userID).Error + return +} + func (d *DkfDB) GetPokerTableAccountSums() (sumAmounts, sumBets PokerChip, err error) { var tmp struct{ SumAmounts, SumBets PokerChip } err = d.db.Raw(`SELECT SUM(amount) AS sum_amounts, SUM(amount_bet) AS sum_bets FROM poker_table_accounts`).Scan(&tmp).Error diff --git a/pkg/database/tableUsers.go b/pkg/database/tableUsers.go @@ -699,3 +699,23 @@ func (d *DkfDB) SetPokerSubAddress(userID UserID, subAddress string) (err error) err = d.db.Exec(`UPDATE users SET poker_xmr_sub_address = ? WHERE id = ?`, subAddress, userID).Error return } + +func (u *User) GetUserChips(isTest bool) PokerChip { + return utils.Ternary(isTest, u.ChipsTest, u.XmrBalance.ToPokerChip()) +} + +func (u *User) IncrUserChips(isTest bool, v PokerChip, decrement bool) { + if decrement { + if isTest { + u.ChipsTest -= v + } else { + u.XmrBalance -= v.ToPiconero() + } + } else { + if isTest { + u.ChipsTest += v + } else { + u.XmrBalance += v.ToPiconero() + } + } +} diff --git a/pkg/web/handlers/data.go b/pkg/web/handlers/data.go @@ -951,7 +951,8 @@ type chessData struct { type TmpTable struct { database.PokerTable - NbSeated int + TableBalance database.PokerChip + NbSeated int } type pokerData struct { @@ -967,6 +968,7 @@ type pokerData struct { WithdrawAddress string WithdrawUnique int64 Error string + ErrorTable string HelperAmount string HelperType string HelperXmr string diff --git a/pkg/web/handlers/handlers.go b/pkg/web/handlers/handlers.go @@ -789,12 +789,20 @@ func PokerHomeHandler(c echo.Context) error { data.HelperChips = pxmr.ToPokerChip() data.HelperpXmr = pxmr.RawString() data.HelperUsd = pxmr.UsdStr() + userTableAccounts, _ := db.GetPokerTableAccounts(authUser.ID) for _, t := range pokerTables { var nbSeated int if g := poker.PokerInstance.GetGame(poker.RoomID(t.Slug)); g != nil { nbSeated = g.CountSeated() } - data.Tables = append(data.Tables, TmpTable{PokerTable: t, NbSeated: nbSeated}) + tableBalance := database.PokerChip(0) + for _, a := range userTableAccounts { + if a.PokerTableID == t.ID { + tableBalance = a.Amount + break + } + } + data.Tables = append(data.Tables, TmpTable{PokerTable: t, NbSeated: nbSeated, TableBalance: tableBalance}) } if authUser.PokerXmrSubAddress != "" { @@ -836,35 +844,87 @@ func PokerHomeHandler(c echo.Context) error { pokerTableSlug := c.Request().PostFormValue("table_slug") playerBuyIn := database.PokerChip(utils.DoParseUint64(c.Request().PostFormValue("buy_in"))) tx := db.Begin() - pokerTable, _ := tx.GetPokerTableBySlug(pokerTableSlug) + g := poker.PokerInstance.GetGame(poker.RoomID(pokerTableSlug)) + if g != nil { + g.Players.Lock() + defer g.Players.Unlock() + if g.IsSeated2(authUser.Username) { + tx.Rollback() + data.ErrorTable = "Cannot buy-in while seated" + return c.Render(http.StatusOK, "poker", data) + } + } + pokerTable, err := tx.GetPokerTableBySlug(pokerTableSlug) + if err != nil { + tx.Rollback() + data.ErrorTable = "table mot found" + return c.Render(http.StatusOK, "poker", data) + } if playerBuyIn < pokerTable.MinBuyIn { tx.Rollback() - data.Error = "buy in too small" + data.ErrorTable = "buy in too small" return c.Render(http.StatusOK, "poker", data) } if playerBuyIn > pokerTable.MaxBuyIn { tx.Rollback() - data.Error = "buy in too high" + data.ErrorTable = "buy in too high" return c.Render(http.StatusOK, "poker", data) } - userChips := authUser.ChipsTest - if !pokerTable.IsTest { - userChips = authUser.XmrBalance.ToPokerChip() - } + userChips := authUser.GetUserChips(pokerTable.IsTest) if userChips < playerBuyIn { tx.Rollback() - data.Error = "not enough chips to buy-in" + data.ErrorTable = "not enough chips to buy-in" + return c.Render(http.StatusOK, "poker", data) + } + tableAccount, err := tx.GetPokerTableAccount(authUser.ID, pokerTable.ID) + if err != nil { + tx.Rollback() + data.ErrorTable = "failed to get table account" + return c.Render(http.StatusOK, "poker", data) + } + if tableAccount.Amount+playerBuyIn > pokerTable.MaxBuyIn { + tx.Rollback() + data.ErrorTable = "Buy-in exceed table max buy-in" return c.Render(http.StatusOK, "poker", data) } - tableAccount, _ := tx.GetPokerTableAccount(authUser.ID, pokerTable.ID) tableAccount.Amount += playerBuyIn - if pokerTable.IsTest { - authUser.ChipsTest -= playerBuyIn - } else { - authUser.XmrBalance -= playerBuyIn.ToPiconero() + authUser.IncrUserChips(pokerTable.IsTest, playerBuyIn, true) + authUser.DoSave(tx) + tableAccount.DoSave(tx) + tx.Commit() + return c.Redirect(http.StatusFound, "/poker/"+pokerTableSlug) + + } else if formName == "cash_out" { + pokerTableSlug := c.Request().PostFormValue("table_slug") + tx := db.Begin() + g := poker.PokerInstance.GetGame(poker.RoomID(pokerTableSlug)) + if g != nil { + g.Players.Lock() + defer g.Players.Unlock() + if g.IsSeated2(authUser.Username) { + tx.Rollback() + data.ErrorTable = "Cannot cash out while seated" + return c.Render(http.StatusOK, "poker", data) + } + } + pokerTable, err := tx.GetPokerTableBySlug(pokerTableSlug) + if err != nil { + tx.Rollback() + data.ErrorTable = "table mot found" + return c.Render(http.StatusOK, "poker", data) + } + account, err := tx.GetPokerTableAccount(authUser.ID, pokerTable.ID) + if err != nil { + tx.Rollback() + data.ErrorTable = "failed to get table account" + return c.Render(http.StatusOK, "poker", data) } + authUser.IncrUserChips(pokerTable.IsTest, account.Amount, false) + account.Amount = 0 + account.DoSave(tx) authUser.DoSave(tx) tx.Commit() + return c.Redirect(http.StatusFound, "/poker") } else if formName == "reset_chips" { authUser.ChipsTest = 1000 diff --git a/pkg/web/handlers/poker/poker.go b/pkg/web/handlers/poker/poker.go @@ -352,6 +352,10 @@ func (g *PokerGame) IsSeated(player database.Username) bool { return g.isSeated(player) } +func (g *PokerGame) IsSeated2(player database.Username) bool { + return g.isSeated(player) +} + func (g *PokerGame) isSeated(player database.Username) bool { return g.getPlayer(player) != nil } @@ -415,27 +419,9 @@ func (g *PokerGame) UnSitPlayer(username database.Username) error { } func (g *PokerGame) UnSitPlayer1(seatedPlayer *SeatedPlayer) error { - db := g.DB ongoing := g.Ongoing - pokerTableID := g.PokerTableID roomTopic := g.RoomID.Topic() seatedPlayerUsername := seatedPlayer.Username - - db.WithE(func(tx *database.DkfDB) error { - user, err := tx.GetUserByUsername(seatedPlayerUsername) - if err != nil { - return err - } - account, err := tx.GetPokerTableAccount(user.ID, pokerTableID) - if err != nil { - return err - } - incrUserChips(&user, g.PokerTableIsTest, account.Amount, false) - account.Amount = 0 - account.DoSave(tx) - user.DoSave(tx) - return nil - }) if ongoing != nil { if player := ongoing.GetPlayer(seatedPlayerUsername); player != nil { select { @@ -1453,13 +1439,7 @@ func Refund(db *database.DkfDB) { accounts, _ := db.GetPositivePokerTableAccounts() db.With(func(tx *database.DkfDB) { for _, account := range accounts { - if user, err := tx.GetUserByID(account.UserID); err == nil { - incrUserChips(&user, account.PokerTable.IsTest, account.Amount+account.AmountBet, false) - account.Amount = 0 - account.AmountBet = 0 - account.DoSave(tx) - user.DoSave(tx) - } + _ = tx.PokerTableAccountRefundPartialBet(account.UserID, account.PokerTableID, account.AmountBet) } }) } @@ -1508,26 +1488,6 @@ func PokerUnSitHandler(c echo.Context) error { return c.HTML(http.StatusOK, html) } -func getUserChips(user *database.User, isTest bool) database.PokerChip { - return utils.Ternary(isTest, user.ChipsTest, user.XmrBalance.ToPokerChip()) -} - -func incrUserChips(user *database.User, isTest bool, v database.PokerChip, decrement bool) { - if decrement { - if isTest { - user.ChipsTest -= v - } else { - user.XmrBalance -= v.ToPiconero() - } - } else { - if isTest { - user.ChipsTest += v - } else { - user.XmrBalance += v.ToPiconero() - } - } -} - func PokerSitHandler(c echo.Context) error { db := c.Get("database").(*database.DkfDB) html := hutils.HtmlCssReset + `<form method="post"><button>Sit</button></form>` @@ -1547,8 +1507,6 @@ func PokerSitHandler(c echo.Context) error { if c.Request().Method == http.MethodPost { pokerTable, err := db.GetPokerTableBySlug(roomID.String()) - tableMinBuyIn := pokerTable.MinBuyIn - tableMaxBuyIn := pokerTable.MaxBuyIn tableID := pokerTable.ID if err != nil { return c.HTML(http.StatusOK, html) @@ -1558,35 +1516,14 @@ func PokerSitHandler(c echo.Context) error { logrus.Error(err) return c.HTML(http.StatusOK, html) } - playerBuyIn := database.PokerChip(utils.DoParseUint64(c.QueryParam("buy-in"))) - if playerBuyIn == 0 { - playerBuyIn = tableMinBuyIn - } - if playerBuyIn < tableMinBuyIn { - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: fmt.Sprintf("buy-in too low; min buy in: %d", tableMinBuyIn)}) - return c.HTML(http.StatusOK, html) - } - if playerBuyIn > tableMaxBuyIn { - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: fmt.Sprintf("buy-in too high; max buy in: %d", tableMaxBuyIn)}) + if tableAccount.Amount < pokerTable.MinBet { + PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: fmt.Sprintf("not enough chips to sit. have: %d, need: %d", tableAccount.Amount, pokerTable.MinBet)}) return c.HTML(http.StatusOK, html) } - userChips := getUserChips(authUser, pokerTable.IsTest) - totalChips := userChips + tableAccount.Amount - if totalChips < playerBuyIn { - PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: fmt.Sprintf("Not enough chips for the desired buy-in; want: %d; have: %d", playerBuyIn, totalChips)}) - return c.HTML(http.StatusOK, html) - } - needed := playerBuyIn - tableAccount.Amount - incrUserChips(authUser, pokerTable.IsTest, needed, true) - tableAccount.Amount += needed if err := g.SitPlayer(authUser, pos, tableAccount.Amount); err != nil { PokerPubSub.Pub(roomUserTopic, ErrorMsgEvent{Message: err.Error()}) return c.HTML(http.StatusOK, html) } - db.With(func(tx *database.DkfDB) { - authUser.DoSave(tx) - tableAccount.DoSave(tx) - }) PokerPubSub.Pub(roomTopic, PokerSeatTakenEvent{}) g.newLogEvent(fmt.Sprintf("%s sit", authUser.Username.String())) } diff --git a/pkg/web/public/views/pages/poker.gohtml b/pkg/web/public/views/pages/poker.gohtml @@ -74,6 +74,9 @@ <hr /> </div> <h3>Tables</h3> + {{ if .Data.ErrorTable }} + <div class="alert alert-danger">{{ .Data.ErrorTable }}</div> + {{ end }} <table class="table table-novpadding table-sm table-hover table-striped"> <tr> <th>Table</th> @@ -86,7 +89,8 @@ {{ range .Data.Tables }} <tr> <td class="align-middle"> - {{ .Name }} + {{ .Name }}<br /> + {{ if gt .TableBalance 0 }}(<span style="color: #eaac45;">{{ .TableBalance }} <small>chips</small></span>){{ end }} </td> <td class="text-center align-middle">{{ .NbSeated }}/6</td> <td class="align-middle">{{ .MinBuyIn }} - {{ .MaxBuyIn }}</td> @@ -94,7 +98,7 @@ <td class="text-center align-middle">{{ if .IsTest }}FREE{{ else }}XMR{{ end }}</td> <td class="text-right"> <form method="post" class="d-inline-block"> - <input type="hidden" name="csrf" value="{{ .CSRF }}" /> + <input type="hidden" name="csrf" value="{{ $.CSRF }}" /> <input type="hidden" name="form_name" value="join_table" /> <input type="hidden" name="table_slug" value="{{ .Slug }}" /> <div class="input-group"> @@ -104,6 +108,14 @@ </div> </div> </form> + {{ if gt .TableBalance 0 }} + <form method="post" class="d-inline-block"> + <input type="hidden" name="csrf" value="{{ $.CSRF }}" /> + <input type="hidden" name="form_name" value="cash_out" /> + <input type="hidden" name="table_slug" value="{{ .Slug }}" /> + <button class="btn btn-primary btn-sm">Cash out</button> + </form> + {{ end }} <a href="/poker/{{ .Slug }}" class="btn btn-primary btn-sm">Spectate</a> </td> </tr>