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:
14
.air.conf
14
.air.conf
@@ -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
17
.air.toml
Normal 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
|
||||||
@@ -58,7 +58,6 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal("sqlite connect:", err)
|
lg.Fatal("sqlite connect:", err)
|
||||||
}
|
}
|
||||||
lg.Println("using SQLite qrank.db")
|
|
||||||
|
|
||||||
if err := db.AutoMigrate(&User{}, &Session{}, &LoginToken{}, &Table{}, &Game{}, &GameUser{}); err != nil {
|
if err := db.AutoMigrate(&User{}, &Session{}, &LoginToken{}, &Table{}, &Game{}, &GameUser{}); err != nil {
|
||||||
lg.Fatal("migrate:", err)
|
lg.Fatal("migrate:", err)
|
||||||
@@ -68,6 +67,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create engine
|
// Create engine
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
store := cookie.NewStore([]byte("secret"))
|
store := cookie.NewStore([]byte("secret"))
|
||||||
@@ -107,7 +107,7 @@ func main() {
|
|||||||
|
|
||||||
// Start application with port
|
// Start application with port
|
||||||
bind := ":" + port
|
bind := ":" + port
|
||||||
lg.Println("listening on", bind, "base:", baseURL)
|
//lg.Println("Listening on", baseURL)
|
||||||
if err := r.Run(bind); err != nil {
|
if err := r.Run(bind); err != nil {
|
||||||
lg.Fatal(err)
|
lg.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ func postEnter(c *gin.Context) {
|
|||||||
slug = tableSlug.(string)
|
slug = tableSlug.(string)
|
||||||
|
|
||||||
}
|
}
|
||||||
sess.Delete("TableSlug")
|
|
||||||
|
|
||||||
// Parse form
|
// Parse form
|
||||||
a1h := strings.TrimSpace(c.PostForm("a1"))
|
a1h := strings.TrimSpace(c.PostForm("a1"))
|
||||||
@@ -127,11 +126,16 @@ func postEnter(c *gin.Context) {
|
|||||||
|
|
||||||
// Create game
|
// Create game
|
||||||
var g Game
|
var g Game
|
||||||
|
|
||||||
|
// Get the current table
|
||||||
|
var t Table
|
||||||
|
db.Model(&Table{}).Where("slug = ?", slug).First(&t)
|
||||||
|
|
||||||
if slug != "" {
|
if slug != "" {
|
||||||
g = Game{
|
g = Game{
|
||||||
ScoreA: scoreA,
|
ScoreA: scoreA,
|
||||||
ScoreB: scoreB,
|
ScoreB: scoreB,
|
||||||
Table: &Table{Slug: slug},
|
TableID: &t.ID,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g = Game{
|
g = Game{
|
||||||
@@ -145,6 +149,7 @@ func postEnter(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var players []Player
|
var players []Player
|
||||||
|
fmt.Println("Len players", len(players))
|
||||||
var playerbuf []float64
|
var playerbuf []float64
|
||||||
for i, user := range users {
|
for i, user := range users {
|
||||||
if user != nil {
|
if user != nil {
|
||||||
@@ -191,15 +196,20 @@ func postEnter(c *gin.Context) {
|
|||||||
Where("id = ?", p.u.ID).
|
Where("id = ?", p.u.ID).
|
||||||
UpdateColumn(updateString, expr).UpdateColumn("game_count", gorm.Expr("game_count + ?", 1)).Error
|
UpdateColumn(updateString, expr).UpdateColumn("game_count", gorm.Expr("game_count + ?", 1)).Error
|
||||||
if err != nil {
|
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 {
|
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")
|
c.String(http.StatusInternalServerError, "failed to assign player")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sess.Delete("TableSlug")
|
||||||
|
sess.Save()
|
||||||
|
|
||||||
c.Redirect(http.StatusFound, "/history")
|
c.Redirect(http.StatusFound, "/history")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,11 +229,13 @@ func roundFloat(val float64, precision uint) float64 {
|
|||||||
func getHistory(c *gin.Context) {
|
func getHistory(c *gin.Context) {
|
||||||
// Load recent games
|
// Load recent games
|
||||||
var games []Game
|
var games []Game
|
||||||
db.Order("created_at desc").Find(&games)
|
db.Preload("Table").Order("created_at desc").Find(&games)
|
||||||
|
|
||||||
type UserElo struct {
|
type UserElo struct {
|
||||||
User
|
User
|
||||||
DeltaElo float64
|
|
||||||
|
DeltaElo string
|
||||||
|
Color string
|
||||||
}
|
}
|
||||||
|
|
||||||
type GRow struct {
|
type GRow struct {
|
||||||
@@ -238,15 +250,28 @@ func getHistory(c *gin.Context) {
|
|||||||
db.Model(&GameUser{}).Preload("User").Where("game_id = ?", g.ID).Find(&gps)
|
db.Model(&GameUser{}).Preload("User").Where("game_id = ?", g.ID).Find(&gps)
|
||||||
var a, b []UserElo
|
var a, b []UserElo
|
||||||
for _, gp := range gps {
|
for _, gp := range gps {
|
||||||
if gp.Side == "A" {
|
var eloColor, eloFloatString string
|
||||||
a = append(a, UserElo{gp.User, roundFloat(gp.DeltaElo, 2)})
|
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 {
|
} 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})
|
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})
|
tm.Render(c, "history", gin.H{"Games": rows})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@@ -64,7 +63,6 @@ func (tm *TemplateManager) LoadTemplates() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name := stripAfterDot(filepath.Base(file))
|
name := stripAfterDot(filepath.Base(file))
|
||||||
lg.Println(name)
|
|
||||||
|
|
||||||
// Parse base + view template together
|
// Parse base + view template together
|
||||||
tpl, err := template.New(name).
|
tpl, err := template.New(name).
|
||||||
@@ -80,7 +78,6 @@ func (tm *TemplateManager) LoadTemplates() {
|
|||||||
|
|
||||||
// Render executes a template by name into the given context
|
// Render executes a template by name into the given context
|
||||||
func (tm *TemplateManager) Render(c *gin.Context, name string, data gin.H) error {
|
func (tm *TemplateManager) Render(c *gin.Context, name string, data gin.H) error {
|
||||||
print("\nRendering template:", name, "\n")
|
|
||||||
u := getSessionUser(c)
|
u := getSessionUser(c)
|
||||||
|
|
||||||
// Prefil the data for the render
|
// 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 {
|
if !ok {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
fmt.Print(tm.templates[name])
|
|
||||||
|
|
||||||
if err := tpl.ExecuteTemplate(c.Writer, tm.base, data); err != nil {
|
if err := tpl.ExecuteTemplate(c.Writer, tm.base, data); err != nil {
|
||||||
log.Println("template error:", err)
|
log.Println("template error:", err)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<h2>Enter a game</h2>
|
<h2>Enter a game</h2>
|
||||||
|
|
||||||
{{if .Table}}
|
{{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}}
|
{{end}}
|
||||||
|
|
||||||
<form method="POST" action="/enter">
|
<form method="POST" action="/enter">
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
<li>
|
<li>
|
||||||
<div class="small">{{fmtTime .CreatedAt}}</div>
|
<div class="small">{{fmtTime .CreatedAt}}</div>
|
||||||
<div>
|
<div>
|
||||||
{{if .Table}}<span class="badge">{{.Table.Name}}</span> {{end}}
|
{{if .Table}}<span class="badge">{{.Table.Slug}}</span> {{end}}
|
||||||
{{if .WinnerIsA}}<span style="color: goldenrod;"> {{range .PlayersA}}{{.Username}} {{end}}{{.ScoreA}}</span>/{{.ScoreB}}
|
{{if .WinnerIsA}}<span style="color: darkgoldenrod;"> {{range .PlayersA}}{{.Username}} {{end}}{{.ScoreA}}</span>/{{.ScoreB}}
|
||||||
{{else}} <span style="color: goldenrod;"> {{range .PlayersB}}{{.Username}} {{end}}{{.ScoreB}}</span>/{{.ScoreA}}{{end}}
|
{{else}} <span style="color: darkgoldenrod;"> {{range .PlayersB}}{{.Username}} {{end}}{{.ScoreB}}</span>/{{.ScoreA}}{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="small">
|
<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>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<form method="post" action="/table/{{.CurrentSlug}}">
|
<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>
|
||||||
<form method="post" action="/table/{{.CurrentSlug}}/reset">
|
<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>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user