flags implementation
Some checks failed
build / build (push) Successful in 29s
release-tag / release-image (push) Has been cancelled

This commit is contained in:
Tijl 2024-08-26 16:46:28 +02:00
parent d246f5e270
commit a71595596a
Signed by: tijl
GPG Key ID: DAE24BFCD722F053
9 changed files with 133 additions and 25 deletions

View File

@ -17,6 +17,51 @@ import (
) )
func answerHandler(c *fiber.Ctx) error { func answerHandler(c *fiber.Ctx) error {
gameId, err := uuid.Parse(c.Cookies("app_flags_game_session"))
if err != nil {
return err
}
answer := c.FormValue("answer")
gameSession, err := db.Queries.GetFlagsGame(context.TODO(), gameId)
if err != nil {
return err
}
err, countries := filterCountriesByTags(gameSession.Tags)
if err != nil {
return err
}
shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.UUID.String())
correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1]
if answer == correctAnswer {
db.Queries.UpdateFlagsGame(context.TODO(), queries.UpdateFlagsGameParams{
GameID: gameId,
QuestionCurrent: gameSession.QuestionCurrent + 1,
})
db.Queries.UpsertGameAnswer(context.TODO(), queries.UpsertGameAnswerParams{
GameID: gameId,
Question: gameSession.QuestionCurrent,
Errors: 0,
})
} else {
db.Queries.UpsertGameAnswer(context.TODO(), queries.UpsertGameAnswerParams{
GameID: gameId,
Question: gameSession.QuestionCurrent,
Errors: 1,
})
}
err = db.Queries.UpdateQuestionCorrect(context.TODO(), gameId)
if err != nil {
return err
}
return questionHandler(c, NewGameUUID{}) return questionHandler(c, NewGameUUID{})
} }
@ -44,8 +89,7 @@ func questionHandler(c *fiber.Ctx, newGame NewGameUUID) error {
} }
if (gameSession.QuestionAmount != 0) && (gameSession.QuestionAmount+1 == gameSession.QuestionCurrent) { if (gameSession.QuestionAmount != 0) && (gameSession.QuestionAmount+1 == gameSession.QuestionCurrent) {
// TODO: game is over return gameEndHandler(c)
return c.SendString("game is over")
} }
err, countries := filterCountriesByTags(gameSession.Tags) err, countries := filterCountriesByTags(gameSession.Tags)
@ -53,6 +97,10 @@ func questionHandler(c *fiber.Ctx, newGame NewGameUUID) error {
return err return err
} }
if int(gameSession.QuestionCurrent) == len(countries) {
return gameEndHandler(c)
}
shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.UUID.String()) shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.UUID.String())
shuffledAnswers := shuffleSlice(countries, gameSession.GameSeed.UUID.String()+string(gameSession.QuestionCurrent)) shuffledAnswers := shuffleSlice(countries, gameSession.GameSeed.UUID.String()+string(gameSession.QuestionCurrent))
shuffledAnswers = shuffledAnswers[0:4] // 4 random aswers shuffledAnswers = shuffledAnswers[0:4] // 4 random aswers
@ -74,9 +122,13 @@ func questionHandler(c *fiber.Ctx, newGame NewGameUUID) error {
data["Title"] = "tmp" data["Title"] = "tmp"
data["Answers"] = shuffledAnswers data["Answers"] = shuffledAnswers
data["Flag"] = flag data["Flag"] = flag
data["Errors"] = gameSession.QuestionsErrors
return c.Render("apps/flags/question", data, "layouts/base") return c.Render("apps/flags/question", data, "layouts/base")
} }
func getGameData() {
}
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
@ -108,13 +160,29 @@ func startNewGameHandler(c *fiber.Ctx) error {
c.Cookie(&fiber.Cookie{ c.Cookie(&fiber.Cookie{
Name: "app_flags_game_session", Name: "app_flags_game_session",
Value: row.GameID.String(), Value: row.GameID.String(),
Secure: true, //Secure: true,
}) })
return questionHandler(c, NewGameUUID{used: true, UUID: row.GameID}) return questionHandler(c, NewGameUUID{used: true, UUID: row.GameID})
} }
func stopGameHandler(c *fiber.Ctx) error { func gameEndHandler(c *fiber.Ctx) error {
gameId, err := uuid.Parse(c.Cookies("app_flags_game_session"))
if err != nil {
return err
}
gameSession, err := db.Queries.GetFlagsGame(context.TODO(), gameId)
if err != nil {
return err
}
data := *web.Common(c)
data["Title"] = "tmp"
data["Errors"] = gameSession.QuestionsErrors
return c.Render("apps/flags/end", data, "layouts/base")
}
func stopGameHandler(c *fiber.Ctx) error { // exit game
utils.ClearCookie(c, "app_flags_game_session") utils.ClearCookie(c, "app_flags_game_session")
return EntryPageHandler(c) return EntryPageHandler(c)
} }

View File

@ -80,8 +80,8 @@ func Setup() {
case "start": case "start":
return startNewGameHandler(c) return startNewGameHandler(c)
case "answer": case "answer":
return c.SendString("wip") return answerHandler(c)
case "cancel": case "exit":
return stopGameHandler(c) return stopGameHandler(c)
} }

View File

@ -13,9 +13,16 @@ WHERE game_id = $2;
-- name: UpdateQuestionCorrect :exec -- name: UpdateQuestionCorrect :exec
UPDATE app_flags_games UPDATE app_flags_games
SET questions_correct = ( SET questions_errors = (
SELECT COUNT(*) SELECT COALESCE(SUM(errors), 0)
FROM app_flags_games_answers FROM app_flags_games_answers
WHERE game_id $1 AND correct = TRUE WHERE app_flags_games_answers.game_id = app_flags_games.game_id
) )
WHERE game_id = $1; WHERE app_flags_games.game_id = $1;
-- name: UpsertGameAnswer :exec
INSERT INTO app_flags_games_answers (game_id, question, errors)
VALUES ($1, $2, $3)
ON CONFLICT (game_id, question)
DO UPDATE SET errors = app_flags_games_answers.errors + EXCLUDED.errors;

View File

@ -38,7 +38,7 @@ func (q *Queries) CreateFlagsGame(ctx context.Context, arg CreateFlagsGameParams
} }
const getFlagsGame = `-- name: GetFlagsGame :one const getFlagsGame = `-- name: GetFlagsGame :one
SELECT game_id, game_seed, uid, tags, question_amount, question_current, question_correct, created_at, last_activity FROM app_flags_games WHERE game_id = $1 LIMIT 1 SELECT game_id, game_seed, uid, tags, question_amount, question_current, questions_errors, created_at, last_activity FROM app_flags_games WHERE game_id = $1 LIMIT 1
` `
func (q *Queries) GetFlagsGame(ctx context.Context, gameID uuid.UUID) (AppFlagsGame, error) { func (q *Queries) GetFlagsGame(ctx context.Context, gameID uuid.UUID) (AppFlagsGame, error) {
@ -51,7 +51,7 @@ func (q *Queries) GetFlagsGame(ctx context.Context, gameID uuid.UUID) (AppFlagsG
pq.Array(&i.Tags), pq.Array(&i.Tags),
&i.QuestionAmount, &i.QuestionAmount,
&i.QuestionCurrent, &i.QuestionCurrent,
&i.QuestionCorrect, &i.QuestionsErrors,
&i.CreatedAt, &i.CreatedAt,
&i.LastActivity, &i.LastActivity,
) )
@ -76,15 +76,33 @@ func (q *Queries) UpdateFlagsGame(ctx context.Context, arg UpdateFlagsGameParams
const updateQuestionCorrect = `-- name: UpdateQuestionCorrect :exec const updateQuestionCorrect = `-- name: UpdateQuestionCorrect :exec
UPDATE app_flags_games UPDATE app_flags_games
SET questions_correct = ( SET questions_errors = (
SELECT COUNT(*) SELECT COALESCE(SUM(errors), 0)
FROM app_flags_games_answers FROM app_flags_games_answers
WHERE game_id $1 AND correct = TRUE WHERE app_flags_games_answers.game_id = app_flags_games.game_id
) )
WHERE game_id = $1 WHERE app_flags_games.game_id = $1
` `
func (q *Queries) UpdateQuestionCorrect(ctx context.Context, dollar_1 interface{}) error { func (q *Queries) UpdateQuestionCorrect(ctx context.Context, gameID uuid.UUID) error {
_, err := q.db.ExecContext(ctx, updateQuestionCorrect, dollar_1) _, err := q.db.ExecContext(ctx, updateQuestionCorrect, gameID)
return err
}
const upsertGameAnswer = `-- name: UpsertGameAnswer :exec
INSERT INTO app_flags_games_answers (game_id, question, errors)
VALUES ($1, $2, $3)
ON CONFLICT (game_id, question)
DO UPDATE SET errors = app_flags_games_answers.errors + EXCLUDED.errors
`
type UpsertGameAnswerParams struct {
GameID uuid.UUID
Question int32
Errors int32
}
func (q *Queries) UpsertGameAnswer(ctx context.Context, arg UpsertGameAnswerParams) error {
_, err := q.db.ExecContext(ctx, upsertGameAnswer, arg.GameID, arg.Question, arg.Errors)
return err return err
} }

View File

@ -18,7 +18,7 @@ type AppFlagsGame struct {
Tags []string Tags []string
QuestionAmount int32 QuestionAmount int32
QuestionCurrent int32 QuestionCurrent int32
QuestionCorrect int32 QuestionsErrors int32
CreatedAt time.Time CreatedAt time.Time
LastActivity time.Time LastActivity time.Time
} }

View File

@ -5,7 +5,7 @@ CREATE TABLE app_flags_games (
tags VARCHAR[] NOT NULL, tags VARCHAR[] NOT NULL,
question_amount INT NOT NULL, question_amount INT NOT NULL,
question_current INT DEFAULT 1 NOT NULL, question_current INT DEFAULT 1 NOT NULL,
question_correct INT DEFAULT 0 NOT NULL, questions_errors INT DEFAULT 0 NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
FOREIGN KEY (uid) REFERENCES users (uid) FOREIGN KEY (uid) REFERENCES users (uid)

View File

@ -0,0 +1,13 @@
<div>
<div>
Errors: {{.Errors}}
</div>
<div>game is over</div>
<form method="post" hx-boost="true">
<input class="hidden" name="type" value="exit" />
<button type="submit" class="btn">exit</button>
</form>
</div>

View File

@ -2,6 +2,10 @@
<div> <div>
<div>
Errors: {{.Errors}}
</div>
<div class="flex justify-center p-4 mt-4"> <div class="flex justify-center p-4 mt-4">
<span style="font-size: 105px;">{{.Flag}}</span> <span style="font-size: 105px;">{{.Flag}}</span>
</div> </div>
@ -17,7 +21,7 @@
</div> </div>
<form hx-boost="true" method="post"> <form hx-boost="true" method="post">
<input class="hidden" name="type" value="cancel" /> <input class="hidden" name="type" value="exit" />
<button type="submit" class="btn hover:btn-error">Stop</button> <button type="submit" class="btn hover:btn-error">Stop</button>
</form> </form>

View File

@ -55,7 +55,6 @@
<span class="text-base">{{.T.about}}</span> <span class="text-base">{{.T.about}}</span>
</a> </a>
</li> </li>
<!--
<li class="flex-none"> <li class="flex-none">
<details class="dropdown"> <details class="dropdown">
<summary><a class="flex gap-4"> <summary><a class="flex gap-4">
@ -92,7 +91,6 @@
</ul> </ul>
</details> </details>
</li> </li>
-->
<li> <li>
{{if .SignedIn}} {{if .SignedIn}}
<a class='flex gap-4 {{if eq .Path "/account"}}active{{end}}' href="/account"> <a class='flex gap-4 {{if eq .Path "/account"}}active{{end}}' href="/account">