From e7acaa92a5e80cd0b0d30f20255d306b3ead7669 Mon Sep 17 00:00:00 2001 From: NeonXP Date: Sat, 6 Jan 2024 08:44:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=20=D1=84=D1=80=D0=BE=D0=BD=D1=82=20=D0=B8=20=D0=B1?= =?UTF-8?q?=D0=B5=D0=BA=20=D0=B4=D0=BE=20=D1=81=D0=BE=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D1=8F=D0=BD=D0=B8=D1=8F=20=D0=B1=D0=BB=D0=B8=D0=B7=D0=BA=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=BA=20MVP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/openapi.yaml | 48 +++++-- api/server.go | 43 +++--- api/types.go | 58 ++++++-- docker-compose.yml | 20 --- frontend/package-lock.json | 9 ++ frontend/package.json | 1 + frontend/public/logo.png | Bin 0 -> 23704 bytes frontend/public/logo_small.png | Bin 0 -> 4363 bytes frontend/src/App.jsx | 25 +--- frontend/src/assets/TiltNeon-Regular.ttf | Bin 95380 -> 0 bytes frontend/src/assets/logo.png | Bin 0 -> 23704 bytes frontend/src/assets/logo_small.png | Bin 0 -> 4363 bytes frontend/src/assets/react.svg | 1 - frontend/src/assets/styles.css | 23 ++- frontend/src/components/Layout.jsx | 58 ++++---- frontend/src/pages/Admin.jsx | 31 ---- frontend/src/pages/AdminGame.jsx | 102 ------------- frontend/src/pages/Engine.jsx | 75 ++++++++++ frontend/src/pages/Index.jsx | 67 ++++++--- frontend/src/pages/Team.jsx | 175 ----------------------- frontend/src/pages/TeamNew.jsx | 52 ------- frontend/src/pages/Teams.jsx | 37 ----- pkg/controller/admin.go | 18 ++- pkg/controller/engine.go | 53 ++++--- pkg/controller/game.go | 19 ++- pkg/controller/user.go | 33 +++-- pkg/models/cursor.go | 19 ++- pkg/models/model.go | 3 +- pkg/models/task.go | 11 +- pkg/service/engine.go | 133 ++++++++++------- pkg/service/game.go | 36 +++-- pkg/service/user.go | 18 ++- pkg/utils/exp.go | 11 ++ requests.http | 120 ++++++++++++++-- views/engine/view.gotmpl | 83 ----------- views/index.gotmpl | 48 ------- views/layout.gotmpl | 67 --------- views/user/login.gotmpl | 27 ---- views/user/register.gotmpl | 39 ----- 39 files changed, 626 insertions(+), 937 deletions(-) create mode 100644 frontend/public/logo.png create mode 100644 frontend/public/logo_small.png delete mode 100644 frontend/src/assets/TiltNeon-Regular.ttf create mode 100644 frontend/src/assets/logo.png create mode 100644 frontend/src/assets/logo_small.png delete mode 100644 frontend/src/assets/react.svg delete mode 100644 frontend/src/pages/Admin.jsx delete mode 100644 frontend/src/pages/AdminGame.jsx create mode 100644 frontend/src/pages/Engine.jsx delete mode 100644 frontend/src/pages/Team.jsx delete mode 100644 frontend/src/pages/TeamNew.jsx delete mode 100644 frontend/src/pages/Teams.jsx create mode 100644 pkg/utils/exp.go delete mode 100644 views/engine/view.gotmpl delete mode 100644 views/index.gotmpl delete mode 100644 views/layout.gotmpl delete mode 100644 views/user/login.gotmpl delete mode 100644 views/user/register.gotmpl diff --git a/api/openapi.yaml b/api/openapi.yaml index aa7e655..1671577 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -69,7 +69,8 @@ paths: in: path required: true schema: - type: integer + type: string + format: uuid responses: 200: $ref: '#/components/responses/taskResponse' @@ -81,7 +82,8 @@ paths: in: path required: true schema: - type: integer + type: string + format: uuid requestBody: $ref: "#/components/requestBodies/enterCodeRequest" responses: @@ -94,7 +96,8 @@ components: type: object properties: id: - type: integer + type: string + format: uuid username: type: string required: [ id, username ] @@ -102,21 +105,44 @@ components: type: object properties: id: - type: integer + type: string + format: uuid title: type: string description: type: string type: $ref: "#/components/schemas/gameType" + points: + type: integer + taskCount: + type: integer + createdAt: + type: string + authors: + type: array + items: + $ref: "#/components/schemas/userView" required: - id - title - description - type + - points + - taskCount + - createdAt + - authors taskView: type: object properties: + message: + type: string + enum: + - ok_code + - invalid_code + - old_code + - next_level + - game_complete title: type: string text: @@ -125,10 +151,6 @@ components: type: array items: $ref: '#/components/schemas/codeView' - entered: - type: array - items: - $ref: '#/components/schemas/codeView' solutions: type: array items: @@ -137,7 +159,6 @@ components: - title - text - codes - - entered - solutions codeView: type: object @@ -278,7 +299,8 @@ components: type: object properties: id: - type: integer + type: string + format: uuid username: type: string email: @@ -287,6 +309,10 @@ components: type: integer level: type: integer + expToCurrentLevel: + type: integer + expToNextLevel: + type: integer games: type: array items: @@ -297,6 +323,8 @@ components: - email - experience - level + - expToCurrentLevel + - expToNextLevel - games errorResponse: description: '' diff --git a/api/server.go b/api/server.go index b911cd5..a76693a 100644 --- a/api/server.go +++ b/api/server.go @@ -16,16 +16,17 @@ import ( "github.com/getkin/kin-openapi/openapi3" "github.com/labstack/echo/v4" "github.com/oapi-codegen/runtime" + openapi_types "github.com/oapi-codegen/runtime/types" ) // ServerInterface represents all server handlers. type ServerInterface interface { // (GET /engine/{uid}) - GameEngine(ctx echo.Context, uid int) error + GameEngine(ctx echo.Context, uid openapi_types.UUID) error // (POST /engine/{uid}/code) - EnterCode(ctx echo.Context, uid int) error + EnterCode(ctx echo.Context, uid openapi_types.UUID) error // (GET /games) GetGames(ctx echo.Context) error @@ -55,7 +56,7 @@ type ServerInterfaceWrapper struct { func (w *ServerInterfaceWrapper) GameEngine(ctx echo.Context) error { var err error // ------------- Path parameter "uid" ------------- - var uid int + var uid openapi_types.UUID err = runtime.BindStyledParameterWithLocation("simple", false, "uid", runtime.ParamLocationPath, ctx.Param("uid"), &uid) if err != nil { @@ -73,7 +74,7 @@ func (w *ServerInterfaceWrapper) GameEngine(ctx echo.Context) error { func (w *ServerInterfaceWrapper) EnterCode(ctx echo.Context) error { var err error // ------------- Path parameter "uid" ------------- - var uid int + var uid openapi_types.UUID err = runtime.BindStyledParameterWithLocation("simple", false, "uid", runtime.ParamLocationPath, ctx.Param("uid"), &uid) if err != nil { @@ -187,22 +188,24 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/8xYTY+kRgz9K5GTIxp6P07cktVqFGUPyWSTS6sPFfAwtQtVpFz0bmvEf49cfDQ0BU0T", - "ZrWnGRXGfu/Zxq5+hljnhVaoLEH0DAb/LZHsLzqR6A5QWTTvdIIP9RM+i7WyqNy/oigyGQsrtQo/kVZ8", - "RvET5oL/K4wu0NjGVawT5L/2VCBEQNZIlUJVBS6qNJhAtK+tDkFrpf/5hLGFamhmTYlVAKnI8X0i7Rps", - "Pxl8hAh+DM8ChPVTClu/E2EznUr1P4TAXMjMo0QAhSD6ok1yXabaR++NhZIZTCVZNN8a/vnha+/TktAo", - "kS8okM4yGIvQj7JIEHdChVbUcDNGm4fmZLtal8piioaJ5kgk0qWNcLb300mQYiMLxgQRQNMTHyTZVSSk", - "xZyWdMffEr9wtAaSMEac5hCtQrMMhD+oFfR586DsdC4ol+YGxTPdYPi1QCNRxRPFxarQBokMQCb+CBke", - "MfM/Wt7CkjvV08c9em2kltOy8q+CRtSuCd1nfOkounB4jUbfOJgaXPUDJ/M3gOGL302zUfz5MAEUWjZ7", - "wTjb3AvLS42t64k6LjUrbeaXoT64XsQf2e5SltptcJEl57JF3zGcku1jAwBVmbPPozS2FFyVsbSn3mtn", - "zF1T3az2VMu9kD6uCWdE8mlCOivZxl9O4rFZLDwc8Ku9Xsm1g8Z6Lr5f4I3i+wJ39evt4eV90H2SPH3Q", - "klvubZAOX2f5WU+X1EQLOT9BQ7UPdEqq6c/dbVJNTSd3K8FkE1/rZZ/y+EKyt6TnE8CMMC6NtKc/GW8r", - "vf4s8efSPjmWPC3rIwigntlASNRr/whEIX/DZquT6lE74DUDUH+4C1cARzRUT99Xd7u7HbPUBSpRSIjg", - "zd2ru51byu2TgxGiSqXC8LmUScUHKTqluErcbvRrAhHc88Byhu5dI3K0aAiifQOd/Z2Bl+5LNlzsg95y", - "dfk1qA4XS//r3W4q5Z1dOFgoKyfKgE3YDvNCk4fT+/Ye/YKU2qv7aZpN73Yfjq721Va6dGuoP71o753B", - "mnCj602/4CHaH9za4svAO4PC4n29cd4s1uVPDdVa8FPAhz26h5jhap6GIsmlgkN1cNry2jwn7V/kRujt", - "4AaXlyqAt7s3118a3peb9LOnsPuRxJ+N3zU5qB+c2YqE1P6rbZjubmd6UXV93rq0i4iz3Qj/29GqCFTG", - "MRL90LjeGnH/J6F5zA+t5Yp8dVG+n5TNNuCBv6mE5th+pkuTQQQhT7bqUP0XAAD//zkXlqI5FQAA", + "H4sIAAAAAAAC/8xYS2/jNhD+K8W0RyHyPk66bYNFUDQo2jTtJTACVpo43EikSo68MQL992Koh2WLtBVV", + "TfcUhxzNfPPNg0O+QKqLUitUZCF5AYN/V2jpR51JdAuoCM2lzvCm2eG1VCtC5X6KssxlKkhqFX+xWvGa", + "TR+xEPyrNLpEQ62qVGfIf2lXIiRgyUi1gbqOnFVpMIPkrpFaR52U/usLpgT1oRiZCusINqLAz5mkOdh+", + "MPgACXwf7wmIm10bd3oDZnO9kepfEIGFkLmHiQhKYe1XbbLzNDU6Bl9MpMzgRlpC89bw95vvvbuVRaNE", + "MSFBesloTMLQyiRC3IottbKtb8Zoc9OuLJfrUhFu0LCjBVorNlMLYS/vdydDmxpZMiZIANqauJaWZjkh", + "CQs7pTr+lPiVrbWQhDFidwrRLDTTQPiNkrBPixtlpaeMcmoukDzhAsPn8lZfVsagomvcYu7PMSf2Cz6f", + "kUEjUaWBPGWC7QI5EYF0/eBBm0IQJFBVkgt15Fsexjq9OTjVng4x8Laz5GNzRF3Hw7Tqq6M2pn0PcKfI", + "1JPwSOE5X4fCUejcbDZcaN4Ahs9+f5iO7J82E0GpZTuWjFOCS3F6erJ0c6CP05Mk5X4amoXziX/Lcse0", + "NGqjoyg5lR363sMQbbctAFRVwTq30lAlOCtTSbvBZ3vMfSGO2BYVPWoznTOuolBJpwYFYfaJZqTP5IZw", + "LvyXulIU2P5vYtrgPBXYFvMQ4JCtqI+CL+RW5xWr81eLeGjHNo+7+EznC7VR0Eqfsh/In2Xs+wz35elt", + "UdNTtu+4npTtnJuu7SAcvsbh9zqcfYEO4fREratDoCGqwt38dVSFqnswonadRz/dt/OoVFuRy6z7V+f9", + "T4XPdJ8Pjs17tpsjobdTzQ9ICPf/EpC+TY4CMrHNzR1uPCNJBBbTykja/c6UdXmhnyR+qujRgeJJpVni", + "kDm7YNHaQRtLQJTyZ2wHeqketMPWkAjqN3fXjmCLxjaTz7uL1cWKfdElKlFKSODDxbuLlbuP0aODEaPa", + "SIXxSyWzmhc26ILFjLmx+KcMErjiYcEJum+NKJCQD627Fjrr2wNvKD2800WDufoM+fX66Pr3frUKJWEv", + "Fx9cLWrH0YFzcTdXldp6XPzcvai8nYfdm84u7Nzg2ScevfnUS9HUXyr8wUe6cgJzzI3uvcNygORu7SYK", + "X0Au3fF81VwYXk3W8RtUPRd8CPhhBd8104Tmg1xkhVSwrteOW24Mp6j9w7rT//XgDm61dQQfVx/Of3T4", + "kNKGnzXF/euZPxq/auugXjuxGQFp9NfLeLp6vadHWTf0W1c0yXGWG+H/OLoyga3SFK39rlW9NOLhW+Fp", + "zDed5Ix49Va+nZCdLMA191SLZtt17crkkEDM5169rv8JAAD//ytDNwRSFwAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/types.go b/api/types.go index 6c2a65c..1af8dd5 100644 --- a/api/types.go +++ b/api/types.go @@ -3,6 +3,10 @@ // Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0 DO NOT EDIT. package api +import ( + openapi_types "github.com/oapi-codegen/runtime/types" +) + const ( CookieAuthScopes = "cookieAuth.Scopes" ) @@ -13,6 +17,15 @@ const ( Virtual GameType = "virtual" ) +// Defines values for TaskViewMessage. +const ( + GameComplete TaskViewMessage = "game_complete" + InvalidCode TaskViewMessage = "invalid_code" + NextLevel TaskViewMessage = "next_level" + OkCode TaskViewMessage = "ok_code" + OldCode TaskViewMessage = "old_code" +) + // CodeEdit defines model for codeEdit. type CodeEdit struct { Code string `json:"code"` @@ -39,10 +52,14 @@ type GameType string // GameView defines model for gameView. type GameView struct { - Description string `json:"description"` - Id int `json:"id"` - Title string `json:"title"` - Type GameType `json:"type"` + Authors []UserView `json:"authors"` + CreatedAt string `json:"createdAt"` + Description string `json:"description"` + Id openapi_types.UUID `json:"id"` + Points int `json:"points"` + TaskCount int `json:"taskCount"` + Title string `json:"title"` + Type GameType `json:"type"` } // SolutionEdit defines model for solutionEdit. @@ -67,11 +84,20 @@ type TaskEdit struct { // TaskView defines model for taskView. type TaskView struct { - Codes []CodeView `json:"codes"` - Entered []CodeView `json:"entered"` - Solutions []SolutionView `json:"solutions"` - Text string `json:"text"` - Title string `json:"title"` + Codes []CodeView `json:"codes"` + Message *TaskViewMessage `json:"message,omitempty"` + Solutions []SolutionView `json:"solutions"` + Text string `json:"text"` + Title string `json:"title"` +} + +// TaskViewMessage defines model for TaskView.Message. +type TaskViewMessage string + +// UserView defines model for userView. +type UserView struct { + Id openapi_types.UUID `json:"id"` + Username string `json:"username"` } // ErrorResponse defines model for errorResponse. @@ -91,12 +117,14 @@ type TaskResponse = TaskView // UserResponse defines model for userResponse. type UserResponse struct { - Email string `json:"email"` - Experience int `json:"experience"` - Games []GameView `json:"games"` - Id int `json:"id"` - Level int `json:"level"` - Username string `json:"username"` + Email string `json:"email"` + ExpToCurrentLevel int `json:"expToCurrentLevel"` + ExpToNextLevel int `json:"expToNextLevel"` + Experience int `json:"experience"` + Games []GameView `json:"games"` + Id openapi_types.UUID `json:"id"` + Level int `json:"level"` + Username string `json:"username"` } // EnterCodeRequest defines model for enterCodeRequest. diff --git a/docker-compose.yml b/docker-compose.yml index 8b1d7ed..dd69a3f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,26 +4,6 @@ volumes: postgres-data: services: - # app: - # build: - # context: . - # dockerfile: Dockerfile - # env_file: - # # Ensure that the variables in .env match the same variables in devcontainer.json - # - .env - - # volumes: - # - ../..:/workspaces:cached - - # # Overrides default command so things don't shut down after the process ends. - # command: sleep infinity - - # # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. - # network_mode: service:db - - # # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. - # # (Adding the "ports" property to this file will not forward from a Codespace.) - db: image: postgres:15-alpine3.17 restart: unless-stopped diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4308c8d..a918d9a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@neonxp/compose": "0.0.6", + "moment": "^2.30.1", "react": "^18.2.0", "react-bootstrap": "^2.9.1", "react-dom": "^18.2.0", @@ -3735,6 +3736,14 @@ "node": "*" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 84ab077..d865f88 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@neonxp/compose": "0.0.6", + "moment": "^2.30.1", "react": "^18.2.0", "react-bootstrap": "^2.9.1", "react-dom": "^18.2.0", diff --git a/frontend/public/logo.png b/frontend/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ce1dc0e4b190f566e9486d48e837b2a2428937e3 GIT binary patch literal 23704 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 XLb;jC?|PXt+C<*c*Z6S5Hu8S}erG`U literal 0 HcmV?d00001 diff --git a/frontend/public/logo_small.png b/frontend/public/logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..9785f266a608168d2c8b54c963950782b7ce1cc3 GIT binary patch literal 4363 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 FV1j42I$Qt% literal 0 HcmV?d00001 diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 00dedcf..6dba62a 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -6,13 +6,9 @@ import Index from './pages/Index' import Login from './pages/Login' import Register from './pages/Register' import NoMatch from './pages/NoMatch' -import Team from './pages/Team' -import Teams from './pages/Teams' import { UserProvider } from './store/user' import { ajax } from './utils/fetch' -import TeamNew from './pages/TeamNew' -import Admin from './pages/Admin' -import AdminGame from './pages/AdminGame' +import Engine from './pages/Engine' const router = createBrowserRouter( createRoutesFromElements( @@ -30,20 +26,11 @@ const router = createBrowserRouter( } /> } /> } - loader={() => ajax("/api/teams")} + path="go/:gameId" + element={} + loader={({ params }) => ajax(`/api/engine/${params.gameId}`)} /> - } - /> - } - loader={({ params }) => ajax(`/api/teams/${params.teamId}`)} - /> - } loader={() => ajax(`/api/admin/games`)} @@ -55,7 +42,7 @@ const router = createBrowserRouter( title: "Новая игра", tasks: [] })} - /> + /> */} } /> ) diff --git a/frontend/src/assets/TiltNeon-Regular.ttf b/frontend/src/assets/TiltNeon-Regular.ttf deleted file mode 100644 index 0cbb1678d8350366e2e7afb11ac422ec4ded39a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95380 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
e`}3J28e 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 XLb;jC?|PXt+C<*c*Z6S5Hu8S}erG`U literal 0 HcmV?d00001 diff --git a/frontend/src/assets/logo_small.png b/frontend/src/assets/logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..9785f266a608168d2c8b54c963950782b7ce1cc3 GIT binary patch literal 4363 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 FV1j42I$Qt% literal 0 HcmV?d00001 diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/frontend/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/assets/styles.css b/frontend/src/assets/styles.css index e18e68e..d6c46c6 100644 --- a/frontend/src/assets/styles.css +++ b/frontend/src/assets/styles.css @@ -2,12 +2,15 @@ .navbar-dark { border-bottom: 0.1px solid #333333 !important; } -@font-face { +.navbar { + background-color: rgb(16, 22, 29) !important; +} +/* @font-face { font-family: 'TiltNeon'; src: url('TiltNeon-Regular.ttf'); -} +} */ .navbar-brand { - font-family: TiltNeon, var(--bs-font-sans-serif); + /* font-family: TiltNeon, var(--bs-font-sans-serif); text-shadow: 0 0 1px rgb(255, 255, 255, 1), 0 0 2px rgb(255, 255, 255, 1), @@ -17,10 +20,14 @@ 0 1px #198754, 1px 0 #198754, 0 -1px #198754; - -webkit-text-stroke: 1px white; + -webkit-text-stroke: 1px white; */ font-size: 26px; padding-top: 0 !important; padding-bottom: 0 !important; + height: 40px; + width: 85px; + background-image: url("./logo_small.png"); + background-size: 100%; } th.thin { @@ -28,3 +35,11 @@ th.thin { white-space: nowrap; } +* { + --bs-body-bg: rgb(23, 30, 38) !important; + --bs-primary-rgb: rgb(16, 22, 29) !important; + --bs-navbar-color: rgb(249, 115, 22) !important; + --bs-btn-bg: rgb(249, 115, 22) !important; + --bs-btn-hover-bg: rgba(249, 115, 22, 0.5) !important; + --bs-btn-active-bg: rgba(249, 115, 22, 0.5) !important; +} \ No newline at end of file diff --git a/frontend/src/components/Layout.jsx b/frontend/src/components/Layout.jsx index c9e0396..c549e00 100644 --- a/frontend/src/components/Layout.jsx +++ b/frontend/src/components/Layout.jsx @@ -1,7 +1,7 @@ import { Link, Outlet, useLoaderData } from "react-router-dom"; -import { Button, Nav, Container, NavbarBrand, NavbarToggle, Navbar, NavbarCollapse, ButtonGroup } from "react-bootstrap"; +import { Button, Nav, Container, NavbarBrand, NavbarToggle, Navbar, NavbarCollapse, ButtonGroup, ProgressBar, OverlayTrigger, Tooltip, Col, Row, NavDropdown } from "react-bootstrap"; import { UserProvider } from "../store/user"; -import { useEffect } from "react"; +import { useEffect, useRef, useState } from "react"; import { ajax } from "../utils/fetch"; import { useRole } from "../utils/roles"; @@ -20,46 +20,44 @@ export default () => { }). then(() => setUser(null)) } - return (<> - + - nQuest + - + - + + diff --git a/frontend/src/pages/Admin.jsx b/frontend/src/pages/Admin.jsx deleted file mode 100644 index 1f92ca8..0000000 --- a/frontend/src/pages/Admin.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Link, useLoaderData } from "react-router-dom"; -import { Button, Table } from 'react-bootstrap'; - -export default () => { - const games = useLoaderData(); - if (!games) { - return null - } - - return (<> -

Управление играми

- - - - - - - - - - {games.map(game => ( - - - - - - ))} - -
IDНазваниеСоздана
{game.id}{game.title}{team.createdAt}
- ); -} \ No newline at end of file diff --git a/frontend/src/pages/AdminGame.jsx b/frontend/src/pages/AdminGame.jsx deleted file mode 100644 index 26d9b0b..0000000 --- a/frontend/src/pages/AdminGame.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import { useLoaderData } from "react-router-dom"; -import { Col, Row, Form, Button, Card } from 'react-bootstrap'; -import { useEffect, useState } from "react"; - -export default () => { - const loadedGame = useLoaderData(); - const [game, setGame] = useState(loadedGame); - const [error, setError] = useState(null); - - if (!game) { - return null - } - const submit = (e) => { - e.preventDefault(); - console.log(game) - } - return (<> -

Игра "{game.title}"

-
-
- {error ? (
{error}
) : null} - - - Название игры - - setGame({ ...game, title: e.target.value })} - /> - - - - Начало в - - - - - - Описание - - setGame({ ...game, description: e.target.value })} - /> - - -
-

- Задания - -

- {game.tasks.map((task, idx) => - { - const newTasks = game.tasks; - newTasks[idx] = task; - setGame({...game, tasks: newTasks}); - }} - /> - )} -
- -
-
- ); -} - -const Task = ({id, task, setTask}) => ( - - - - Задание #{id + 1} - - - Задание - - setTask({ ...task, text: e.target.value })} - /> - - - - -) \ No newline at end of file diff --git a/frontend/src/pages/Engine.jsx b/frontend/src/pages/Engine.jsx new file mode 100644 index 0000000..506bbd1 --- /dev/null +++ b/frontend/src/pages/Engine.jsx @@ -0,0 +1,75 @@ +import { Badge, Button, Col, Form, Row, Table } from "react-bootstrap"; +import { Link, useLoaderData, useParams } from "react-router-dom"; +import Markdown from "react-markdown"; +import { useState } from "react"; +import { ajax } from "../utils/fetch"; + +export default () => { + const params = useParams(); + const loadedTask = useLoaderData(); + const [task, setTask] = useState(loadedTask); + const [code, setCode] = useState(""); + const onSubmitCode = (e) => { + e.preventDefault(); + ajax(`/api/engine/${params.gameId}/code`, { + method: "POST", + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ code }) + }). + then((x) => { + if (x != null) { + setTask(x); + setCode(""); + } + }).catch(e => { + console.warn(e); + }); + } + + if (task && task.message == "game_complete") { + return (
+
Вы прошли все уровни!
+ К списку игр +
); + } + if (!task) { + return (
+
Для вас не предусмотренно уровней
+ К списку игр +
); + } + + return (<> +

{task.title}

+ {task.text} + {task.message == "invalid_code" ? (
Неверный код
) : null} + {task.message == "old_code" ? (
Этот код уже вводился
) : null} + {task.message == "next_level" ? (
Переход на новый уровень
) : null} + {task.message == "ok_code" ? (
Код принят, ищите оставшиеся
) : null} +

Коды:

+
    + {task.codes.map( + (c, idx) =>
  • {c.description} {!!c.code ? (Принят {c.code}) : (Не введён)}
  • + )} +
+
+ + Код: + + setCode(e.target.value)} + /> + + + + + +
+ ); +} \ No newline at end of file diff --git a/frontend/src/pages/Index.jsx b/frontend/src/pages/Index.jsx index 44f7952..38638c8 100644 --- a/frontend/src/pages/Index.jsx +++ b/frontend/src/pages/Index.jsx @@ -1,47 +1,72 @@ import { Button, Table } from "react-bootstrap"; import { Link, useLoaderData } from "react-router-dom"; import Markdown from "react-markdown"; +import moment from 'moment/min/moment-with-locales'; +import { UserProvider } from "../store/user"; export default () => { + moment.locale('ru'); const games = useLoaderData(); - + const { user } = UserProvider.useContainer(); return (<> -

Текущие игры

+

Доступные квесты

{games && games.map(game => ( - <> +

{game.title}

- - + + - + + + + + + + + + + - - - -
- Начало + + Тип - {game.startAt} + + {game.type} + + Опыт за квест + + {game.points}
+ + Уровней + + {game.taskCount} + + Опубликовано + + {moment(game.createdAt).fromNow()} +
+ Автор + + {game.authors.map(a => {a.username})} +
{game.description}
- + {user ? (<> + {(!!user.games.find(x => x.id === game.id)) + ? (Вы уже прошли этот квест) + : (Начать прохождение)} + ): null} +
- Участвуют: - -
    - {game.teams.map(team => (
  • {team.name}
  • ))} - {game.teams.length == 0 ?

    Никто пока не подал заявку

    : null} -
-
- +
))} {!games ? (Игр пока не анонсировано) : null} ); diff --git a/frontend/src/pages/Team.jsx b/frontend/src/pages/Team.jsx deleted file mode 100644 index 2f892aa..0000000 --- a/frontend/src/pages/Team.jsx +++ /dev/null @@ -1,175 +0,0 @@ -import { useLoaderData, useNavigate, useRouteLoaderData } from "react-router-dom"; -import { Alert, Button, ButtonGroup, Table } from "react-bootstrap"; -import { UserProvider } from "../store/user"; -import { ajax } from "../utils/fetch"; -import { useEffect, useState } from "react"; - -const userRoles = { captain: "Капитан", member: "Участник" }; - -export default () => { - const teamFromRouter = useLoaderData(); - const [team, setTeam] = useState(teamFromRouter); - const [error, setError] = useState(null); - useEffect(() => { - setTeam(teamFromRouter); - }, [teamFromRouter]); - const navigate = useNavigate(); - - const { user, setUser } = UserProvider.useContainer(); - - const [request, setRequest] = useState(false); - - useEffect(() => { - setRequest(!!team.requests.find(x => user && x.user.id == user.id)); - }, [user, team.requests]) - - if (!team) { - return null; - } - - if (!user) { - return null; - } - - const member = team.members.find(tm => tm.user.id === user.id); - const inOtherTeam = user.team && user.team.td != team.id; - const isCaptain = member && user.team.role == "captain"; - - const sendRequest = () => { - ajax(`/api/teams/${team.id}/requests`, { - method: "POST", - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - } - }).then(() => setRequest(true)).catch(setError); - }; - const updateMemebers = (members) => { - ajax(`/api/teams/${team.id}/members`, { - method: "POST", - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ members }), - }).then(team => setTeam(team)).catch(setError); - }; - const approveRequest = (userID, approve) => { - ajax(`/api/teams/${team.id}/requests/${userID}`, { - method: "POST", - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ approve }), - }).then(team => setTeam(team)).catch(setError); - } - const removeMember = (userID) => { - const members = team.members.map(x => x.user.id).filter(uid => uid != userID); - return updateMemebers(members) - } - const leaveTeam = () => { - ajax(`/api/teams/${team.id}/members`, { - method: "DELETE", - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - }).then(team => setTeam(team)).then(() => { - setUser({ - ...user, - team: null, - }); - }).catch(setError); - }; - const deleteTeam = () => { - ajax(`/api/teams/${team.id}`, { - method: "DELETE", - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - }).then(() => { - setUser({ - ...user, - team: null, - }); - navigate("/teams"); - }).catch(setError); - }; - - return (<> -

{team.name}

-

Создана: {team.createdAt}

- - {!member && !inOtherTeam && !request ? () : null} - {request ? (Заявка в команду отправлена) : null} - {error ? ({error}) : null} - {member && !isCaptain ? () : null} - -

Участники

- - - - - - - - - - - {team.members.map(tm => ( - - - - - - - ))} - -
Имя пользователяРольПрисоединился
{tm.user.username}{userRoles[tm.role]}{tm.createdAt} - { - isCaptain && tm.user.id != user.id - ? () - : null - } -
- {isCaptain - ? (<> -

Заявки

- - - - - - - - - - {team.requests.map(tm => ( - - - - - - ))} - -
Имя пользователяДата заявки
{tm.user.username}{tm.createdAt} - - - - -
- ) - : null} - {isCaptain && (team.members.length == 1) ? : null} - ); -} \ No newline at end of file diff --git a/frontend/src/pages/TeamNew.jsx b/frontend/src/pages/TeamNew.jsx deleted file mode 100644 index 7498c5c..0000000 --- a/frontend/src/pages/TeamNew.jsx +++ /dev/null @@ -1,52 +0,0 @@ -import { useState } from "react"; -import { Form, Button, Row, Col } from "react-bootstrap"; -import { useNavigate } from "react-router-dom"; -import { ajax } from "../utils/fetch"; -import { UserProvider } from "../store/user"; - -export default () => { - const {user, setUser} = UserProvider.useContainer(); - const [name, setName] = useState(""); - const [error, setError] = useState(null); - const navigate = useNavigate(); - - const onCreate = (e) => { - e.preventDefault(); - ajax("/api/teams", { - method: "POST", - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ name }) - }).then((team) => { - setUser({ - ...user, - team: { - role: 1, - ...team, - } - }); - navigate(`/teams/${team.id}`); - }).catch(e => setError(e.message)) - } - return (<> -

Создание команды

-
-
- {error ? (
{error}
) : null} - - Название команды - - setName(e.target.value)} - /> - - - -
-
- ) -}; \ No newline at end of file diff --git a/frontend/src/pages/Teams.jsx b/frontend/src/pages/Teams.jsx deleted file mode 100644 index 96ab72d..0000000 --- a/frontend/src/pages/Teams.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import { Link, useLoaderData } from "react-router-dom"; -import { Table } from 'react-bootstrap'; -import { UserProvider } from "../store/user"; - -export default () => { - const teams = useLoaderData(); - if (!teams) { - return null - } - const { user } = UserProvider.useContainer(); - - return (<> -

Команды

- {user && !user.team - ? (

Вы не состоите в командах. Создать свою команду.

) - : null} - - - - - - - - - - - {teams.map(team => ( - - - - - - ))} - -
КомандаУчастниковСоздана
{team.name}{team.members}{team.createdAt}
- ); -} \ No newline at end of file diff --git a/pkg/controller/admin.go b/pkg/controller/admin.go index fe13302..62b7ace 100644 --- a/pkg/controller/admin.go +++ b/pkg/controller/admin.go @@ -3,6 +3,7 @@ package controller import ( "net/http" + "github.com/google/uuid" "github.com/labstack/echo/v4" "gitrepo.ru/neonxp/nquest/api" "gitrepo.ru/neonxp/nquest/pkg/contextlib" @@ -31,7 +32,7 @@ func (a *Admin) CreateGame(ctx echo.Context) error { } return ctx.JSON(http.StatusCreated, api.GameResponse{ - Id: int(game.ID), + Id: game.ID, Title: game.Title, Description: game.Description, }) @@ -39,6 +40,9 @@ func (a *Admin) CreateGame(ctx echo.Context) error { func (*Admin) mapCreateGameRequest(req *api.GameEditRequest, user *models.User) *models.Game { game := &models.Game{ + Model: models.Model{ + ID: uuid.New(), + }, Visible: false, Title: req.Title, Description: req.Description, @@ -49,22 +53,32 @@ func (*Admin) mapCreateGameRequest(req *api.GameEditRequest, user *models.User) Tasks: make([]*models.Task, 0, len(req.Tasks)), Points: req.Points, } - for _, te := range req.Tasks { + for order, te := range req.Tasks { task := &models.Task{ + Model: models.Model{ + ID: uuid.New(), + }, Title: te.Title, Text: te.Text, MaxTime: 0, Solutions: make([]*models.Solution, 0, len(te.Solutions)), Codes: make([]*models.Code, 0, len(te.Codes)), + TaskOrder: uint(order), } for _, s := range te.Solutions { task.Solutions = append(task.Solutions, &models.Solution{ + Model: models.Model{ + ID: uuid.New(), + }, After: s.After, Text: s.Text, }) } for _, ce := range te.Codes { task.Codes = append(task.Codes, &models.Code{ + Model: models.Model{ + ID: uuid.New(), + }, Code: ce.Code, Description: ce.Description, }) diff --git a/pkg/controller/engine.go b/pkg/controller/engine.go index 7ffbf68..6b9ca0e 100644 --- a/pkg/controller/engine.go +++ b/pkg/controller/engine.go @@ -1,8 +1,10 @@ package controller import ( + "errors" "net/http" + "github.com/google/uuid" "github.com/labstack/echo/v4" "gitrepo.ru/neonxp/nquest/api" "gitrepo.ru/neonxp/nquest/pkg/contextlib" @@ -16,10 +18,10 @@ type Engine struct { } // (GET /engine/{uid}) -func (ec *Engine) GameEngine(c echo.Context, uid int) error { +func (ec *Engine) GameEngine(c echo.Context, uid uuid.UUID) error { user := contextlib.GetUser(c) - game, err := ec.GameService.GetByID(c.Request().Context(), uint(uid)) + game, err := ec.GameService.GetByID(c.Request().Context(), uid) if err != nil { return err } @@ -29,16 +31,16 @@ func (ec *Engine) GameEngine(c echo.Context, uid int) error { return err } - return c.JSON(http.StatusOK, mapCursorToTask(cursor)) + return c.JSON(http.StatusOK, mapCursorToTask(cursor, nil)) } // (POST /engine/{uid}/code) -func (ec *Engine) EnterCode(c echo.Context, uid int) error { +func (ec *Engine) EnterCode(c echo.Context, uid uuid.UUID) error { user := contextlib.GetUser(c) ctx := c.Request().Context() - game, err := ec.GameService.GetByID(ctx, uint(uid)) + game, err := ec.GameService.GetByID(ctx, uid) if err != nil { return err } @@ -49,31 +51,48 @@ func (ec *Engine) EnterCode(c echo.Context, uid int) error { } cursor, err := ec.EngineService.EnterCode(ctx, game, user, req.Code) + message := api.OkCode if err != nil { - return err + switch { + case errors.Is(err, service.ErrGameFinished): + message = api.GameComplete + case errors.Is(err, service.ErrInvalidCode): + message = api.InvalidCode + case errors.Is(err, service.ErrOldCode): + message = api.OldCode + case errors.Is(err, service.ErrNextLevel): + message = api.NextLevel + default: + return c.JSON(http.StatusBadRequest, &api.ErrorResponse{ + Code: http.StatusBadRequest, + Message: err.Error(), + }) + } } - return c.JSON(http.StatusOK, mapCursorToTask(cursor)) + return c.JSON(http.StatusOK, mapCursorToTask(cursor, &message)) } -func mapCursorToTask(cursor *models.GameCursor) *api.TaskView { +func mapCursorToTask(cursor *models.GameCursor, message *api.TaskViewMessage) *api.TaskView { resp := &api.TaskResponse{ + Message: message, Codes: make([]api.CodeView, 0, len(cursor.Task.Codes)), - Entered: make([]api.CodeView, 0, len(cursor.Codes)), Solutions: []api.SolutionView{}, Text: cursor.Task.Text, Title: cursor.Task.Title, } for _, code := range cursor.Task.Codes { - resp.Codes = append(resp.Codes, api.CodeView{ + c := api.CodeView{ Description: code.Description, - }) - } - for _, code := range cursor.Codes { - resp.Entered = append(resp.Entered, api.CodeView{ - Code: &code.Code, - Description: code.Description, - }) + } + for _, cd := range cursor.Codes { + if cd.ID == code.ID { + c.Code = &cd.Code + break + } + } + resp.Codes = append(resp.Codes, c) } + return resp } diff --git a/pkg/controller/game.go b/pkg/controller/game.go index 3e48425..6502c53 100644 --- a/pkg/controller/game.go +++ b/pkg/controller/game.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "time" "github.com/labstack/echo/v4" "gitrepo.ru/neonxp/nquest/api" @@ -21,11 +22,23 @@ func (g *Game) GetGames(ctx echo.Context) error { resp := make(api.GameListResponse, 0, len(games)) for _, game := range games { - resp = append(resp, api.GameView{ - Id: int(game.ID), + gv := api.GameView{ + Id: game.ID, Title: game.Title, Description: game.Description, - }) + Type: api.MapGameTypeReverse(game.Type), + Points: game.Points, + TaskCount: len(game.Tasks), + Authors: make([]api.UserView, 0, len(game.Authors)), + CreatedAt: game.CreatedAt.Format(time.RFC3339), + } + for _, u := range game.Authors { + gv.Authors = append(gv.Authors, api.UserView{ + Id: u.ID, + Username: u.Username, + }) + } + resp = append(resp, gv) } return ctx.JSON(http.StatusOK, resp) diff --git a/pkg/controller/user.go b/pkg/controller/user.go index e204fa2..67a00fc 100644 --- a/pkg/controller/user.go +++ b/pkg/controller/user.go @@ -9,6 +9,7 @@ import ( "gitrepo.ru/neonxp/nquest/api" "gitrepo.ru/neonxp/nquest/pkg/models" "gitrepo.ru/neonxp/nquest/pkg/service" + "gitrepo.ru/neonxp/nquest/pkg/utils" ) type User struct { @@ -116,7 +117,7 @@ func setUser(c echo.Context, user *models.User) error { MaxAge: 86400 * 7, HttpOnly: true, } - sess.Values["userID"] = user.ID + sess.Values["userID"] = user.ID.String() if err := sess.Save(c.Request(), c.Response()); err != nil { return err @@ -128,22 +129,24 @@ func setUser(c echo.Context, user *models.User) error { func mapUser(c echo.Context, user *models.User) error { games := make([]api.GameView, 0) for _, gc := range user.Games { - if gc.Status == models.TaskFinished && gc.Task.Next == nil { - games = append(games, api.GameView{ - Id: int(gc.GameID), - Title: gc.Game.Title, - Description: gc.Game.Description, - Type: api.MapGameTypeReverse(gc.Game.Type), - }) - } + games = append(games, api.GameView{ + Id: gc.GameID, + Title: gc.Game.Title, + Description: gc.Game.Description, + Type: api.MapGameTypeReverse(gc.Game.Type), + }) } + level := utils.ExpToLevel(user.Experience) + return c.JSON(http.StatusOK, &api.UserResponse{ - Id: int(user.ID), - Username: user.Username, - Email: user.Email, - Experience: user.Experience, - Level: user.Experience / 1000, - Games: games, + Id: user.ID, + Username: user.Username, + Email: user.Email, + Experience: user.Experience, + ExpToCurrentLevel: utils.LevelToExp(level), + ExpToNextLevel: utils.LevelToExp(level + 1), + Level: int(level), + Games: games, }) } diff --git a/pkg/models/cursor.go b/pkg/models/cursor.go index 63d7548..caaab88 100644 --- a/pkg/models/cursor.go +++ b/pkg/models/cursor.go @@ -1,18 +1,23 @@ package models -import "time" +import ( + "time" + + "github.com/google/uuid" +) type GameCursor struct { - User *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` - UserID uint `gorm:"primaryKey"` - Game *Game `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` - GameID uint `gorm:"primaryKey"` - Task *Task `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` - TaskID uint `gorm:"primaryKey"` + User *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` + UserID uuid.UUID `gorm:"primaryKey"` + Game *Game `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` + GameID uuid.UUID `gorm:"primaryKey"` + Task *Task `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` + TaskID uuid.UUID `gorm:"primaryKey"` CreatedAt time.Time FinishedAt *time.Time Status CursorStatus Codes []*Code `gorm:"many2many:passing_codes;"` + Finish bool } type CursorStatus int diff --git a/pkg/models/model.go b/pkg/models/model.go index 572add7..cb8b301 100644 --- a/pkg/models/model.go +++ b/pkg/models/model.go @@ -3,11 +3,12 @@ package models import ( "time" + "github.com/google/uuid" "gorm.io/gorm" ) type Model struct { - ID uint `gorm:"primarykey" json:"id"` + ID uuid.UUID `gorm:"primarykey" json:"id"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` diff --git a/pkg/models/task.go b/pkg/models/task.go index 2ce5de8..5a0df22 100644 --- a/pkg/models/task.go +++ b/pkg/models/task.go @@ -1,22 +1,23 @@ package models +import "github.com/google/uuid" + type Task struct { Model Title string Text string MaxTime int - GameID uint + GameID uuid.UUID Solutions []*Solution `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` Codes []*Code `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"` - Next *Task `gorm:"foreignKey:NextID"` - NextID *uint + TaskOrder uint } type Solution struct { Model - TaskID uint + TaskID uuid.UUID After int Text string } @@ -24,7 +25,7 @@ type Solution struct { type Code struct { Model - TaskID uint + TaskID uuid.UUID Code string `gorm:"index"` Description string } diff --git a/pkg/service/engine.go b/pkg/service/engine.go index ab9e4bd..c0086b4 100644 --- a/pkg/service/engine.go +++ b/pkg/service/engine.go @@ -5,6 +5,7 @@ import ( "errors" "strings" + "github.com/google/uuid" "github.com/jackc/pgx/v5/pgconn" "gitrepo.ru/neonxp/nquest/pkg/models" "gorm.io/gorm" @@ -15,6 +16,7 @@ var ( ErrInvalidCode = errors.New("invalid code") ErrOldCode = errors.New("old code") ErrGameFinished = errors.New("game finished") + ErrNextLevel = errors.New("next level") ) type Engine struct { @@ -30,20 +32,18 @@ func NewEngine(db *gorm.DB) *Engine { func (e *Engine) GetState(ctx context.Context, game *models.Game, user *models.User) (*models.GameCursor, error) { db := e.DB.WithContext(ctx) - // Пытаемся получить GamePassing + // Пытаемся получить GameCursor cursor := &models.GameCursor{ User: user, Game: game, Task: game.Tasks[0], Status: models.TaskStarted, - Codes: []*models.Code{}, + Codes: make([]*models.Code, 0), } err := db. Where(`user_id = ? and game_id = ? and status = ?`, user.ID, game.ID, models.TaskStarted). Preload("Task"). Preload("Task.Codes"). - Preload("Task.Next"). - Preload("Task.Next.Codes"). Preload("Codes"). FirstOrCreate(cursor). Error @@ -62,62 +62,91 @@ func (e *Engine) GetState(ctx context.Context, game *models.Game, user *models.U func (e *Engine) EnterCode(ctx context.Context, game *models.Game, user *models.User, code string) (*models.GameCursor, error) { db := e.DB.WithContext(ctx) + st, err := e.GetState(ctx, game, user) if err != nil { return nil, err } - code = strings.Trim(code, " \n\t") - code = strings.ToLower(code) - var currentCode *models.Code - for _, c := range st.Task.Codes { - if c.Code == code { - currentCode = c - break + + return st, db.Transaction(func(tx *gorm.DB) error { + code = strings.Trim(code, " \n\t") + code = strings.ToLower(code) + var currentCode *models.Code + for _, c := range st.Task.Codes { + if c.Code == code { + currentCode = c + break + } } - } - if currentCode == nil { - return nil, ErrInvalidCode - } - for _, c := range st.Codes { - if c.ID == currentCode.ID { - return nil, ErrOldCode + if currentCode == nil { + return ErrInvalidCode } - } - - st.Codes = append(st.Codes, currentCode) - - if err := db.Save(st).Error; err != nil { - return nil, err - } - - if len(st.Codes) != len(st.Task.Codes) { - return st, nil - } - - // Уровень пройден. Выдаем следующий - - st.Status = models.TaskFinished - if err := db.Save(st).Error; err != nil { - return nil, err - } - - if st.Task.Next == nil { - - user.Experience += st.Game.Points - if err := db.Save(user).Error; err != nil { - return nil, err + for _, c := range st.Codes { + if c.ID == currentCode.ID { + return ErrOldCode + } } - return nil, ErrGameFinished - } + if err := db.Model(st).Association("Codes").Append(currentCode); err != nil { + return err + } - newState := &models.GameCursor{ - User: user, - Game: game, - Task: st.Task.Next, - Status: models.TaskStarted, - Codes: []*models.Code{}, - } + if len(st.Codes) != len(st.Task.Codes) { + return nil + } - return newState, db.Create(newState).Error + // Уровень пройден. Выдаем следующий + + if err := db.Model(st).UpdateColumn("Status", models.TaskFinished).Error; err != nil { + return err + } + + nextTask, err := e.GetNext(ctx, game.ID, st.Task.TaskOrder) + if err != nil { + return err + } + + if nextTask == nil { + user.Experience += st.Game.Points + if err := db.Model(user).UpdateColumn("Experience", user.Experience).Error; err != nil { + return err + } + if err := db.Model(st).UpdateColumn("Finish", true).Error; err != nil { + return err + } + + return ErrGameFinished + } + + st = &models.GameCursor{ + User: user, + Game: game, + Task: nextTask, + Status: models.TaskStarted, + Codes: []*models.Code{}, + } + if err := db.Create(st).Error; err != nil { + return err + } + + return ErrNextLevel + }) +} + +func (e *Engine) GetNext(ctx context.Context, gameID uuid.UUID, currentOrder uint) (*models.Task, error) { + var t models.Task + err := e.DB.WithContext(ctx). + Preload("Codes"). + Preload("Solutions"). + Order("task_order ASC"). + First(&t, `game_id = ? AND task_order > ?`, gameID, currentOrder). + Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + + return nil, err + } + return &t, nil } diff --git a/pkg/service/game.go b/pkg/service/game.go index 5bc8192..c28475f 100644 --- a/pkg/service/game.go +++ b/pkg/service/game.go @@ -3,6 +3,7 @@ package service import ( "context" + "github.com/google/uuid" "gitrepo.ru/neonxp/nquest/pkg/models" "gorm.io/gorm" ) @@ -18,12 +19,16 @@ func NewGame(db *gorm.DB) *Game { } } -func (gs *Game) GetByID(ctx context.Context, id uint) (*models.Game, error) { +func (gs *Game) GetByID(ctx context.Context, id uuid.UUID) (*models.Game, error) { g := &models.Game{} return g, gs.DB. WithContext(ctx). - Preload("Tasks"). + Preload("Tasks", func(db *gorm.DB) *gorm.DB { + return db.Order("tasks.task_order ASC") + }). + Preload("Tasks.Codes"). + Preload("Tasks.Solutions"). First(g, id). Error } @@ -34,15 +39,17 @@ func (gs *Game) List(ctx context.Context) ([]*models.Game, error) { return games, gs.DB. WithContext(ctx). Order("created_at DESC"). - Find(&games, "visible = true"). + Preload("Tasks"). + Preload("Authors"). + Find(&games). Limit(20). Error } -func (gs *Game) GetTaskID(ctx context.Context, id uint) (*models.Task, error) { +func (gs *Game) GetTaskID(ctx context.Context, id uuid.UUID) (*models.Task, error) { t := &models.Task{} - return t, gs.DB.WithContext(ctx).Preload("Next").First(t, id).Error + return t, gs.DB.WithContext(ctx).First(t, id).Error } func (gs *Game) ListByAuthor(ctx context.Context, author *models.User) ([]*models.Game, error) { @@ -59,19 +66,8 @@ func (gs *Game) ListByAuthor(ctx context.Context, author *models.User) ([]*model } func (gs *Game) CreateGame(ctx context.Context, game *models.Game) (*models.Game, error) { - return game, gs.DB.Transaction(func(tx *gorm.DB) error { - if err := tx.Create(game).Error; err != nil { - return err - } - for i, t := range game.Tasks { - if i < len(game.Tasks)-1 { - t.Next = game.Tasks[i+1] - if err := tx.Save(t).Error; err != nil { - return err - } - - } - } - return nil - }) + return game, gs.DB. + Session(&gorm.Session{FullSaveAssociations: true}). + Create(game). + Error } diff --git a/pkg/service/user.go b/pkg/service/user.go index 55c658d..d57f25e 100644 --- a/pkg/service/user.go +++ b/pkg/service/user.go @@ -7,6 +7,7 @@ import ( "net/mail" normalizer "github.com/dimuska139/go-email-normalizer" + "github.com/google/uuid" "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" "golang.org/x/crypto/bcrypt" @@ -58,6 +59,9 @@ func (s *User) Register(ctx context.Context, username, email, password, password } u := &models.User{ + Model: models.Model{ + ID: uuid.New(), + }, Username: username, Email: normalizer.NewNormalizer().Normalize(email), Password: hex.EncodeToString(hashed), @@ -99,14 +103,12 @@ func (s *User) Login(ctx context.Context, email, password string) (*models.User, return u, nil } -func (s *User) GetUserByID(ctx context.Context, userID uint) (*models.User, error) { +func (s *User) GetUserByID(ctx context.Context, userID uuid.UUID) (*models.User, error) { u := new(models.User) return u, s.DB.WithContext(ctx). - Preload("Games"). + Preload("Games", `Finish = true`). Preload("Games.Game"). - Preload("Games.Task"). - Preload("Games.Task.Next"). First(u, userID).Error } @@ -116,12 +118,16 @@ func (s *User) GetUser(c echo.Context) *models.User { return nil } - userID, ok := sess.Values["userID"].(uint) + userID, ok := sess.Values["userID"].(string) if !ok { return nil } + uid, err := uuid.Parse(userID) + if err != nil { + return nil + } - user, err := s.GetUserByID(c.Request().Context(), userID) + user, err := s.GetUserByID(c.Request().Context(), uid) if err != nil { return nil } diff --git a/pkg/utils/exp.go b/pkg/utils/exp.go new file mode 100644 index 0000000..0ef15a6 --- /dev/null +++ b/pkg/utils/exp.go @@ -0,0 +1,11 @@ +package utils + +import "math" + +func ExpToLevel(exp int) int { + return int(math.Floor((math.Sqrt(625+100*float64(exp))-25)/50)) + 1 +} + +func LevelToExp(level int) int { + return 25*level*level - 25*level +} diff --git a/requests.http b/requests.http index 680d575..b763010 100644 --- a/requests.http +++ b/requests.http @@ -33,13 +33,14 @@ POST http://localhost:8000/api/games Content-Type: application/json { - "title": "Тестовая игра", + "title": "Тестовая игра 2", "description": "Описание тестовой игры", "type": "city", + "points": 500, "tasks": [ { "title": "Задание 1", - "text": "Текст первого задания", + "text": "Текст первого задания.\n\n*Коды: `nq1111`*", "codes": [ { "description": "1+", @@ -96,11 +97,114 @@ Content-Type: application/json ### -GET http://localhost:8000/api/engine/1 + +POST http://localhost:8000/api/games +Content-Type: application/json + +{ + "title": "Тестовая игра 3", + "description": "Описание тестовой игры", + "type": "city", + "points": 500, + "tasks": [ + { + "title": "Задание 1", + "text": "Текст первого задания.\n\n*Коды: `nq1111`*", + "codes": [ + { + "description": "1+", + "code": "nq1111" + } + ], + "solutions": [] + }, + { + "title": "Задание 2", + "text": "Текст второго задания", + "codes": [ + { + "description": "1+", + "code": "nq2211" + } + ], + "solutions": [] + }, + { + "title": "Задание 3", + "text": "Текст третьего задания", + "codes": [ + { + "description": "1+", + "code": "nq3311" + } + ], + "solutions": [] + }, + { + "title": "Задание 4", + "text": "Текст 4 задания", + "codes": [ + { + "description": "1+", + "code": "nq4411" + } + ], + "solutions": [] + }, + { + "title": "Задание 5", + "text": "Текст 5 задания", + "codes": [ + { + "description": "1+", + "code": "nq5511" + } + ], + "solutions": [] + }, + { + "title": "Задание 6", + "text": "Текст 6 задания", + "codes": [ + { + "description": "1+", + "code": "nq6611" + } + ], + "solutions": [] + }, + { + "title": "Задание 7", + "text": "Текст 7 задания", + "codes": [ + { + "description": "1+", + "code": "nq7711" + } + ], + "solutions": [] + }, + { + "title": "Задание 8", + "text": "Текст 8 задания", + "codes": [ + { + "description": "1+", + "code": "nq8811" + } + ], + "solutions": [] + } + ] +} ### -POST http://localhost:8000/api/engine/1/code +GET http://localhost:8000/api/engine/2 + +### + +POST http://localhost:8000/api/engine/2/code Content-Type: application/json { @@ -108,7 +212,7 @@ Content-Type: application/json } ### -POST http://localhost:8000/api/engine/1/code +POST http://localhost:8000/api/engine/2/code Content-Type: application/json { @@ -116,7 +220,7 @@ Content-Type: application/json } ### -POST http://localhost:8000/api/engine/1/code +POST http://localhost:8000/api/engine/2/code Content-Type: application/json { @@ -124,9 +228,9 @@ Content-Type: application/json } ### -POST http://localhost:8000/api/engine/1/code +POST http://localhost:8000/api/engine/2/code Content-Type: application/json { - "code": "NQ3322" + "code": "NQ3333" } \ No newline at end of file diff --git a/views/engine/view.gotmpl b/views/engine/view.gotmpl deleted file mode 100644 index 6ad8b6b..0000000 --- a/views/engine/view.gotmpl +++ /dev/null @@ -1,83 +0,0 @@ -{{ template "header" . }} - -{{ if .State }} -
Уровень
- - - - - - - - - - - - - - - -
- {{.State.Task.Title}} -
Выдано:{{ .State.CreatedAt.Format "15:04 02.01.2006" }}Автопереход:{{ .State.Deadline.Format "15:04 02.01.2006" }} (через {{ (.State.Deadline.Sub now) | toTime }})
{{ .State.Task.Text | markDown }}
- - - - - - - - - - -
- Ввод кода -
-
-
-
-
- -
- -
-
-
-
- -
История игры
- - - - - - - - - - - {{ range $i, $a := .History }} - - - - - - - {{ end }} - -
УровеньВремя началаВремя окончанияСтатус
{{ inc $i }}{{ $a.CreatedAt.Format "15:04 02.01.2006" }}{{ $a.Deadline.Format "15:04 02.01.2006" }} - {{ if eq $a.Status 0 }} - Текущее - {{ else if eq $a.Status 1 }} - Пройден - {{ else if eq $a.Status 2 }} - Снят - {{ else if eq $a.Status 3 }} - Автопереход - {{ end }} -
-{{ else }} -

Вам не предусмотренно следующее задание

-{{ end }} - -{{ template "footer" . }} \ No newline at end of file diff --git a/views/index.gotmpl b/views/index.gotmpl deleted file mode 100644 index 25590d3..0000000 --- a/views/index.gotmpl +++ /dev/null @@ -1,48 +0,0 @@ -{{ template "header" . }} -

Текущие игры

-{{ range .Games }} - - - - - - - - - - - - - - - - - -
- {{.Title}} -
- Начало - - {{ .StartAt.Format "15:04 02.01.2006" }} -
- {{ .Description | markDown }} - -
- Участвуют: - -
    - {{ range .Teams }} -
  • {{.Team.Name}}
  • - {{ else }} - Никто пока не подал заявку - {{ end }} -
-
-{{ else }} -

- Игр пока не анонсировано -

-{{ end }} -{{ template "footer" . }} \ No newline at end of file diff --git a/views/layout.gotmpl b/views/layout.gotmpl deleted file mode 100644 index 4f31ab0..0000000 --- a/views/layout.gotmpl +++ /dev/null @@ -1,67 +0,0 @@ -{{define "header"}} - - - - - - - nQuest - - - - - - - -
- {{end}} - -{{define "footer"}} -
- - - - -{{end}} \ No newline at end of file diff --git a/views/user/login.gotmpl b/views/user/login.gotmpl deleted file mode 100644 index 6d76dcd..0000000 --- a/views/user/login.gotmpl +++ /dev/null @@ -1,27 +0,0 @@ -{{ template "header" . }} -

Вход

-
-
- {{ if .Error }} - - {{ end }} -
- -
- -
-
-
- -
- -
-
-
-
- -
-
-
-
-{{ template "footer" . }} \ No newline at end of file diff --git a/views/user/register.gotmpl b/views/user/register.gotmpl deleted file mode 100644 index af1a783..0000000 --- a/views/user/register.gotmpl +++ /dev/null @@ -1,39 +0,0 @@ -{{ template "header" . }} -

Регистрация

-
-
- {{ if .Error }} - - {{ end }} -
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- -
-
-
-
-{{ template "footer" . }} \ No newline at end of file