tic-tac-toe/main.go
2023-12-29 20:40:16 +02:00

160 lines
3.4 KiB
Go

package main
import (
"fmt"
"net/http"
"strconv"
"github.com/foolin/goview/supports/ginview"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.HTMLRender = ginview.Default()
store := cookie.NewStore([]byte("secret"))
r.Use(sessions.Sessions("mysession", store))
r.StaticFile("/favicon.ico", "./assets/favicon.ico")
r.StaticFile("/sgs.png", "./assets/sgs.png")
r.StaticFile("/en.png", "./assets/en.png")
r.StaticFile("/cross.png", "./assets/cross.png")
r.StaticFile("/nought.png", "./assets/nought.png")
r.GET("/", func(c *gin.Context) {
lang := getLang(c)
c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/%s/0/x", lang))
})
r.GET("/:lang", func(c *gin.Context) {
lang := getLang(c)
c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/%s/0/x", lang))
})
r.GET("/:lang/:ai_second/:game", func(c *gin.Context) {
lang := getLang(c)
gameFlow, gameState := getGameFlow(c)
aiSecond, err := strconv.ParseBool(c.Param("ai_second"))
if err != nil {
aiSecond = false
}
game := newGame(gameFlow, aiSecond)
if gameState == GameStateInProgress && !game.isFinished() {
gameFlow = gameFlow + getNewClick(gameFlow)
game = newGame(gameFlow, aiSecond)
}
// if game ended - save results
c.HTML(http.StatusOK, "index", gin.H{
"title": "Index title!",
"lang": lang,
"gameFlow": gameFlow,
"game": game,
"fields": [9]int{1, 2, 3, 4, 5, 6, 7, 8, 9},
"fieldClass": func(game *Game, fieldNum int) string {
fieldClass := FieldClass[fieldNum]
if field, ok := game.fields[fieldNum]; ok {
if len(field.image) > 0 {
fieldClass = fieldClass + " " + field.image
}
if field.line {
fieldClass = fieldClass + " line"
}
}
return fieldClass
},
"disabled": func(game *Game, fieldNum int) bool {
if field, ok := game.fields[fieldNum]; ok {
return field.disabled
}
return false
},
"total": 8787,
"aiWon": 232,
"aiWonPercent": "3.5%",
"draw": 6777,
"drawPercent": "94.4%",
})
})
r.Run()
}
func getLang(c *gin.Context) string {
session := sessions.Default(c)
lang := session.Get("lang").(string)
pLang, hasParam := c.Params.Get("lang")
if hasParam && pLang != lang {
lang = pLang
session.Set("lang", lang)
session.Save()
}
if lang != "sgs" && lang != "en" {
lang = "sgs"
session.Set("lang", lang)
session.Save()
}
return lang
}
func getGameFlow(c *gin.Context) (string, int) {
gameFlow := c.Param("game")
if "0" == gameFlow {
return gameFlow, GameStateWaitingUser
}
if "x" == gameFlow {
return "", GameStateInProgress
}
if "0" == string(gameFlow[0]) {
gameFlow = string(gameFlow[1:])
}
if len(gameFlow) >= 9 {
return gameFlow, GameStateEnded
}
return gameFlow, GameStateInProgress
}
func getNewClick(gameFlow string) string {
return difference("123456789", gameFlow)[0]
}
func difference(a, b string) []string {
mb := make(map[string]struct{}, len(b))
for _, x := range str2array(b) {
mb[x] = struct{}{}
}
var diff []string
for _, x := range str2array(a) {
if _, found := mb[x]; !found {
diff = append(diff, x)
}
}
return diff
}
func str2array(str string) []string {
chars := []rune(str)
var splited []string
for i := 0; i < len(chars); i++ {
splited = append(splited, string(chars[i]))
}
return splited
}