Better deployment with air. Colorized history. Fixed table bugs. Table will be added to game if coming from QR code. With tables in the history. App could be deployed now

This commit is contained in:
Jonas Hahn
2025-08-27 15:00:52 +02:00
parent 01132e1968
commit 9595da7a53
8 changed files with 62 additions and 38 deletions

View File

@@ -1,14 +0,0 @@
root = "."
[build]
cmd = "nix develop -c go build -o ./tmp/main ./src/..." # for nix users
include_ext = ["go", "html", "css"]
exclude_dir = ["tmp"]
[log]
level = "warn"
time = true
[env]
GIN_MODE = "release" # change to "release" for production
APP_PORT = 18765

17
.air.toml Normal file
View File

@@ -0,0 +1,17 @@
[build]
cmd = "nix develop -c go build -o ./tmp/main ./src/..." # only for nix users
[log]
time = false
[misc]
clean_on_exit = true
[screen]
clear_on_rebuild = true
keep_scroll = true
[proxy]
enabled = true
proxy_port = 8090
app_port = 18765

View File

@@ -58,7 +58,6 @@ func main() {
if err != nil {
lg.Fatal("sqlite connect:", err)
}
lg.Println("using SQLite qrank.db")
if err := db.AutoMigrate(&User{}, &Session{}, &LoginToken{}, &Table{}, &Game{}, &GameUser{}); err != nil {
lg.Fatal("migrate:", err)
@@ -68,6 +67,7 @@ func main() {
}
// Create engine
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
store := cookie.NewStore([]byte("secret"))
@@ -107,7 +107,7 @@ func main() {
// Start application with port
bind := ":" + port
lg.Println("listening on", bind, "base:", baseURL)
//lg.Println("Listening on", baseURL)
if err := r.Run(bind); err != nil {
lg.Fatal(err)
}

View File

@@ -52,7 +52,6 @@ func postEnter(c *gin.Context) {
slug = tableSlug.(string)
}
sess.Delete("TableSlug")
// Parse form
a1h := strings.TrimSpace(c.PostForm("a1"))
@@ -127,11 +126,16 @@ func postEnter(c *gin.Context) {
// Create game
var g Game
// Get the current table
var t Table
db.Model(&Table{}).Where("slug = ?", slug).First(&t)
if slug != "" {
g = Game{
ScoreA: scoreA,
ScoreB: scoreB,
Table: &Table{Slug: slug},
ScoreA: scoreA,
ScoreB: scoreB,
TableID: &t.ID,
}
} else {
g = Game{
@@ -145,6 +149,7 @@ func postEnter(c *gin.Context) {
}
var players []Player
fmt.Println("Len players", len(players))
var playerbuf []float64
for i, user := range users {
if user != nil {
@@ -191,15 +196,20 @@ func postEnter(c *gin.Context) {
Where("id = ?", p.u.ID).
UpdateColumn(updateString, expr).UpdateColumn("game_count", gorm.Expr("game_count + ?", 1)).Error
if err != nil {
fmt.Println(err)
log.Println(err)
}
log.Println(p.dElo)
if err := db.Create(&GameUser{GameID: g.ID, UserID: p.u.ID, Side: p.side, DeltaElo: p.dElo}).Error; err != nil {
c.String(http.StatusInternalServerError, "failed to assign player")
return
}
}
sess.Delete("TableSlug")
sess.Save()
c.Redirect(http.StatusFound, "/history")
}
@@ -219,11 +229,13 @@ func roundFloat(val float64, precision uint) float64 {
func getHistory(c *gin.Context) {
// Load recent games
var games []Game
db.Order("created_at desc").Find(&games)
db.Preload("Table").Order("created_at desc").Find(&games)
type UserElo struct {
User
DeltaElo float64
DeltaElo string
Color string
}
type GRow struct {
@@ -238,15 +250,28 @@ func getHistory(c *gin.Context) {
db.Model(&GameUser{}).Preload("User").Where("game_id = ?", g.ID).Find(&gps)
var a, b []UserElo
for _, gp := range gps {
if gp.Side == "A" {
a = append(a, UserElo{gp.User, roundFloat(gp.DeltaElo, 2)})
var eloColor, eloFloatString string
eloFloat := roundFloat(gp.DeltaElo, 2)
if eloFloat > 0 {
eloColor = "green"
eloFloatString = fmt.Sprintf("+%.2f", eloFloat)
} else if eloFloat < 0 {
eloColor = "red"
eloFloatString = fmt.Sprintf("%.2f", eloFloat)
} else {
b = append(b, UserElo{gp.User, roundFloat(gp.DeltaElo, 2)})
eloColor = "black"
eloFloatString = fmt.Sprintf("%.2f", eloFloat)
}
if gp.Side == "A" {
a = append(a, UserElo{gp.User, eloFloatString, eloColor})
} else {
b = append(b, UserElo{gp.User, eloFloatString, eloColor})
}
}
rows = append(rows, GRow{Game: g, PlayersA: a, PlayersB: b, WinnerIsA: g.ScoreA > g.ScoreB})
log.Printf("%+v", rows[0].PlayersA[0].Username)
}
tm.Render(c, "history", gin.H{"Games": rows})
}

View File

@@ -1,7 +1,6 @@
package main
import (
"fmt"
"html/template"
"log"
"os"
@@ -64,7 +63,6 @@ func (tm *TemplateManager) LoadTemplates() {
}
name := stripAfterDot(filepath.Base(file))
lg.Println(name)
// Parse base + view template together
tpl, err := template.New(name).
@@ -80,7 +78,6 @@ func (tm *TemplateManager) LoadTemplates() {
// Render executes a template by name into the given context
func (tm *TemplateManager) Render(c *gin.Context, name string, data gin.H) error {
print("\nRendering template:", name, "\n")
u := getSessionUser(c)
// Prefil the data for the render
@@ -93,7 +90,6 @@ func (tm *TemplateManager) Render(c *gin.Context, name string, data gin.H) error
if !ok {
return os.ErrNotExist
}
fmt.Print(tm.templates[name])
if err := tpl.ExecuteTemplate(c.Writer, tm.base, data); err != nil {
log.Println("template error:", err)

View File

@@ -4,7 +4,7 @@
<h2>Enter a game</h2>
{{if .Table}}
<p class="small">Table: <span class="badge">{{.Table.Name}}</span></p>
<p class="small">Table: <span class="badge">{{.Table.Slug}}</span></p>
{{end}}
<form method="POST" action="/enter">

View File

@@ -6,12 +6,12 @@
<li>
<div class="small">{{fmtTime .CreatedAt}}</div>
<div>
{{if .Table}}<span class="badge">{{.Table.Name}}</span> {{end}}
{{if .WinnerIsA}}<span style="color: goldenrod;"> {{range .PlayersA}}{{.Username}} {{end}}{{.ScoreA}}</span>/{{.ScoreB}}
{{else}} <span style="color: goldenrod;"> {{range .PlayersB}}{{.Username}} {{end}}{{.ScoreB}}</span>/{{.ScoreA}}{{end}}
{{if .Table}}<span class="badge">{{.Table.Slug}}</span> {{end}}
{{if .WinnerIsA}}<span style="color: darkgoldenrod;"> {{range .PlayersA}}{{.Username}} {{end}}{{.ScoreA}}</span>/{{.ScoreB}}
{{else}} <span style="color: darkgoldenrod;"> {{range .PlayersB}}{{.Username}} {{end}}{{.ScoreB}}</span>/{{.ScoreA}}{{end}}
</div>
<div class="small">
{{range .PlayersA}}@{{.Username}} <span style="color: chocolate;">{{.DeltaElo}}</span> {{end}}vs {{range .PlayersB}}@{{.Username}} <span style="color: chocolate;">{{.DeltaElo}}</span> {{end}}
{{range .PlayersA}}@{{.Username}} <span style="color: {{.Color}};">{{.DeltaElo}}</span> {{end}}vs {{range .PlayersB}}@{{.Username}} <span style="color: {{.Color}};">{{.DeltaElo}}</span> {{end}}
</div>
</li>
{{else}}

View File

@@ -19,10 +19,10 @@
<div class="row">
<form method="post" action="/table/{{.CurrentSlug}}">
<button style="background-color: greenyellow; border-color: gray;" type="submit">FinishGame</button>
<button style="background-color: powderblue; border-color: gray;" type="submit">FinishGame</button>
</form>
<form method="post" action="/table/{{.CurrentSlug}}/reset">
<button style="background-color: coral; border-color: gray;" type="submit">ResetGame</button>
<button type="submit">ResetGame</button>
</form>