feat: UploadProblem
This commit is contained in:
parent
2ab7a16ddf
commit
01ed1de8c3
6 changed files with 140 additions and 3 deletions
|
@ -20,6 +20,7 @@ type Handlers interface {
|
|||
DeleteProblem(c *fiber.Ctx, id int32) error
|
||||
GetProblem(c *fiber.Ctx, id int32) error
|
||||
UpdateProblem(c *fiber.Ctx, id int32) error
|
||||
UploadProblem(c *fiber.Ctx, id int32) error
|
||||
ListSolutions(c *fiber.Ctx, params testerv1.ListSolutionsParams) error
|
||||
CreateSolution(c *fiber.Ctx, params testerv1.CreateSolutionParams) error
|
||||
GetSolution(c *fiber.Ctx, id int32) error
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/tester"
|
||||
"git.sch9.ru/new_gate/ms-tester/pkg"
|
||||
testerv1 "git.sch9.ru/new_gate/ms-tester/proto/tester/v1"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"io"
|
||||
)
|
||||
|
||||
type TesterHandlers struct {
|
||||
|
@ -240,6 +241,23 @@ func (h *TesterHandlers) UpdateProblem(c *fiber.Ctx, id int32) error {
|
|||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func (h *TesterHandlers) UploadProblem(c *fiber.Ctx, id int32) error {
|
||||
var req testerv1.UploadProblemRequest
|
||||
err := c.BodyParser(&req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := req.Archive.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = h.problemsUC.UploadProblem(c.Context(), id, data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *TesterHandlers) UpdateContest(c *fiber.Ctx, id int32) error {
|
||||
var req testerv1.UpdateContestRequest
|
||||
err := c.BodyParser(&req)
|
||||
|
|
|
@ -2,6 +2,7 @@ package repository
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/tester"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
|
|
@ -2,6 +2,7 @@ package tester
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||
)
|
||||
|
||||
|
@ -11,6 +12,7 @@ type ProblemUseCase interface {
|
|||
DeleteProblem(ctx context.Context, id int32) error
|
||||
ListProblems(ctx context.Context, filter models.ProblemsFilter) (*models.ProblemsList, error)
|
||||
UpdateProblem(ctx context.Context, id int32, problem models.ProblemUpdate) error
|
||||
UploadProblem(ctx context.Context, id int32, archive []byte) error
|
||||
}
|
||||
|
||||
type ContestUseCase interface {
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package usecase
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||
"git.sch9.ru/new_gate/ms-tester/internal/tester"
|
||||
"git.sch9.ru/new_gate/ms-tester/pkg"
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ProblemUseCase struct {
|
||||
|
@ -115,6 +120,116 @@ func (u *ProblemUseCase) UpdateProblem(ctx context.Context, id int32, problemUpd
|
|||
return nil
|
||||
}
|
||||
|
||||
type ProblemProperties struct {
|
||||
Title string `json:"name"`
|
||||
TimeLimit int32 `json:"timeLimit"`
|
||||
MemoryLimit int32 `json:"memoryLimit"`
|
||||
}
|
||||
|
||||
func (u *ProblemUseCase) UploadProblem(ctx context.Context, id int32, data []byte) error {
|
||||
|
||||
locale := "russian"
|
||||
defaultLocale := "english"
|
||||
var localeProblem, defaultProblem string
|
||||
var localeProperties, defaultProperties ProblemProperties
|
||||
|
||||
r := bytes.NewReader(data)
|
||||
rc, err := zip.NewReader(r, int64(r.Len()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
testsZipBuf := new(bytes.Buffer)
|
||||
w := zip.NewWriter(testsZipBuf)
|
||||
|
||||
for _, f := range rc.File {
|
||||
if f.FileInfo().IsDir() {
|
||||
continue
|
||||
}
|
||||
if f.Name == fmt.Sprintf("statements/%s/problem.tex", locale) {
|
||||
localeProblem, err = readProblem(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if f.Name == fmt.Sprintf("statements/%s/problem.tex", defaultLocale) {
|
||||
defaultProblem, err = readProblem(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if f.Name == fmt.Sprintf("statements/%s/problem-properties.json", locale) {
|
||||
localeProperties, err = readProperties(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if f.Name == fmt.Sprintf("statements/%s/problem-properties.json", defaultLocale) {
|
||||
defaultProperties, err = readProperties(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(f.Name, "tests/") {
|
||||
if err := w.Copy(f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := w.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
// testsZipBuf contains test files; this is for s3
|
||||
|
||||
localeProperties.MemoryLimit /= 1024 * 1024
|
||||
defaultProperties.MemoryLimit /= 1024 * 1024
|
||||
|
||||
var problemUpdate models.ProblemUpdate
|
||||
if localeProblem != "" {
|
||||
problemUpdate.Legend = &localeProblem
|
||||
problemUpdate.Title = &localeProperties.Title
|
||||
problemUpdate.TimeLimit = &localeProperties.TimeLimit
|
||||
problemUpdate.MemoryLimit = &localeProperties.MemoryLimit
|
||||
} else {
|
||||
problemUpdate.Legend = &defaultProblem
|
||||
problemUpdate.Title = &defaultProperties.Title
|
||||
problemUpdate.TimeLimit = &defaultProperties.TimeLimit
|
||||
problemUpdate.MemoryLimit = &defaultProperties.MemoryLimit
|
||||
}
|
||||
if err := u.UpdateProblem(ctx, id, problemUpdate); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readProblem(f *zip.File) (string, error) {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rc.Close()
|
||||
problemData, err := io.ReadAll(rc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(problemData), nil
|
||||
}
|
||||
|
||||
func readProperties(f *zip.File) (ProblemProperties, error) {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return ProblemProperties{}, err
|
||||
}
|
||||
defer rc.Close()
|
||||
var properties ProblemProperties
|
||||
if err := json.NewDecoder(rc).Decode(&properties); err != nil {
|
||||
return ProblemProperties{}, err
|
||||
}
|
||||
return properties, nil
|
||||
}
|
||||
|
||||
func isEmpty(p models.ProblemUpdate) bool {
|
||||
return p.Title == nil &&
|
||||
p.Legend == nil &&
|
||||
|
|
2
proto
2
proto
|
@ -1 +1 @@
|
|||
Subproject commit 1fbee7ba29c358c76d1c835ac6999ce9e1b59ee9
|
||||
Subproject commit f00483d24a53a243734c793fc24e02d52d39fdab
|
Loading…
Add table
Reference in a new issue