package main import ( "database/sql" "fmt" "log" "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() { db, err := connectDB() if err != nil { log.Fatal(err) } defer db.Close() 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("/data", func(c *gin.Context) { c.HTML(http.StatusOK, "data", gin.H{ "stats": getStatsTable(db), "games": getGamesTable(db), "single": true, }) }) 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 + getNewStep(db, game) game = newGame(gameFlow, aiSecond) } if game.isFinished() { saveGameLog(db, game) } stats := getStats(db) fmt.Println(game) 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": stats["total"], "aiWon": stats["aiWon"], "aiWonPercent": stats["aiWonPercent"], "draw": stats["draw"], "drawPercent": stats["drawPercent"], "lastAiLost": stats["lastAiLost"], }) }) r.Run() } func getLang(c *gin.Context) string { session := sessions.Default(c) lang := session.Get("lang") if lang == nil { lang = "" } else { lang = 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.(string) } 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 getNewStep(db *sql.DB, game *Game) string { nextStep := getWinnerNextStep(db, game) if "" != nextStep { return nextStep } return difference("123456789", game.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 } func getStats(db *sql.DB) map[string]string { stats := make(map[string]string) total, _ := getStatsCounter(db, "total") stats["total"] = strconv.Itoa(total) aiWon, _ := getStatsCounter(db, "ai_won") stats["aiWon"] = strconv.Itoa(aiWon) if total > 0 { stats["aiWonPercent"] = fmt.Sprintf("%.2f%%", float64(aiWon)/float64(total)*100) } else { stats["aiWonPercent"] = "0%" } draw, _ := getStatsCounter(db, "draw") stats["draw"] = strconv.Itoa(draw) if total > 0 { stats["drawPercent"] = fmt.Sprintf("%.2f%%", float64(draw)/float64(total)*100) } else { stats["drawPercent"] = "0%" } lastAiLost, _ := getStatsComment(db, "last_ai_lost") stats["lastAiLost"] = lastAiLost return stats }