Skip to content

Commit 49d30b8

Browse files
authored
Merge pull request #95 from CS3219-AY2425S1/jehou/questiondb
Leetcode SPA/Question service upgrades
2 parents 4efaaca + cee960b commit 49d30b8

File tree

11 files changed

+464
-28
lines changed

11 files changed

+464
-28
lines changed

backend/question/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Question Service
2+
3+
## Description
4+
5+
This service is used to manage the programming questions given to the users after matching. It uses MongoDB Atlas to host a cloud database to manage the questions. The service comes with a RESTful API interface to support Create, Read, Update and Delete (CRUD) operations.
6+
7+
This service also includes Jest for unit testing on an isolated Mongo Memory DB server to ensure that all the endpoints work as required.
8+
9+
## Setup
10+
11+
1. Install Node version 18 or above.
12+
2. Run `npm install` to install the dependencies required.
13+
3. Create `.env` file in the `/questions` folder, copying the content from `sample.env`, setting `NODE_ENV` as `DEV` and filling in the MONGO_URI.
14+
4. Run `npm start` to start the service.
15+
16+
## API Documentation
17+
18+
Refer to [`question.yaml`](./docs/question.yaml) file for the API documentation.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
@startuml Question Service
2+
3+
entity Question {
4+
+ questionId : number
5+
+ title : string
6+
+ description : string
7+
+ complexity : string
8+
+ categories : Array<string>
9+
}
10+
11+
entity EditQuestion {
12+
+ title : string
13+
+ description : string
14+
+ complexity : string
15+
+ categories : Array<string>
16+
}
17+
18+
entity Pagination {
19+
+ pagination : number = 1
20+
+ pageSize : number = 10
21+
}
22+
23+
interface IQuestionServiceAPI {
24+
+ GET /
25+
+ POST /create [createQuestion: EditQuestion]
26+
+ POST /all [pagination: Pagination]
27+
+ GET /{id}
28+
+ POST /{id}/update [updateQuestion: EditQuestion]
29+
+ POST /{id}/delete
30+
}
31+
32+
note right of IQuestionServiceAPI
33+
- GET /: Check service status
34+
- POST /create: Create a new question
35+
- POST /all: Retrieve all questions with pagination
36+
- GET /{id}: Retrieve a specific question by ID
37+
- POST /{id}/update: Update a specific question by ID
38+
- POST /{id}/delete: Delete a specific question by ID
39+
end note
40+
41+
class QuestionService {
42+
}
43+
44+
entity QuestionDatabase {
45+
+ questions: Array<Question>
46+
}
47+
48+
QuestionService ..|> IQuestionServiceAPI : implements
49+
QuestionService --> QuestionDatabase : interacts with
50+
51+
@enduml
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
openapi: 3.0.0
2+
info:
3+
title: Question Service API
4+
description: API for managing questions, including CRUD operations.
5+
version: 1.0.0
6+
servers:
7+
# Added by API Auto Mocking Plugin
8+
- description: SwaggerHub API Auto Mocking
9+
url: https://virtserver.swaggerhub.com/JEHOUSOH/Question/1.0.0
10+
- url: http://localhost:3003
11+
description: Local development server
12+
13+
paths:
14+
/:
15+
get:
16+
summary: Check service status
17+
responses:
18+
"200":
19+
description: Service status message
20+
content:
21+
application/json:
22+
schema:
23+
type: object
24+
properties:
25+
message:
26+
type: string
27+
example: Hello from question service!
28+
29+
/create:
30+
post:
31+
summary: Create a new question
32+
requestBody:
33+
required: true
34+
content:
35+
application/json:
36+
schema:
37+
$ref: "#/components/schemas/QuestionCreate"
38+
responses:
39+
"200":
40+
description: Question created successfully
41+
content:
42+
application/json:
43+
schema:
44+
type: object
45+
properties:
46+
message:
47+
type: string
48+
example: Question created successfully
49+
question:
50+
$ref: "#/components/schemas/Question"
51+
"400":
52+
description: Bad Request (validation error)
53+
"500":
54+
description: Internal server error
55+
56+
/all:
57+
post:
58+
summary: Retrieve all questions with pagination
59+
requestBody:
60+
content:
61+
application/json:
62+
schema:
63+
type: object
64+
properties:
65+
pagination:
66+
type: integer
67+
default: 1
68+
description: Page number
69+
page_size:
70+
type: integer
71+
default: 10
72+
description: Number of questions per page
73+
responses:
74+
"200":
75+
description: List of questions
76+
content:
77+
application/json:
78+
schema:
79+
$ref: "#/components/schemas/QuestionAll"
80+
"500":
81+
description: Internal server error
82+
83+
/{id}:
84+
get:
85+
summary: Get a specific question by ID
86+
parameters:
87+
- in: path
88+
name: id
89+
schema:
90+
type: integer
91+
required: true
92+
description: ID of the question
93+
responses:
94+
"200":
95+
description: A specific question
96+
content:
97+
application/json:
98+
schema:
99+
$ref: "#/components/schemas/Question"
100+
"400":
101+
description: Invalid ID format
102+
"404":
103+
description: Question not found
104+
"500":
105+
description: Internal server error
106+
107+
/{id}/update:
108+
post:
109+
summary: Update a specific question by ID
110+
parameters:
111+
- in: path
112+
name: id
113+
schema:
114+
type: integer
115+
required: true
116+
description: ID of the question to update
117+
requestBody:
118+
required: true
119+
content:
120+
application/json:
121+
schema:
122+
$ref: "#/components/schemas/QuestionUpdate"
123+
responses:
124+
"200":
125+
description: Updated question
126+
content:
127+
application/json:
128+
schema:
129+
$ref: "#/components/schemas/QuestionUpdate"
130+
"400":
131+
description: Validation or duplicate title error
132+
"404":
133+
description: Question not found
134+
"500":
135+
description: Internal server error
136+
137+
/{id}/delete:
138+
post:
139+
summary: Delete a specific question by ID
140+
parameters:
141+
- in: path
142+
name: id
143+
schema:
144+
type: integer
145+
required: true
146+
description: ID of the question to delete
147+
responses:
148+
"200":
149+
description: Deleted question
150+
content:
151+
application/json:
152+
schema:
153+
$ref: "#/components/schemas/Question"
154+
"404":
155+
description: Question not found
156+
"500":
157+
description: Internal server error
158+
159+
components:
160+
schemas:
161+
Question:
162+
type: object
163+
properties:
164+
questionid:
165+
type: integer
166+
example: 1
167+
title:
168+
type: string
169+
example: "Two Sum"
170+
description:
171+
type: string
172+
example: "Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.You may assume that each input would have exactly one solution, and you may not use the same element twice.You can return the answer in any order."
173+
category:
174+
type: array
175+
items:
176+
type: string
177+
example: ["Array", "Hash Table"]
178+
complexity:
179+
type: string
180+
example: "Easy"
181+
182+
QuestionCreate:
183+
type: object
184+
required:
185+
- title
186+
- description
187+
- category
188+
- complexity
189+
properties:
190+
title:
191+
type: string
192+
example: "Two Sum"
193+
description:
194+
type: string
195+
example: "Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.You may assume that each input would have exactly one solution, and you may not use the same element twice.You can return the answer in any order."
196+
category:
197+
type: array
198+
items:
199+
type: string
200+
example: ["Array", "Hash Table"]
201+
complexity:
202+
type: string
203+
example: "Easy"
204+
205+
QuestionAll:
206+
type: object
207+
properties:
208+
questions:
209+
type: array
210+
items:
211+
$ref: "#/components/schemas/Question"
212+
example:
213+
- _id: "66f925ddfdfb8e1665720acc"
214+
questionid: 1
215+
title: "Two Sum"
216+
description: "Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume that each input would have exactly one solution, and you may not use the same element twice. You can return the answer in any order. "
217+
category: ["Array", "Hash Table"]
218+
complexity: "Easy"
219+
- _id: "66f925ddfdfb8e1665720acd"
220+
questionid: 2
221+
title: "Add Two Numbers"
222+
description: "You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. "
223+
category: ["Linked List", "Math", "Recursion"]
224+
complexity: "Medium"
225+
- _id: "66f925ddfdfb8e1665720ace"
226+
questionid: 3
227+
title: "Longest Substring Without Repeating Characters"
228+
description: "Given a string s, find the length of the longest substring without repeating characters. "
229+
category: ["Hash Table", "String", "Sliding Window"]
230+
complexity: "Medium"
231+
- _id: "66f925ddfdfb8e1665720acf"
232+
questionid: 4
233+
title: "Median of Two Sorted Arrays"
234+
description: "Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). "
235+
category: ["Array", "Binary Search", "Divide and Conquer"]
236+
complexity: "Hard"
237+
- _id: "66f925ddfdfb8e1665720ad0"
238+
questionid: 5
239+
title: "Longest Palindromic Substring"
240+
description: "Given a string s, return the longest palindromic substring in s. "
241+
category: ["String", "Dynamic Programming"]
242+
complexity: "Medium"
243+
- _id: "66f925ddfdfb8e1665720ad1"
244+
questionid: 6
245+
title: "Reverse Integer"
246+
description: "Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-231, 231 - 1], then return 0. Assume the environment does not allow you to store 64-bit integers (signed or unsigned). "
247+
category: ["Math"]
248+
complexity: "Medium"
249+
- _id: "66f925ddfdfb8e1665720ad2"
250+
questionid: 7
251+
title: "Palindrome Number"
252+
description: "Given an integer x, return true if x is palindrome integer. An integer is a palindrome when it reads the same backward as forward. "
253+
category: ["Math"]
254+
complexity: "Easy"
255+
- _id: "66f925ddfdfb8e1665720ad3"
256+
questionid: 8
257+
title: "Container With Most Water"
258+
description: "You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]). Find two lines that together with the x-axis form a container, such that the container contains the most water. Return the maximum amount of water a container can store. Notice that you may not slant the container. "
259+
category: ["Array", "Two Pointers", "Greedy"]
260+
complexity: "Medium"
261+
- _id: "66f925ddfdfb8e1665720ad4"
262+
questionid: 9
263+
title: "Longest Common Prefix"
264+
description: 'Write a function to find the longest common prefix string amongst an array of strings. If there is no common prefix, return an empty string "". '
265+
category: ["String"]
266+
complexity: "Easy"
267+
- _id: "66f925ddfdfb8e1665720ad5"
268+
questionid: 10
269+
title: "3Sum"
270+
description: "Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0. Notice that the solution set must not contain duplicate triplets. "
271+
category: ["Array", "Two Pointers", "Sorting"]
272+
complexity: "Medium"
273+
274+
currentPage:
275+
type: integer
276+
example: 1
277+
totalPages:
278+
type: integer
279+
example: 10
280+
totalQuestions:
281+
type: integer
282+
example: 100
283+
284+
QuestionUpdate:
285+
type: object
286+
properties:
287+
title:
288+
type: string
289+
example: "Two Sum Updated"
290+
description:
291+
type: string
292+
example: "Updated question description"
293+
category:
294+
type: array
295+
items:
296+
type: string
297+
example: ["Dynamic Programming", "Bit Manipulation"]
298+
complexity:
299+
type: string
300+
example: "Hard"

backend/question/src/routes/questionRoutes.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ router.post(
5050
);
5151

5252
// Retrieve all questions
53-
router.get("/all", async (req: Request, res: Response) => {
54-
const pagination = parseInt(req.body.pagination as string, 10) || 1; // Default page is 1
53+
router.post("/all", async (req: Request, res: Response) => {
54+
let pagination = parseInt(req.body.pagination as string, 10) || 1; // Default page is 1
5555
const page_size = parseInt(req.body.page_size as string, 10) || 10; // Default limit is 10
5656
const skip = (pagination - 1) * page_size; // Calculate how many documents to skip
5757
try {
@@ -72,11 +72,13 @@ router.get("/all", async (req: Request, res: Response) => {
7272
.exec();
7373

7474
const total = await Question.countDocuments().exec();
75+
const totalPages = Math.ceil(total / page_size);
76+
if (totalPages < pagination) pagination = 1;
7577

7678
return res.json({
7779
questions,
7880
currentPage: pagination,
79-
totalPages: Math.ceil(total / page_size),
81+
totalPages: totalPages,
8082
totalQuestions: total,
8183
});
8284
} catch (error) {

0 commit comments

Comments
 (0)