tAdd login key in app to show personal badge collection - scoreboard - Interactive scoreboard for CTF-like games
 (HTM) git clone git://git.z3bra.org/scoreboard.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit cb97cb5f224a91c0f4b47db43fae0f37f6e1a079
 (DIR) parent f77371dc092804946f8d32c60dbdf1a10b9516da
 (HTM) Author: Willy Goiffon <contact@z3bra.org>
       Date:   Fri, 27 Sep 2024 18:08:23 +0200
       
       Add login key in app to show personal badge collection
       
       Diffstat:
         M main.go                             |      28 +++++++++++-----------------
         M player.go                           |       8 ++++++--
         M ui.go                               |      40 +++++++++++++++++++++++++-------
       
       3 files changed, 49 insertions(+), 27 deletions(-)
       ---
 (DIR) diff --git a/main.go b/main.go
       t@@ -120,7 +120,13 @@ func main() {
                scoreboard.app = tview.NewApplication()
                scoreboard.pages = tview.NewPages()
                scoreboard.board = tview.NewFlex()
       -        scoreboard.player = &Player{ db: scoreboard.db }
       +        scoreboard.player = &Player{
       +                db: scoreboard.db,
       +                flag: 0,
       +                score: 0,
       +                ts: time.Now().Unix(),
       +                token: "",
       +        }
        
                scoreboard.pages.SetBackgroundColor(tcell.ColorDefault)
        
       t@@ -145,22 +151,11 @@ func main() {
                                os.Exit(0)
        
                        case "register":
       -                        scoreboard.player.flag = 0
       -                        scoreboard.player.score = 0
       -                        scoreboard.player.ts = time.Now().Unix()
       -
                                rank, _ := db_count_players(scoreboard.db)
                                scoreboard.NewPlayer(rank + 1)
                                scoreboard.pages.SwitchToPage("board")
                                reminder = true
        
       -                case "badges":
       -                        badgepage := scoreboard.Token(func () {
       -                                scoreboard.app.Stop()
       -                                fmt.Printf("Collection: %d/%d\n\n%s", scoreboard.player.flag, len(scoreboard.flag_ref), scoreboard.player.BadgeStr())
       -                        })
       -                        scoreboard.pages.AddAndSwitchToPage("badge", badgepage, true)
       -
                        /* anything not a command is treated as a flag */
                        default:
                                scoreboard.flag, err = db_get_flag(scoreboard.db, args[0])
       t@@ -169,19 +164,18 @@ func main() {
                                        return
                                }
        
       -                        submitpage := scoreboard.Token(func () {
       +                        page := scoreboard.Token(func () {
                                        err = scoreboard.player.Submit(scoreboard.flag)
                                        if err != nil {
                                                scoreboard.Fatal(err)
                                                return
                                        }
                                        scoreboard.HighlightBoard(scoreboard.player.ScoreRank() + 1)
       -                                scoreboard.pages.RemovePage("submit")
       -                                scoreboard.pages.ShowPage("board")
       +                                scoreboard.pages.RemovePage("token")
                                        scoreboard.GenerateHTML()
                                })
        
       -                        scoreboard.pages.AddAndSwitchToPage("submit", submitpage, true)
       +                        scoreboard.pages.AddAndSwitchToPage("token", page, true)
                        }
                }
        
       t@@ -192,7 +186,7 @@ func main() {
                }
        
                /* Print a token reminder on exit in case one has been generated or provided */
       -        if reminder {
       +        if reminder && scoreboard.player.token != "" {
                        fmt.Printf(TOKEN_REMINDER, scoreboard.player.name, scoreboard.player.token)
                }
        }
 (DIR) diff --git a/player.go b/player.go
       t@@ -147,7 +147,7 @@ func (p *Player) FlagStr() string {
                return fmt.Sprintf("%2d/%d", p.flag, len(scoreboard.flag_ref))
        }
        
       -func (p *Player) BadgeStr() string {
       +func (p *Player) BadgeStr(full bool) string {
                var badges strings.Builder
        
                query := `SELECT
       t@@ -168,7 +168,11 @@ func (p *Player) BadgeStr() string {
                        if err != nil {
                                return ""
                        }
       -                badges.WriteString(fmt.Sprintf("%s %s (%d pts)\n", b, v, s))
       +                if full {
       +                        badges.WriteString(fmt.Sprintf("%s %s\n", b, v))
       +                } else {
       +                        badges.WriteString(b)
       +                }
                }
        
                return badges.String();
 (DIR) diff --git a/ui.go b/ui.go
       t@@ -58,6 +58,19 @@ func RankTable(offset, limit, rank int, fill bool) *tview.Table {
                        t.SetCell(i, 3, newcell(scorestr))
                }
        
       +        t.SetSelectedFunc(func (row, col int) {
       +                var player Player
       +                col = 1
       +                player.name = t.GetCell(row, col).Text
       +                player.db = scoreboard.db
       +                player.Fetch()
       +                if scoreboard.player.name == player.name {
       +                        scoreboard.Message(player.name, player.BadgeStr(true))
       +                } else {
       +                        scoreboard.Popup(player.name, player.BadgeStr(false))
       +                }
       +        })
       +
                if fill == true {
                        bsize := int(math.Max(float64(BOARD_HEIGHT), float64(limit)))
                        for i:=t.GetRowCount(); i<bsize; i++ {
       t@@ -85,6 +98,7 @@ func (a *Application) SetupFrame() {
                grid.AddItem(a.board, 1, 0, 1, 1, BOARD_HEIGHT, BOARD_WIDTH, true)
        
                a.frame = tview.NewFrame(grid)
       +        a.frame.AddText(fmt.Sprintf("press 'l' to login"), false, tview.AlignCenter, 0)
        }
        
        func (a *Application) DrawBoard() {
       t@@ -98,6 +112,13 @@ func (a *Application) DrawBoard() {
                                a.app.Stop()
                                return nil
                        }
       +                if event.Rune() == 'l' && a.player.token == "" {
       +                        page := a.Token(func () {
       +                                a.pages.RemovePage("token")
       +                                a.HighlightBoard(a.player.ScoreRank() + 1)
       +                        })
       +                        a.pages.AddAndSwitchToPage("token", page, true)
       +                }
                        return event
                })
        }
       t@@ -108,7 +129,8 @@ func (a *Application) HighlightBoard(line int) {
                        AddItem(RankTable(0, -1, 0, true).Select(line - 1, 0), BOARD_HEIGHT, 1, true)
                a.app.SetFocus(a.board)
        
       -        a.frame.AddText(fmt.Sprintf(" 🔑%s", a.player.token), false, tview.AlignCenter, 0)
       +        a.frame.Clear()
       +        a.frame.AddText(fmt.Sprintf("🔑%s", a.player.token), false, tview.AlignCenter, 0)
        }
        
        func (a *Application) NewPlayer(rank int) {
       t@@ -150,7 +172,7 @@ func popup(title, text string, w, h int, callback func(key tcell.Key)) tview.Pri
        }
        
        func (a *Application) Message(title, text string) {
       -        p := popup(title, text, 64, 19, func(key tcell.Key) {
       +        p := popup(title, text, 72, 19, func(key tcell.Key) {
                        a.pages.RemovePage("popup")
                })
        
       t@@ -200,18 +222,20 @@ func (a *Application) Token(callback func()) tview.Primitive {
                                token := input.GetText()
        
                                if len(token) != 24 {
       -                                scoreboard.Popup("ERROR", "Invalid token format")
       +                                a.Popup("ERROR", "Invalid token format")
                                        return
                                }
       -                        err := scoreboard.player.FromToken(token)
       +                        err := a.player.FromToken(token)
                                if err != nil {
       -                                scoreboard.Fatal(err)
       +                                a.Fatal(err)
                                        return
                                }
        
       -                        scoreboard.player.token = token;
       -                        scoreboard.player.Fetch()
       -                        scoreboard.pages.RemovePage("token");
       +                        a.player.Fetch()
       +                        a.player.token = token;
       +                        a.pages.RemovePage("token");
       +                        a.frame.Clear()
       +                        a.frame.AddText(fmt.Sprintf("🔑%s", a.player.token), false, tview.AlignCenter, 0)
                                callback()
                        })