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
|
DeleteProblem(c *fiber.Ctx, id int32) error
|
||||||
GetProblem(c *fiber.Ctx, id int32) error
|
GetProblem(c *fiber.Ctx, id int32) error
|
||||||
UpdateProblem(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
|
ListSolutions(c *fiber.Ctx, params testerv1.ListSolutionsParams) error
|
||||||
CreateSolution(c *fiber.Ctx, params testerv1.CreateSolutionParams) error
|
CreateSolution(c *fiber.Ctx, params testerv1.CreateSolutionParams) error
|
||||||
GetSolution(c *fiber.Ctx, id int32) error
|
GetSolution(c *fiber.Ctx, id int32) error
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package rest
|
package rest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
"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/internal/tester"
|
||||||
"git.sch9.ru/new_gate/ms-tester/pkg"
|
"git.sch9.ru/new_gate/ms-tester/pkg"
|
||||||
testerv1 "git.sch9.ru/new_gate/ms-tester/proto/tester/v1"
|
testerv1 "git.sch9.ru/new_gate/ms-tester/proto/tester/v1"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TesterHandlers struct {
|
type TesterHandlers struct {
|
||||||
|
@ -240,6 +241,23 @@ func (h *TesterHandlers) UpdateProblem(c *fiber.Ctx, id int32) error {
|
||||||
return c.SendStatus(fiber.StatusOK)
|
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 {
|
func (h *TesterHandlers) UpdateContest(c *fiber.Ctx, id int32) error {
|
||||||
var req testerv1.UpdateContestRequest
|
var req testerv1.UpdateContestRequest
|
||||||
err := c.BodyParser(&req)
|
err := c.BodyParser(&req)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
"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/internal/tester"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
|
|
@ -2,6 +2,7 @@ package tester
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,6 +12,7 @@ type ProblemUseCase interface {
|
||||||
DeleteProblem(ctx context.Context, id int32) error
|
DeleteProblem(ctx context.Context, id int32) error
|
||||||
ListProblems(ctx context.Context, filter models.ProblemsFilter) (*models.ProblemsList, error)
|
ListProblems(ctx context.Context, filter models.ProblemsFilter) (*models.ProblemsList, error)
|
||||||
UpdateProblem(ctx context.Context, id int32, problem models.ProblemUpdate) error
|
UpdateProblem(ctx context.Context, id int32, problem models.ProblemUpdate) error
|
||||||
|
UploadProblem(ctx context.Context, id int32, archive []byte) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContestUseCase interface {
|
type ContestUseCase interface {
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
package usecase
|
package usecase
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
"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/internal/tester"
|
||||||
"git.sch9.ru/new_gate/ms-tester/pkg"
|
"git.sch9.ru/new_gate/ms-tester/pkg"
|
||||||
"github.com/microcosm-cc/bluemonday"
|
"github.com/microcosm-cc/bluemonday"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProblemUseCase struct {
|
type ProblemUseCase struct {
|
||||||
|
@ -115,6 +120,116 @@ func (u *ProblemUseCase) UpdateProblem(ctx context.Context, id int32, problemUpd
|
||||||
return nil
|
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 {
|
func isEmpty(p models.ProblemUpdate) bool {
|
||||||
return p.Title == nil &&
|
return p.Title == nil &&
|
||||||
p.Legend == nil &&
|
p.Legend == nil &&
|
||||||
|
|
2
proto
2
proto
|
@ -1 +1 @@
|
||||||
Subproject commit 1fbee7ba29c358c76d1c835ac6999ce9e1b59ee9
|
Subproject commit f00483d24a53a243734c793fc24e02d52d39fdab
|
Loading…
Add table
Reference in a new issue