changes + add uploader
All checks were successful
build / build (push) Successful in 24s
release-tag / release-image (push) Successful in 16m35s

This commit is contained in:
Tijl 2024-08-29 12:36:58 +02:00
parent 1383b52f85
commit 06c6057c7d
Signed by: tijl
GPG Key ID: DAE24BFCD722F053
2 changed files with 231 additions and 206 deletions

View File

@ -1,203 +1,215 @@
package flags package flags
import ( import (
"context" "context"
"database/sql" "database/sql"
"net/http" "net/http"
"strconv" "strconv"
"time" "time"
"git.tijl.dev/tijl/tijl.dev-core/internal/queries" "git.tijl.dev/tijl/tijl.dev-core/internal/queries"
"git.tijl.dev/tijl/tijl.dev-core/internal/user" "git.tijl.dev/tijl/tijl.dev-core/internal/user"
"git.tijl.dev/tijl/tijl.dev-core/internal/utils" "git.tijl.dev/tijl/tijl.dev-core/internal/utils"
"git.tijl.dev/tijl/tijl.dev-core/modules/db" "git.tijl.dev/tijl/tijl.dev-core/modules/db"
"git.tijl.dev/tijl/tijl.dev-core/modules/i18n" "git.tijl.dev/tijl/tijl.dev-core/modules/i18n"
"git.tijl.dev/tijl/tijl.dev-core/modules/web" "git.tijl.dev/tijl/tijl.dev-core/modules/web"
"github.com/enescakir/emoji" "github.com/enescakir/emoji"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/google/uuid" "github.com/google/uuid"
) )
const flagSessionCookie string = "app_flags_game_session" const flagSessionCookie string = "app_flags_game_session"
type NullableUUID struct { type NullableUUID struct {
uuid.UUID uuid.UUID
valid bool valid bool
} }
type NullableString struct { type NullableString struct {
String string String string
valid bool valid bool
} }
func answerHandler(c *fiber.Ctx) error { func answerHandler(c *fiber.Ctx) error {
gameId, err := uuid.Parse(c.Cookies(flagSessionCookie)) gameId, err := uuid.Parse(c.Cookies(flagSessionCookie))
if err != nil { if err != nil {
return err return err
} }
answer := c.FormValue("answer") answer := c.FormValue("answer")
gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId)
if err != nil { if err != nil {
return err return err
} }
err, countries := filterCountriesByTags(gameSession.Tags) err, countries := filterCountriesByTags(gameSession.Tags)
if err != nil { if err != nil {
return err return err
} }
shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String()) shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String())
correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1] correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1]
if answer == correctAnswer { if answer == correctAnswer {
db.Queries.AppFlagsUpdateGame(context.TODO(), queries.AppFlagsUpdateGameParams{ db.Queries.AppFlagsUpdateGame(context.TODO(), queries.AppFlagsUpdateGameParams{
GameID: gameId, GameID: gameId,
QuestionCurrent: gameSession.QuestionCurrent + 1, QuestionCurrent: gameSession.QuestionCurrent + 1,
}) })
db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{ db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{
GameID: gameId, GameID: gameId,
Question: gameSession.QuestionCurrent, Question: gameSession.QuestionCurrent,
Errors: 0, Errors: 0,
}) })
} else { } else {
db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{ db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{
GameID: gameId, GameID: gameId,
Question: gameSession.QuestionCurrent, Question: gameSession.QuestionCurrent,
Errors: 1, Errors: 1,
}) })
} }
err = db.Queries.AppFlagsUpdateQuestionCorrect(context.TODO(), gameId) err = db.Queries.AppFlagsUpdateQuestionCorrect(context.TODO(), gameId)
if err != nil { if err != nil {
return err return err
} }
if answer == correctAnswer { if answer == correctAnswer {
return questionHandler(c, NullableUUID{}, NullableString{}) return questionHandler(c, NullableUUID{}, NullableString{})
} else { } else {
return questionHandler(c, NullableUUID{}, NullableString{valid: true, String: answer}) return questionHandler(c, NullableUUID{}, NullableString{valid: true, String: answer})
} }
} }
func questionHandler(c *fiber.Ctx, newGame NullableUUID, prevError NullableString) error { func questionHandler(c *fiber.Ctx, newGame NullableUUID, prevError NullableString) error {
var gameId uuid.UUID var gameId uuid.UUID
var err error var err error
if newGame.valid { if newGame.valid {
gameId = newGame.UUID gameId = newGame.UUID
} else { } else {
gameId, err = uuid.Parse(c.Cookies(flagSessionCookie)) gameId, err = uuid.Parse(c.Cookies(flagSessionCookie))
if err != nil { if err != nil {
return err return err
} }
} }
gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId)
if err != nil { if err != nil {
return err return err
} }
uid, err := user.GetSession(c) uid, err := user.GetSession(c)
if uid != gameSession.Uid.String { if uid != gameSession.Uid.String {
utils.ClearCookie(c, flagSessionCookie) utils.ClearCookie(c, flagSessionCookie)
return gameStartHandler(c) return gameStartHandler(c)
} }
if (gameSession.QuestionAmount != 0) && (gameSession.QuestionAmount+1 == gameSession.QuestionCurrent) { if (gameSession.QuestionAmount != 0) && (gameSession.QuestionAmount+1 == gameSession.QuestionCurrent) {
return gameEndHandler(c) return gameEndHandler(c)
} }
err, countries := filterCountriesByTags(gameSession.Tags) err, countries := filterCountriesByTags(gameSession.Tags)
if err != nil { if err != nil {
return err return err
} }
if int(gameSession.QuestionCurrent) == len(countries) { if int(gameSession.QuestionCurrent) == len(countries) {
return gameEndHandler(c) return gameEndHandler(c)
} }
shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String()) shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String())
shuffledAnswers := shuffleSlice(countries, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent)) correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1]
shuffledAnswers = shuffledAnswers[0:4] // 4 random aswers
shuffledAnswers = append(shuffledAnswers, shuffledCountries[gameSession.QuestionCurrent-1]) // add correct answer
shuffledAnswers = shuffleSlice(shuffledAnswers, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent)) // shuffle again
if gameSession.QuestionAmount != 0 && int(gameSession.QuestionAmount) < len(countries) { // Filter out the correct answer from the countries list
shuffledCountries = shuffledCountries[0:gameSession.QuestionAmount] filteredCountries := filterSlice(countries, correctAnswer)
}
var timeleft = []string{} // Shuffle the filtered countries to get random answers
if gameSession.Seconds != 0 { shuffledAnswers := shuffleSlice(filteredCountries, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent))
timeleft = append(timeleft, strconv.Itoa(int(gameSession.Seconds)-int(time.Since(gameSession.CreatedAt).Seconds())))
}
flag, err := emoji.CountryFlag(shuffledCountries[gameSession.QuestionCurrent-1]) // Select 4 random answers from the shuffled list
if err != nil { shuffledAnswers = shuffledAnswers[0:4]
return err
}
data := *web.Common(c) // Add the correct answer to the list
data["Title"] = "tmp" shuffledAnswers = append(shuffledAnswers, correctAnswer)
data["TimeLeft"] = timeleft
data["QuestionsLeft"] = len(shuffledCountries) - int(gameSession.QuestionCurrent) + 1 // Shuffle the answers again to randomize the position of the correct answer
data["Answers"] = shuffledAnswers shuffledAnswers = shuffleSlice(shuffledAnswers, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent))
data["Flag"] = flag
data["Errors"] = gameSession.QuestionsErrors if gameSession.QuestionAmount != 0 && int(gameSession.QuestionAmount) < len(countries) {
data["PreviousError"] = prevError.String shuffledCountries = shuffledCountries[0:gameSession.QuestionAmount]
data["ShortcutKeys"] = []string{"d", "f", "h", "j", "k"} }
return c.Render("apps/flags/question", data, "layouts/base")
var timeleft = []string{}
if gameSession.Seconds != 0 {
timeleft = append(timeleft, strconv.Itoa(int(gameSession.Seconds)-int(time.Since(gameSession.CreatedAt).Seconds())))
}
flag, err := emoji.CountryFlag(shuffledCountries[gameSession.QuestionCurrent-1])
if err != nil {
return err
}
data := *web.Common(c)
data["Title"] = "tmp"
data["TimeLeft"] = timeleft
data["QuestionsLeft"] = len(shuffledCountries) - int(gameSession.QuestionCurrent) + 1
data["Answers"] = shuffledAnswers
data["Flag"] = flag
data["Errors"] = gameSession.QuestionsErrors
data["PreviousError"] = prevError.String
data["ShortcutKeys"] = []string{"d", "f", "h", "j", "k"}
return c.Render("apps/flags/question", data, "layouts/base")
} }
func sharedGameHandler(c *fiber.Ctx) error { func sharedGameHandler(c *fiber.Ctx) error {
shareKey := c.FormValue("sharekey") shareKey := c.FormValue("sharekey")
data, err := db.Queries.AppFlagsGetSharedData(context.TODO(), shareKey) data, err := db.Queries.AppFlagsGetSharedData(context.TODO(), shareKey)
if err != nil { if err != nil {
return err return err
} }
return setupGame(c, data.Tags, int(data.Questions), int(data.Seconds), NullableUUID{valid: true, UUID: data.GameSeed}) return setupGame(c, data.Tags, int(data.Questions), int(data.Seconds), NullableUUID{valid: true, UUID: data.GameSeed})
} }
func startNewGameHandler(c *fiber.Ctx) error { func startNewGameHandler(c *fiber.Ctx) error {
values := c.Request().PostArgs().PeekMulti("tags") values := c.Request().PostArgs().PeekMulti("tags")
var selectedTags []string var selectedTags []string
for _, v := range values { for _, v := range values {
selectedTags = append(selectedTags, string(v)) selectedTags = append(selectedTags, string(v))
} }
if len(selectedTags) < 1 { if len(selectedTags) < 1 {
return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"]) return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"])
} }
err, countries := filterCountriesByTags(selectedTags) err, countries := filterCountriesByTags(selectedTags)
if err != nil { if err != nil {
return err return err
} }
if len(countries) < 6 { if len(countries) < 6 {
return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"]) return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"])
} }
maxQuestions, err := strconv.Atoi(c.FormValue("max_questions")) maxQuestions, err := strconv.Atoi(c.FormValue("max_questions"))
if err != nil { if err != nil {
return err return err
} }
seconds, err := strconv.Atoi(c.FormValue("seconds")) seconds, err := strconv.Atoi(c.FormValue("seconds"))
if err != nil { if err != nil {
return err return err
} }
if c.FormValue("share") != "" { if c.FormValue("share") != "" {
return createSharedGameData(c, selectedTags, maxQuestions, seconds) return createSharedGameData(c, selectedTags, maxQuestions, seconds)
} }
return setupGame(c, selectedTags, maxQuestions, seconds, NullableUUID{}) return setupGame(c, selectedTags, maxQuestions, seconds, NullableUUID{})
} }
func createSharedGameData(c *fiber.Ctx, tags []string, maxQuestions int, seconds int) error { func createSharedGameData(c *fiber.Ctx, tags []string, maxQuestions int, seconds int) error {
@ -206,83 +218,86 @@ func createSharedGameData(c *fiber.Ctx, tags []string, maxQuestions int, seconds
return c.SendStatus(http.StatusUnauthorized) return c.SendStatus(http.StatusUnauthorized)
} }
shareKey := utils.RandString(4) shareKey := utils.RandString(4)
_, err = db.Queries.AppFlagsNewSharedData(context.TODO(), queries.AppFlagsNewSharedDataParams{ _, err = db.Queries.AppFlagsNewSharedData(context.TODO(), queries.AppFlagsNewSharedDataParams{
Uid: uid, Uid: uid,
ShareKey: shareKey, ShareKey: shareKey,
Tags: tags, Tags: tags,
Questions: int32(maxQuestions), Questions: int32(maxQuestions),
Seconds: int32(seconds), Seconds: int32(seconds),
GameSeed: uuid.New(), GameSeed: uuid.New(),
}) })
if err != nil { if err != nil {
return err return err
} }
data := *web.Common(c) data := *web.Common(c)
data["Title"] = "tmp" data["Title"] = "tmp"
data["ShareKey"] = shareKey data["ShareKey"] = shareKey
return c.Render("apps/flags/shared", data, "layouts/base") return c.Render("apps/flags/shared", data, "layouts/base")
} }
func setupGame(c *fiber.Ctx, tags []string, maxQuestions int, seconds int, gameSeed NullableUUID) error { func setupGame(c *fiber.Ctx, tags []string, maxQuestions int, seconds int, gameSeed NullableUUID) error {
var Quid = sql.NullString{} var Quid = sql.NullString{}
uid, err := user.GetSession(c) uid, err := user.GetSession(c)
if err == nil { if err == nil {
Quid.Valid = true Quid.Valid = true
Quid.String = uid Quid.String = uid
} }
createGameParams := queries.AppFlagsCreateGameWithSeedParams{ createGameParams := queries.AppFlagsCreateGameWithSeedParams{
Uid: Quid, Uid: Quid,
Tags: tags, Tags: tags,
QuestionAmount: int32(maxQuestions), QuestionAmount: int32(maxQuestions),
Seconds: int32(seconds), Seconds: int32(seconds),
GameSeed: uuid.New(), GameSeed: uuid.New(),
} }
if gameSeed.valid { if gameSeed.valid {
createGameParams.GameSeed = gameSeed.UUID createGameParams.GameSeed = gameSeed.UUID
} }
gameID, err := db.Queries.AppFlagsCreateGameWithSeed(context.TODO(), createGameParams) gameID, err := db.Queries.AppFlagsCreateGameWithSeed(context.TODO(), createGameParams)
if err != nil { if err != nil {
return err return err
} }
c.Cookie(&fiber.Cookie{ c.Cookie(&fiber.Cookie{
Name: flagSessionCookie, Name: flagSessionCookie,
Value: gameID.String(), Value: gameID.String(),
//Secure: true, //Secure: true,
}) })
return questionHandler(c, NullableUUID{valid: true, UUID: gameID}, NullableString{}) return questionHandler(c, NullableUUID{valid: true, UUID: gameID}, NullableString{})
} }
func gameEndHandler(c *fiber.Ctx) error { func gameEndHandler(c *fiber.Ctx) error {
gameId, err := uuid.Parse(c.Cookies(flagSessionCookie)) gameId, err := uuid.Parse(c.Cookies(flagSessionCookie))
if err != nil { if err != nil {
return err return err
} }
gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId)
if err != nil { if err != nil {
return err return err
} }
data := *web.Common(c) data := *web.Common(c)
data["Title"] = "tmp" data["Title"] = "tmp"
data["Errors"] = gameSession.QuestionsErrors data["Errors"] = gameSession.QuestionsErrors
return c.Render("apps/flags/end", data, "layouts/base") return c.Render("apps/flags/end", data, "layouts/base")
} }
func stopGameHandler(c *fiber.Ctx) error { // exit game func stopGameHandler(c *fiber.Ctx) error { // exit game
utils.ClearCookie(c, flagSessionCookie) utils.ClearCookie(c, flagSessionCookie)
return gameStartHandler(c) return gameStartHandler(c)
} }
func gameStartHandler(c *fiber.Ctx) error { func gameStartHandler(c *fiber.Ctx) error {
data := *web.Common(c)
data["Title"] = "tmp"
data["SupportedTags"] = supportedTags
return c.Render("apps/flags/start", data, "layouts/base") data := *web.Common(c)
data["Title"] = "tmp"
data["SupportedTags"] = supportedTags
return c.Render("apps/flags/start", data, "layouts/base")
} }

View File

@ -66,3 +66,13 @@ func filterCountriesByTags(tags []string) (error, []string) {
return nil, result return nil, result
} }
func filterSlice(slice []string, value string) []string {
var result []string
for _, v := range slice {
if v != value {
result = append(result, v)
}
}
return result
}