From 0b520dc2529d7df6263842480d4ba7eaf07f4dcd Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Sat, 10 Aug 2024 14:06:28 +0900
Subject: feat(backend): include `players` in `Game` object

---
 backend/query.sql | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'backend/query.sql')

diff --git a/backend/query.sql b/backend/query.sql
index 13bbbe6..12b67b9 100644
--- a/backend/query.sql
+++ b/backend/query.sql
@@ -58,7 +58,7 @@ LIMIT 1;
 
 -- name: ListGamePlayers :many
 SELECT * FROM game_players
-LEFT JOIN users ON game_players.user_id = users.user_id
+JOIN users ON game_players.user_id = users.user_id
 WHERE game_players.game_id = $1
 ORDER BY game_players.user_id;
 
-- 
cgit v1.3.1


From 47f95342097e8828059053c168e06cd44e0ab43b Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Sat, 10 Aug 2024 19:55:28 +0900
Subject: feat(backend): include `verification_steps` in `Game` object

---
 backend/api/generated.go             | 76 ++++++++++++++++++++----------------
 backend/api/handler.go               | 33 ++++++++++++----
 backend/db/query.sql.go              | 26 ++++++++++++
 backend/query.sql                    |  5 +++
 frontend/app/.server/api/schema.d.ts |  7 ++++
 openapi.yaml                         | 18 +++++++++
 6 files changed, 123 insertions(+), 42 deletions(-)

(limited to 'backend/query.sql')

diff --git a/backend/api/generated.go b/backend/api/generated.go
index 2a113a4..b33747a 100644
--- a/backend/api/generated.go
+++ b/backend/api/generated.go
@@ -61,14 +61,15 @@ type Error struct {
 
 // Game defines model for Game.
 type Game struct {
-	DisplayName     string       `json:"display_name"`
-	DurationSeconds int          `json:"duration_seconds"`
-	GameID          int          `json:"game_id"`
-	GameType        GameGameType `json:"game_type"`
-	Players         []User       `json:"players"`
-	Problem         *Problem     `json:"problem,omitempty"`
-	StartedAt       *int         `json:"started_at,omitempty"`
-	State           GameState    `json:"state"`
+	DisplayName       string             `json:"display_name"`
+	DurationSeconds   int                `json:"duration_seconds"`
+	GameID            int                `json:"game_id"`
+	GameType          GameGameType       `json:"game_type"`
+	Players           []User             `json:"players"`
+	Problem           *Problem           `json:"problem,omitempty"`
+	StartedAt         *int               `json:"started_at,omitempty"`
+	State             GameState          `json:"state"`
+	VerificationSteps []VerificationStep `json:"verification_steps"`
 }
 
 // GameGameType defines model for Game.GameType.
@@ -228,6 +229,12 @@ type User struct {
 	Username    string  `json:"username"`
 }
 
+// VerificationStep defines model for VerificationStep.
+type VerificationStep struct {
+	Label      string                 `json:"label"`
+	TestcaseID nullable.Nullable[int] `json:"testcase_id"`
+}
+
 // HeaderAuthorization defines model for header_authorization.
 type HeaderAuthorization = string
 
@@ -1108,32 +1115,33 @@ func (sh *strictHandler) GetToken(ctx echo.Context, params GetTokenParams) error
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"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",
+	"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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 8830d1c..134a4f9 100644
--- a/backend/api/handler.go
+++ b/backend/api/handler.go
@@ -3,11 +3,13 @@ package api
 import (
 	"context"
 	"errors"
+	"fmt"
 	"log"
 	"net/http"
 
 	"github.com/jackc/pgx/v5"
 	"github.com/labstack/echo/v4"
+	"github.com/oapi-codegen/nullable"
 
 	"github.com/nsfisis/iosdc-japan-2024-albatross/backend/auth"
 	"github.com/nsfisis/iosdc-japan-2024-albatross/backend/db"
@@ -149,15 +151,30 @@ func (h *Handler) GetGame(ctx context.Context, request GetGameRequestObject, use
 			IsAdmin:     playerRow.IsAdmin,
 		}
 	}
+	testcaseIDs, err := h.q.ListTestcaseIDsByGameID(ctx, int32(gameID))
+	if err != nil {
+		return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+	}
+	verificationSteps := make([]VerificationStep, len(testcaseIDs)+1)
+	verificationSteps[0] = VerificationStep{
+		Label: "Compile",
+	}
+	for i, testcaseID := range testcaseIDs {
+		verificationSteps[i+1] = VerificationStep{
+			TestcaseID: nullable.NewNullableWithValue(int(testcaseID)),
+			Label:      fmt.Sprintf("Testcase %d", i+1),
+		}
+	}
 	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,
-		Players:         players,
+		GameID:            int(row.GameID),
+		GameType:          GameGameType(row.GameType),
+		State:             GameState(row.State),
+		DisplayName:       row.DisplayName,
+		DurationSeconds:   int(row.DurationSeconds),
+		StartedAt:         startedAt,
+		Problem:           problem,
+		Players:           players,
+		VerificationSteps: verificationSteps,
 	}
 	return GetGame200JSONResponse{
 		Game: game,
diff --git a/backend/db/query.sql.go b/backend/db/query.sql.go
index 392e6a6..cbef51d 100644
--- a/backend/db/query.sql.go
+++ b/backend/db/query.sql.go
@@ -403,6 +403,32 @@ func (q *Queries) ListGamesForPlayer(ctx context.Context, userID int32) ([]ListG
 	return items, nil
 }
 
+const listTestcaseIDsByGameID = `-- name: ListTestcaseIDsByGameID :many
+SELECT testcases.testcase_id FROM testcases
+WHERE testcases.problem_id = (SELECT problem_id FROM games WHERE game_id = $1)
+ORDER BY testcases.testcase_id
+`
+
+func (q *Queries) ListTestcaseIDsByGameID(ctx context.Context, gameID int32) ([]int32, error) {
+	rows, err := q.db.Query(ctx, listTestcaseIDsByGameID, gameID)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+	var items []int32
+	for rows.Next() {
+		var testcase_id int32
+		if err := rows.Scan(&testcase_id); err != nil {
+			return nil, err
+		}
+		items = append(items, testcase_id)
+	}
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+	return items, nil
+}
+
 const listTestcasesByGameID = `-- name: ListTestcasesByGameID :many
 SELECT testcase_id, problem_id, stdin, stdout FROM testcases
 WHERE testcases.problem_id = (SELECT problem_id FROM games WHERE game_id = $1)
diff --git a/backend/query.sql b/backend/query.sql
index 12b67b9..bcbee12 100644
--- a/backend/query.sql
+++ b/backend/query.sql
@@ -83,6 +83,11 @@ SELECT * FROM testcases
 WHERE testcases.problem_id = (SELECT problem_id FROM games WHERE game_id = $1)
 ORDER BY testcases.testcase_id;
 
+-- name: ListTestcaseIDsByGameID :many
+SELECT testcases.testcase_id FROM testcases
+WHERE testcases.problem_id = (SELECT problem_id FROM games WHERE game_id = $1)
+ORDER BY testcases.testcase_id;
+
 -- name: CreateSubmissionResult :exec
 INSERT INTO submission_results (submission_id, status, stdout, stderr)
 VALUES ($1, $2, $3, $4);
diff --git a/frontend/app/.server/api/schema.d.ts b/frontend/app/.server/api/schema.d.ts
index f7caebb..779f11e 100644
--- a/frontend/app/.server/api/schema.d.ts
+++ b/frontend/app/.server/api/schema.d.ts
@@ -113,6 +113,13 @@ export interface components {
             started_at?: number;
             problem?: components["schemas"]["Problem"];
             players: components["schemas"]["User"][];
+            verification_steps: components["schemas"]["VerificationStep"][];
+        };
+        VerificationStep: {
+            /** @example 1 */
+            testcase_id: number | null;
+            /** @example Test case 1 */
+            label: string;
         };
         Problem: {
             /** @example 1 */
diff --git a/openapi.yaml b/openapi.yaml
index fdd0146..6d9dea3 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -220,6 +220,10 @@ components:
           type: array
           items:
             $ref: '#/components/schemas/User'
+        verification_steps:
+          type: array
+          items:
+            $ref: '#/components/schemas/VerificationStep'
       required:
         - game_id
         - game_type
@@ -227,6 +231,20 @@ components:
         - display_name
         - duration_seconds
         - players
+        - verification_steps
+    VerificationStep:
+      type: object
+      properties:
+        testcase_id:
+          type: integer
+          nullable: true
+          example: 1
+        label:
+          type: string
+          example: "Test case 1"
+      required:
+        - testcase_id
+        - label
     Problem:
       type: object
       properties:
-- 
cgit v1.3.1

