changes + add uploader
This commit is contained in:
parent
1383b52f85
commit
06c6057c7d
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user