aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2024-08-11 20:53:17 +0900
committernsfisis <nsfisis@gmail.com>2024-08-11 20:53:17 +0900
commitfe8b14ccc77c829a2baa4034edb22daff9d5d8f8 (patch)
tree37528798ede5a89b1a7be6c6ee2fec20395668a2
parente3502d9e649fe61bb0ba4046b2c23c0d78bc92e9 (diff)
parent0c448f5d403a084389acb0b3d215f8728a599302 (diff)
downloadphperkaigi-2025-albatross-fe8b14ccc77c829a2baa4034edb22daff9d5d8f8.tar.gz
phperkaigi-2025-albatross-fe8b14ccc77c829a2baa4034edb22daff9d5d8f8.tar.zst
phperkaigi-2025-albatross-fe8b14ccc77c829a2baa4034edb22daff9d5d8f8.zip
Merge branch 'feat/send-problem-before-starting-game'
-rw-r--r--Makefile2
-rw-r--r--backend/admin/handler.go21
-rw-r--r--backend/admin/templates/game_edit.html2
-rw-r--r--backend/api/generated.go67
-rw-r--r--backend/api/handler.go49
-rw-r--r--backend/db/models.go2
-rw-r--r--backend/db/query.sql.go32
-rw-r--r--backend/game/hub.go21
-rw-r--r--backend/game/message.go1
-rw-r--r--backend/query.sql6
-rw-r--r--backend/schema.sql2
-rw-r--r--frontend/app/.server/api/schema.d.ts6
-rw-r--r--frontend/app/components/GolfPlayApp.client.tsx8
-rw-r--r--frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx10
-rw-r--r--openapi/api-server.yaml11
15 files changed, 90 insertions, 150 deletions
diff --git a/Makefile b/Makefile
index b9320bd..5cda0b3 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ DOCKER_COMPOSE := docker compose -f compose.local.yaml
all: down build reset up
reset:
- echo "UPDATE games SET state = 'waiting_entries', started_at = NULL WHERE game_id = 1;" | make psql-query
+ echo "UPDATE games SET state = 'waiting_entries', started_at = NULL WHERE game_id = 7;" | make psql-query
.PHONY: build
build:
diff --git a/backend/admin/handler.go b/backend/admin/handler.go
index 7239b08..d540f57 100644
--- a/backend/admin/handler.go
+++ b/backend/admin/handler.go
@@ -196,16 +196,14 @@ func (h *Handler) postGameEdit(c echo.Context) error {
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid duration_seconds")
}
- var problemID *int
+ var problemID int
{
problemIDRaw := c.FormValue("problem_id")
- if problemIDRaw != "" {
- problemIDInt, err := strconv.Atoi(problemIDRaw)
- if err != nil {
- return echo.NewHTTPError(http.StatusBadRequest, "Invalid problem_id")
- }
- problemID = &problemIDInt
+ problemIDInt, err := strconv.Atoi(problemIDRaw)
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, "Invalid problem_id")
}
+ problemID = problemIDInt
}
var startedAt *time.Time
{
@@ -230,13 +228,6 @@ func (h *Handler) postGameEdit(c echo.Context) error {
Valid: true,
}
}
- var changedProblemID *int32
- if problemID == nil {
- changedProblemID = nil
- } else {
- changedProblemID = new(int32)
- *changedProblemID = int32(*problemID)
- }
{
// TODO:
@@ -255,7 +246,7 @@ func (h *Handler) postGameEdit(c echo.Context) error {
DisplayName: displayName,
DurationSeconds: int32(durationSeconds),
StartedAt: changedStartedAt,
- ProblemID: changedProblemID,
+ ProblemID: int32(problemID),
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
diff --git a/backend/admin/templates/game_edit.html b/backend/admin/templates/game_edit.html
index f40cc5d..c1e38a6 100644
--- a/backend/admin/templates/game_edit.html
+++ b/backend/admin/templates/game_edit.html
@@ -43,7 +43,7 @@
</div>
<div>
<label>Problem ID</label>
- <input type="text" name="problem_id" value="{{ if .Game.ProblemID }}{{ .Game.ProblemID }}{{ end }}">
+ <input type="text" name="problem_id" value="{{ .Game.ProblemID }}">
</div>
<div>
<button type="submit">Save</button>
diff --git a/backend/api/generated.go b/backend/api/generated.go
index f7fd7e4..a68b13b 100644
--- a/backend/api/generated.go
+++ b/backend/api/generated.go
@@ -81,7 +81,7 @@ type Game struct {
GameID int `json:"game_id"`
GameType GameGameType `json:"game_type"`
Players []User `json:"players"`
- Problem *Problem `json:"problem,omitempty"`
+ Problem Problem `json:"problem"`
StartedAt *int `json:"started_at,omitempty"`
State GameState `json:"state"`
VerificationSteps []VerificationStep `json:"verification_steps"`
@@ -157,13 +157,7 @@ type GamePlayerMessageS2CExecResultPayloadStatus string
// GamePlayerMessageS2CPrepare defines model for GamePlayerMessageS2CPrepare.
type GamePlayerMessageS2CPrepare struct {
- Data GamePlayerMessageS2CPreparePayload `json:"data"`
- Type string `json:"type"`
-}
-
-// GamePlayerMessageS2CPreparePayload defines model for GamePlayerMessageS2CPreparePayload.
-type GamePlayerMessageS2CPreparePayload struct {
- Problem Problem `json:"problem"`
+ Type string `json:"type"`
}
// GamePlayerMessageS2CStart defines model for GamePlayerMessageS2CStart.
@@ -1209,35 +1203,34 @@ func (sh *strictHandler) GetToken(ctx echo.Context, params GetTokenParams) error
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "AA==",
+ "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",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/backend/api/handler.go b/backend/api/handler.go
index 5b53791..4150ba6 100644
--- a/backend/api/handler.go
+++ b/backend/api/handler.go
@@ -89,17 +89,6 @@ func (h *Handler) GetGames(ctx context.Context, _ GetGamesRequestObject, user *a
startedAtTimestamp := int(row.StartedAt.Time.Unix())
startedAt = &startedAtTimestamp
}
- var problem *Problem
- if row.ProblemID != nil {
- if row.Title == nil || row.Description == nil {
- panic("inconsistent data")
- }
- problem = &Problem{
- ProblemID: int(*row.ProblemID),
- Title: *row.Title,
- Description: *row.Description,
- }
- }
games[i] = Game{
GameID: int(row.GameID),
GameType: GameGameType(row.GameType),
@@ -107,7 +96,11 @@ func (h *Handler) GetGames(ctx context.Context, _ GetGamesRequestObject, user *a
DisplayName: row.DisplayName,
DurationSeconds: int(row.DurationSeconds),
StartedAt: startedAt,
- Problem: problem,
+ Problem: Problem{
+ ProblemID: int(row.ProblemID),
+ Title: row.Title,
+ Description: row.Description,
+ },
}
}
return GetGames200JSONResponse{
@@ -117,6 +110,7 @@ func (h *Handler) GetGames(ctx context.Context, _ GetGamesRequestObject, user *a
func (h *Handler) GetGame(ctx context.Context, request GetGameRequestObject, user *auth.JWTClaims) (GetGameResponseObject, error) {
// TODO: check user permission
+ _ = user
gameID := request.GameID
row, err := h.q.GetGameByID(ctx, int32(gameID))
if err != nil {
@@ -134,19 +128,6 @@ func (h *Handler) GetGame(ctx context.Context, request GetGameRequestObject, use
startedAtTimestamp := int(row.StartedAt.Time.Unix())
startedAt = &startedAtTimestamp
}
- var problem *Problem
- if row.ProblemID != nil {
- if row.Title == nil || row.Description == nil {
- panic("inconsistent data")
- }
- if user.IsAdmin || (GameState(row.State) != Closed && GameState(row.State) != WaitingEntries) {
- problem = &Problem{
- ProblemID: int(*row.ProblemID),
- Title: *row.Title,
- Description: *row.Description,
- }
- }
- }
playerRows, err := h.q.ListGamePlayers(ctx, int32(gameID))
if err != nil {
return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
@@ -176,13 +157,17 @@ func (h *Handler) GetGame(ctx context.Context, request GetGameRequestObject, use
}
}
game := Game{
- GameID: int(row.GameID),
- GameType: GameGameType(row.GameType),
- State: GameState(row.State),
- DisplayName: row.DisplayName,
- DurationSeconds: int(row.DurationSeconds),
- StartedAt: startedAt,
- Problem: problem,
+ GameID: int(row.GameID),
+ GameType: GameGameType(row.GameType),
+ State: GameState(row.State),
+ DisplayName: row.DisplayName,
+ DurationSeconds: int(row.DurationSeconds),
+ StartedAt: startedAt,
+ Problem: Problem{
+ ProblemID: int(row.ProblemID),
+ Title: row.Title,
+ Description: row.Description,
+ },
Players: players,
VerificationSteps: verificationSteps,
}
diff --git a/backend/db/models.go b/backend/db/models.go
index 800c183..f6e7ed1 100644
--- a/backend/db/models.go
+++ b/backend/db/models.go
@@ -16,7 +16,7 @@ type Game struct {
DurationSeconds int32
CreatedAt pgtype.Timestamp
StartedAt pgtype.Timestamp
- ProblemID *int32
+ ProblemID int32
}
type GamePlayer struct {
diff --git a/backend/db/query.sql.go b/backend/db/query.sql.go
index cbef51d..583389e 100644
--- a/backend/db/query.sql.go
+++ b/backend/db/query.sql.go
@@ -136,7 +136,7 @@ func (q *Queries) CreateUserAuth(ctx context.Context, arg CreateUserAuthParams)
const getGameByID = `-- name: GetGameByID :one
SELECT game_id, game_type, state, display_name, duration_seconds, created_at, started_at, games.problem_id, problems.problem_id, title, description FROM games
-LEFT JOIN problems ON games.problem_id = problems.problem_id
+JOIN problems ON games.problem_id = problems.problem_id
WHERE games.game_id = $1
LIMIT 1
`
@@ -149,10 +149,10 @@ type GetGameByIDRow struct {
DurationSeconds int32
CreatedAt pgtype.Timestamp
StartedAt pgtype.Timestamp
- ProblemID *int32
- ProblemID_2 *int32
- Title *string
- Description *string
+ ProblemID int32
+ ProblemID_2 int32
+ Title string
+ Description string
}
func (q *Queries) GetGameByID(ctx context.Context, gameID int32) (GetGameByIDRow, error) {
@@ -295,7 +295,7 @@ func (q *Queries) ListGamePlayers(ctx context.Context, gameID int32) ([]ListGame
const listGames = `-- name: ListGames :many
SELECT game_id, game_type, state, display_name, duration_seconds, created_at, started_at, games.problem_id, problems.problem_id, title, description FROM games
-LEFT JOIN problems ON games.problem_id = problems.problem_id
+JOIN problems ON games.problem_id = problems.problem_id
ORDER BY games.game_id
`
@@ -307,10 +307,10 @@ type ListGamesRow struct {
DurationSeconds int32
CreatedAt pgtype.Timestamp
StartedAt pgtype.Timestamp
- ProblemID *int32
- ProblemID_2 *int32
- Title *string
- Description *string
+ ProblemID int32
+ ProblemID_2 int32
+ Title string
+ Description string
}
func (q *Queries) ListGames(ctx context.Context) ([]ListGamesRow, error) {
@@ -347,7 +347,7 @@ func (q *Queries) ListGames(ctx context.Context) ([]ListGamesRow, error) {
const listGamesForPlayer = `-- name: ListGamesForPlayer :many
SELECT games.game_id, game_type, state, display_name, duration_seconds, created_at, started_at, games.problem_id, problems.problem_id, title, description, game_players.game_id, user_id FROM games
-LEFT JOIN problems ON games.problem_id = problems.problem_id
+JOIN problems ON games.problem_id = problems.problem_id
JOIN game_players ON games.game_id = game_players.game_id
WHERE game_players.user_id = $1
ORDER BY games.game_id
@@ -361,10 +361,10 @@ type ListGamesForPlayerRow struct {
DurationSeconds int32
CreatedAt pgtype.Timestamp
StartedAt pgtype.Timestamp
- ProblemID *int32
- ProblemID_2 *int32
- Title *string
- Description *string
+ ProblemID int32
+ ProblemID_2 int32
+ Title string
+ Description string
GameID_2 int32
UserID int32
}
@@ -511,7 +511,7 @@ type UpdateGameParams struct {
DisplayName string
DurationSeconds int32
StartedAt pgtype.Timestamp
- ProblemID *int32
+ ProblemID int32
}
func (q *Queries) UpdateGame(ctx context.Context, arg UpdateGameParams) error {
diff --git a/backend/game/hub.go b/backend/game/hub.go
index 54c559c..b454bb5 100644
--- a/backend/game/hub.go
+++ b/backend/game/hub.go
@@ -611,13 +611,6 @@ func (hub *gameHub) startGame() error {
for player := range hub.players {
player.s2cMessages <- &playerMessageS2CPrepare{
Type: playerMessageTypeS2CPrepare,
- Data: playerMessageS2CPreparePayload{
- Problem: api.Problem{
- ProblemID: 1,
- Title: "the answer",
- Description: "print 42",
- },
- },
}
}
@@ -693,16 +686,10 @@ func (hubs *Hubs) RestoreFromDB(ctx context.Context) error {
if row.StartedAt.Valid {
startedAt = &row.StartedAt.Time
}
- var pr *problem
- if row.ProblemID != nil {
- if row.Title == nil || row.Description == nil {
- panic("inconsistent data")
- }
- pr = &problem{
- problemID: int(*row.ProblemID),
- title: *row.Title,
- description: *row.Description,
- }
+ pr := &problem{
+ problemID: int(row.ProblemID),
+ title: row.Title,
+ description: row.Description,
}
// TODO: N+1
playerRows, err := hubs.q.ListGamePlayers(ctx, int32(row.GameID))
diff --git a/backend/game/message.go b/backend/game/message.go
index 1fb30cb..2895119 100644
--- a/backend/game/message.go
+++ b/backend/game/message.go
@@ -24,7 +24,6 @@ type playerMessageC2SWithClient struct {
type playerMessageS2C = interface{}
type playerMessageS2CPrepare = api.GamePlayerMessageS2CPrepare
-type playerMessageS2CPreparePayload = api.GamePlayerMessageS2CPreparePayload
type playerMessageS2CStart = api.GamePlayerMessageS2CStart
type playerMessageS2CStartPayload = api.GamePlayerMessageS2CStartPayload
type playerMessageS2CExecResult = api.GamePlayerMessageS2CExecResult
diff --git a/backend/query.sql b/backend/query.sql
index bcbee12..408bf2d 100644
--- a/backend/query.sql
+++ b/backend/query.sql
@@ -30,12 +30,12 @@ SELECT EXISTS (
-- name: ListGames :many
SELECT * FROM games
-LEFT JOIN problems ON games.problem_id = problems.problem_id
+JOIN problems ON games.problem_id = problems.problem_id
ORDER BY games.game_id;
-- name: ListGamesForPlayer :many
SELECT * FROM games
-LEFT JOIN problems ON games.problem_id = problems.problem_id
+JOIN problems ON games.problem_id = problems.problem_id
JOIN game_players ON games.game_id = game_players.game_id
WHERE game_players.user_id = $1
ORDER BY games.game_id;
@@ -52,7 +52,7 @@ WHERE game_id = $1;
-- name: GetGameByID :one
SELECT * FROM games
-LEFT JOIN problems ON games.problem_id = problems.problem_id
+JOIN problems ON games.problem_id = problems.problem_id
WHERE games.game_id = $1
LIMIT 1;
diff --git a/backend/schema.sql b/backend/schema.sql
index 2779eaf..dc49363 100644
--- a/backend/schema.sql
+++ b/backend/schema.sql
@@ -37,7 +37,7 @@ CREATE TABLE games (
duration_seconds INT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
started_at TIMESTAMP,
- problem_id INT,
+ problem_id INT NOT NULL,
CONSTRAINT fk_problem_id FOREIGN KEY(problem_id) REFERENCES problems(problem_id)
);
CREATE INDEX idx_games_problem_id ON games(problem_id);
diff --git a/frontend/app/.server/api/schema.d.ts b/frontend/app/.server/api/schema.d.ts
index 719babb..93385f2 100644
--- a/frontend/app/.server/api/schema.d.ts
+++ b/frontend/app/.server/api/schema.d.ts
@@ -111,7 +111,7 @@ export interface components {
duration_seconds: number;
/** @example 946684800 */
started_at?: number;
- problem?: components["schemas"]["Problem"];
+ problem: components["schemas"]["Problem"];
players: components["schemas"]["User"][];
verification_steps: components["schemas"]["VerificationStep"][];
};
@@ -134,10 +134,6 @@ export interface components {
GamePlayerMessageS2CPrepare: {
/** @constant */
type: "player:s2c:prepare";
- data: components["schemas"]["GamePlayerMessageS2CPreparePayload"];
- };
- GamePlayerMessageS2CPreparePayload: {
- problem: components["schemas"]["Problem"];
};
GamePlayerMessageS2CStart: {
/** @constant */
diff --git a/frontend/app/components/GolfPlayApp.client.tsx b/frontend/app/components/GolfPlayApp.client.tsx
index 43828e6..70c463f 100644
--- a/frontend/app/components/GolfPlayApp.client.tsx
+++ b/frontend/app/components/GolfPlayApp.client.tsx
@@ -11,7 +11,6 @@ import GolfPlayAppWaiting from "./GolfPlayApps/GolfPlayAppWaiting";
type WebSocketMessage = components["schemas"]["GamePlayerMessageS2C"];
type Game = components["schemas"]["Game"];
-type Problem = components["schemas"]["Problem"];
type GameState = "connecting" | "waiting" | "starting" | "gaming" | "finished";
@@ -32,8 +31,6 @@ export default function GolfPlayApp({
const [gameState, setGameState] = useState<GameState>("connecting");
- const [problem, setProblem] = useState<Problem | null>(null);
-
const [startedAt, setStartedAt] = useState<number | null>(null);
const [timeLeftSeconds, setTimeLeftSeconds] = useState<number | null>(null);
@@ -105,8 +102,6 @@ export default function GolfPlayApp({
if (lastJsonMessage !== null) {
console.log(lastJsonMessage.type);
if (lastJsonMessage.type === "player:s2c:prepare") {
- const { problem } = lastJsonMessage.data;
- setProblem(problem);
console.log("player:c2s:ready");
sendJsonMessage({ type: "player:c2s:ready" });
} else if (lastJsonMessage.type === "player:s2c:start") {
@@ -148,7 +143,8 @@ export default function GolfPlayApp({
} else if (gameState === "gaming") {
return (
<GolfPlayAppGaming
- problem={problem!.description}
+ problemTitle={game.problem.title}
+ problemDescription={game.problem.description}
onCodeChange={onCodeChange}
onCodeSubmit={onCodeSubmit}
currentScore={currentScore}
diff --git a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
index fdf0e0c..31927a5 100644
--- a/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
+++ b/frontend/app/components/GolfPlayApps/GolfPlayAppGaming.tsx
@@ -1,7 +1,8 @@
import React, { useRef } from "react";
type Props = {
- problem: string;
+ problemTitle: string;
+ problemDescription: string;
onCodeChange: (code: string) => void;
onCodeSubmit: (code: string) => void;
currentScore: number | null;
@@ -9,7 +10,8 @@ type Props = {
};
export default function GolfPlayAppGaming({
- problem,
+ problemTitle,
+ problemDescription,
onCodeChange,
onCodeSubmit,
currentScore,
@@ -32,8 +34,8 @@ export default function GolfPlayAppGaming({
<div className="mx-auto flex min-h-full flex-grow">
<div className="flex w-1/2 flex-col justify-between p-4">
<div>
- <div className="mb-2 text-xl font-bold">TODO</div>
- <div className="text-gray-700">{problem}</div>
+ <div className="mb-2 text-xl font-bold">{problemTitle}</div>
+ <div className="text-gray-700">{problemDescription}</div>
</div>
<div className="mb-4 mt-auto">
<div className="mb-2">
diff --git a/openapi/api-server.yaml b/openapi/api-server.yaml
index 54f9f3c..16dd7c5 100644
--- a/openapi/api-server.yaml
+++ b/openapi/api-server.yaml
@@ -230,6 +230,7 @@ components:
- state
- display_name
- duration_seconds
+ - problem
- players
- verification_steps
VerificationStep:
@@ -276,18 +277,8 @@ components:
type:
type: string
const: "player:s2c:prepare"
- data:
- $ref: '#/components/schemas/GamePlayerMessageS2CPreparePayload'
required:
- type
- - data
- GamePlayerMessageS2CPreparePayload:
- type: object
- properties:
- problem:
- $ref: '#/components/schemas/Problem'
- required:
- - problem
GamePlayerMessageS2CStart:
type: object
properties: