aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--backend/api/generated.go67
-rw-r--r--backend/api/handler.go22
-rw-r--r--backend/db/models.go1
-rw-r--r--backend/db/query.sql.go8
-rw-r--r--backend/fixtures/dev.sql16
-rw-r--r--backend/game/hub.go12
-rw-r--r--backend/schema.sql1
-rw-r--r--backend/taskqueue/processor.go2
-rw-r--r--backend/taskqueue/queue.go2
-rw-r--r--backend/taskqueue/tasks.go3
10 files changed, 87 insertions, 47 deletions
diff --git a/backend/api/generated.go b/backend/api/generated.go
index 8a74b01..15f1c17 100644
--- a/backend/api/generated.go
+++ b/backend/api/generated.go
@@ -39,6 +39,12 @@ const (
N1V1 GameGameType = "1v1"
)
+// Defines values for ProblemLanguage.
+const (
+ Php ProblemLanguage = "php"
+ Swift ProblemLanguage = "swift"
+)
+
// Error defines model for Error.
type Error struct {
Message string `json:"message"`
@@ -72,12 +78,16 @@ type LatestGameState struct {
// Problem defines model for Problem.
type Problem struct {
- Description string `json:"description"`
- ProblemID int `json:"problem_id"`
- SampleCode string `json:"sample_code"`
- Title string `json:"title"`
+ Description string `json:"description"`
+ Language ProblemLanguage `json:"language"`
+ ProblemID int `json:"problem_id"`
+ SampleCode string `json:"sample_code"`
+ Title string `json:"title"`
}
+// ProblemLanguage defines model for Problem.Language.
+type ProblemLanguage string
+
// RankingEntry defines model for RankingEntry.
type RankingEntry struct {
Code nullable.Nullable[string] `json:"code"`
@@ -1130,30 +1140,31 @@ func (sh *strictHandler) PostLogin(ctx echo.Context) error {
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
+ "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",
+ "KoN2UB8AAA==",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/backend/api/handler.go b/backend/api/handler.go
index 67f859c..4321d15 100644
--- a/backend/api/handler.go
+++ b/backend/api/handler.go
@@ -21,8 +21,8 @@ type Handler struct {
}
type GameHubInterface interface {
- CalcCodeSize(code string) int
- EnqueueTestTasks(ctx context.Context, submissionID, gameID, userID int, code string) error
+ CalcCodeSize(code string, language string) int
+ EnqueueTestTasks(ctx context.Context, submissionID, gameID, userID int, language, code string) error
}
func (h *Handler) PostLogin(ctx context.Context, request PostLoginRequestObject) (PostLoginResponseObject, error) {
@@ -88,6 +88,7 @@ func (h *Handler) GetGames(ctx context.Context, _ GetGamesRequestObject, _ *auth
ProblemID: int(row.ProblemID),
Title: row.Title,
Description: row.Description,
+ Language: ProblemLanguage(*row.Language),
SampleCode: row.SampleCode,
},
}
@@ -166,6 +167,7 @@ func (h *Handler) GetGame(ctx context.Context, request GetGameRequestObject, _ *
ProblemID: int(row.ProblemID),
Title: row.Title,
Description: row.Description,
+ Language: ProblemLanguage(*row.Language),
SampleCode: row.SampleCode,
},
MainPlayers: mainPlayers,
@@ -294,10 +296,20 @@ func (h *Handler) PostGamePlaySubmit(ctx context.Context, request PostGamePlaySu
gameID := request.GameID
userID := user.UserID
code := request.Body.Code
- codeSize := h.hub.CalcCodeSize(code)
+
+ gameRow, err := h.q.GetGameByID(ctx, int32(gameID))
+ if err != nil {
+ if errors.Is(err, pgx.ErrNoRows) {
+ return PostGamePlaySubmit404JSONResponse{}, nil
+ }
+ return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ }
+
+ language := *gameRow.Language
+ codeSize := h.hub.CalcCodeSize(code, language)
// TODO: check if the game is running
// TODO: transaction
- err := h.q.UpdateCodeAndStatus(ctx, db.UpdateCodeAndStatusParams{
+ err = h.q.UpdateCodeAndStatus(ctx, db.UpdateCodeAndStatusParams{
GameID: int32(gameID),
UserID: int32(userID),
Code: code,
@@ -315,7 +327,7 @@ func (h *Handler) PostGamePlaySubmit(ctx context.Context, request PostGamePlaySu
if err != nil {
return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
- err = h.hub.EnqueueTestTasks(ctx, int(submissionID), gameID, userID, code)
+ err = h.hub.EnqueueTestTasks(ctx, int(submissionID), gameID, userID, language, code)
if err != nil {
return nil, echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
diff --git a/backend/db/models.go b/backend/db/models.go
index 9bb8ccb..c7d649c 100644
--- a/backend/db/models.go
+++ b/backend/db/models.go
@@ -36,6 +36,7 @@ type Problem struct {
ProblemID int32
Title string
Description string
+ Language *string
SampleCode string
}
diff --git a/backend/db/query.sql.go b/backend/db/query.sql.go
index d4e134f..f70cd29 100644
--- a/backend/db/query.sql.go
+++ b/backend/db/query.sql.go
@@ -128,7 +128,7 @@ func (q *Queries) CreateUserAuth(ctx context.Context, arg CreateUserAuthParams)
}
const getGameByID = `-- name: GetGameByID :one
-SELECT game_id, game_type, is_public, display_name, duration_seconds, created_at, started_at, games.problem_id, problems.problem_id, title, description, sample_code FROM games
+SELECT game_id, game_type, is_public, display_name, duration_seconds, created_at, started_at, games.problem_id, problems.problem_id, title, description, language, sample_code FROM games
JOIN problems ON games.problem_id = problems.problem_id
WHERE games.game_id = $1
LIMIT 1
@@ -146,6 +146,7 @@ type GetGameByIDRow struct {
ProblemID_2 int32
Title string
Description string
+ Language *string
SampleCode string
}
@@ -164,6 +165,7 @@ func (q *Queries) GetGameByID(ctx context.Context, gameID int32) (GetGameByIDRow
&i.ProblemID_2,
&i.Title,
&i.Description,
+ &i.Language,
&i.SampleCode,
)
return i, err
@@ -575,7 +577,7 @@ func (q *Queries) ListMainPlayers(ctx context.Context, dollar_1 []int32) ([]List
}
const listPublicGames = `-- name: ListPublicGames :many
-SELECT game_id, game_type, is_public, display_name, duration_seconds, created_at, started_at, games.problem_id, problems.problem_id, title, description, sample_code FROM games
+SELECT game_id, game_type, is_public, display_name, duration_seconds, created_at, started_at, games.problem_id, problems.problem_id, title, description, language, sample_code FROM games
JOIN problems ON games.problem_id = problems.problem_id
WHERE is_public = true
ORDER BY games.game_id
@@ -593,6 +595,7 @@ type ListPublicGamesRow struct {
ProblemID_2 int32
Title string
Description string
+ Language *string
SampleCode string
}
@@ -617,6 +620,7 @@ func (q *Queries) ListPublicGames(ctx context.Context) ([]ListPublicGamesRow, er
&i.ProblemID_2,
&i.Title,
&i.Description,
+ &i.Language,
&i.SampleCode,
); err != nil {
return nil, err
diff --git a/backend/fixtures/dev.sql b/backend/fixtures/dev.sql
index 1df6353..bc25011 100644
--- a/backend/fixtures/dev.sql
+++ b/backend/fixtures/dev.sql
@@ -13,15 +13,15 @@ VALUES
(3, 'password', '$2a$10$F/TePpu1pyJRWgn0e6A14.VL9D/17sRxT/2DyZ2Oi4Eg/lR6n7JcK');
INSERT INTO problems
-(title, description, sample_code)
+(title, description, language, sample_code)
VALUES
- ('TEST problem 1', 'This is TEST problem 1', 'sample code'),
- ('TEST problem 2', 'This is TEST problem 2', 'sample code'),
- ('TEST problem 3', 'This is TEST problem 3', 'sample code'),
- ('TEST problem 4', 'This is TEST problem 4', 'sample code'),
- ('TEST problem 5', 'This is TEST problem 5', 'sample code'),
- ('TEST problem 6', 'This is TEST problem 6', 'sample code'),
- ('TEST problem 7', 'This is TEST problem 7', 'sample code');
+ ('TEST problem 1', 'This is TEST problem 1', 'php', 'sample code'),
+ ('TEST problem 2', 'This is TEST problem 2', 'php', 'sample code'),
+ ('TEST problem 3', 'This is TEST problem 3', 'php', 'sample code'),
+ ('TEST problem 4', 'This is TEST problem 4', 'php', 'sample code'),
+ ('TEST problem 5', 'This is TEST problem 5', 'php', 'sample code'),
+ ('TEST problem 6', 'This is TEST problem 6', 'php', 'sample code'),
+ ('TEST problem 7', 'This is TEST problem 7', 'php', 'sample code');
INSERT INTO games
(game_type, is_public, display_name, duration_seconds, problem_id)
diff --git a/backend/game/hub.go b/backend/game/hub.go
index 3697b4a..8f27466 100644
--- a/backend/game/hub.go
+++ b/backend/game/hub.go
@@ -36,12 +36,17 @@ func (hub *Hub) Run() {
go hub.processTaskResults()
}
-func (hub *Hub) CalcCodeSize(code string) int {
+func (hub *Hub) CalcCodeSize(code string, language string) int {
re := regexp.MustCompile(`\s+`)
- return len(strings.TrimSuffix(strings.TrimPrefix(strings.TrimPrefix(re.ReplaceAllString(code, ""), "<?php"), "<?"), "?>"))
+ trimmed := re.ReplaceAllString(code, "")
+ if language == "php" {
+ return len(strings.TrimSuffix(strings.TrimPrefix(strings.TrimPrefix(trimmed, "<?php"), "<?"), "?>"))
+ } else {
+ return len(trimmed)
+ }
}
-func (hub *Hub) EnqueueTestTasks(ctx context.Context, submissionID, gameID, userID int, code string) error {
+func (hub *Hub) EnqueueTestTasks(ctx context.Context, submissionID, gameID, userID int, language, code string) error {
rows, err := hub.q.ListTestcasesByGameID(ctx, int32(gameID))
if err != nil {
return err
@@ -52,6 +57,7 @@ func (hub *Hub) EnqueueTestTasks(ctx context.Context, submissionID, gameID, user
userID,
submissionID,
int(row.TestcaseID),
+ language,
code,
row.Stdin,
row.Stdout,
diff --git a/backend/schema.sql b/backend/schema.sql
index 6408cbc..cd4ed4c 100644
--- a/backend/schema.sql
+++ b/backend/schema.sql
@@ -22,6 +22,7 @@ CREATE TABLE problems (
problem_id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
+ language VARCHAR(8) /* NOT NULL */,
sample_code TEXT NOT NULL
);
diff --git a/backend/taskqueue/processor.go b/backend/taskqueue/processor.go
index 42714f5..8dadfdf 100644
--- a/backend/taskqueue/processor.go
+++ b/backend/taskqueue/processor.go
@@ -39,7 +39,7 @@ func (p *processor) doProcessTaskRunTestcase(
if err != nil {
return nil, fmt.Errorf("json.Marshal failed: %v", err)
}
- req, err := http.NewRequest("POST", "http://worker-php:80/exec", bytes.NewBuffer(reqJSON))
+ req, err := http.NewRequest("POST", "http://worker-"+payload.Language+":80/exec", bytes.NewBuffer(reqJSON))
if err != nil {
return nil, fmt.Errorf("http.NewRequest failed: %v", err)
}
diff --git a/backend/taskqueue/queue.go b/backend/taskqueue/queue.go
index b348fca..60844d2 100644
--- a/backend/taskqueue/queue.go
+++ b/backend/taskqueue/queue.go
@@ -25,6 +25,7 @@ func (q *Queue) EnqueueTaskRunTestcase(
userID int,
submissionID int,
testcaseID int,
+ language string,
code string,
stdin string,
stdout string,
@@ -34,6 +35,7 @@ func (q *Queue) EnqueueTaskRunTestcase(
userID,
submissionID,
testcaseID,
+ language,
code,
stdin,
stdout,
diff --git a/backend/taskqueue/tasks.go b/backend/taskqueue/tasks.go
index f4cba20..943943f 100644
--- a/backend/taskqueue/tasks.go
+++ b/backend/taskqueue/tasks.go
@@ -17,6 +17,7 @@ type TaskPayloadRunTestcase struct {
UserID int
SubmissionID int
TestcaseID int
+ Language string
Code string
Stdin string
Stdout string
@@ -27,6 +28,7 @@ func newTaskRunTestcase(
userID int,
submissionID int,
testcaseID int,
+ language string,
code string,
stdin string,
stdout string,
@@ -36,6 +38,7 @@ func newTaskRunTestcase(
UserID: userID,
SubmissionID: submissionID,
TestcaseID: testcaseID,
+ Language: language,
Code: code,
Stdin: stdin,
Stdout: stdout,