Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions question-service/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts
/generated/prisma

/generated/prisma
4 changes: 4 additions & 0 deletions question-service/app/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import express from "express";
import cors from "cors";
import questionRoutes from "./routes/question-routes.js";

const app = express();

Expand All @@ -11,6 +12,9 @@ app.get("/healthz", (req, res) => {
res.status(200).json({ status: "ok" });
});

// Use question routes
app.use("/questions", questionRoutes);

app.use("/api", (req, res) => {
res.json({ message: "Question service is running!" });
});
Expand Down
41 changes: 41 additions & 0 deletions question-service/app/routes/question-routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import express from "express";
import {PrismaClient} from '../../generated/prisma/index.js';

const router = express.Router();
const prisma = new PrismaClient();

// GET /questions - Retrieve all questions
router.get("/", async (req, res) => {
const {difficulty, topic} = req.query;
let questions;

try {
// If a difficulty or topic is provided, filter questions accordingly
if (difficulty || topic) {
questions = await prisma.question.findMany({
where: {
...(difficulty && {difficulty: difficulty.toUpperCase()}),
...(topic && {topic: topic}),
},
});

if (questions.length === 0) {
return res.status(404).json({error: "No questions found matching the criteria"});
}

//pick one random question from the filtered list
const randomIndex = Math.floor(Math.random() * questions.length);
res.json(questions[randomIndex]);

} else {
// If no filters, return the first 100 questions
questions = await prisma.question.findMany({take: 100});
res.json(questions);
}
} catch (error) {
console.error("Error fetching questions:", error);
res.status(500).json({error: "Internal Server Error"});
}
});

export default router;
40 changes: 40 additions & 0 deletions question-service/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "linux-musl-openssl-3.0.x"]
output = "../generated/prisma"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model Question {
id Int @id @default(autoincrement())
title String
description String
descriptionImages String[] @default([])
constraints String[] @default([])
examples Json?
solution String
difficulty Difficulty
language String?
topic String
followUp String?
createdAt DateTime @default(now())
}

model User {
id String @id
username String @unique
email String @unique
password String
createdAt DateTime @default(now())
isAdmin Boolean @default(false)
}

enum Difficulty {
EASY
MEDIUM
HARD
}
25 changes: 25 additions & 0 deletions question-service/prisma/seed/check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { PrismaClient } from "../../generated/prisma/index.js";

const prisma = new PrismaClient();

async function main() {
const question = await prisma.question.findUnique({
where: { id: 2000 },
});

console.log("Title:", question.title);
console.log("Description:\n", question.description);

if (question.examples) {
question.examples.forEach((ex, i) => {
console.log(ex.text); // this will render \n as real line breaks
if (ex.image) console.log("Image:", ex.image);
});
}
}

main()
.catch(console.error)
.finally(async () => {
await prisma.$disconnect();
});
15 changes: 15 additions & 0 deletions question-service/prisma/seed/clear-questions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PrismaClient } from "../../generated/prisma/index.js";
const prisma = new PrismaClient();

async function main() {
await prisma.question.deleteMany(); // deletes all rows in Question table
console.log("All questions deleted!");
}

main()
.catch((e) => {
console.error(e);
})
.finally(async () => {
await prisma.$disconnect();
});
101,923 changes: 101,923 additions & 0 deletions question-service/prisma/seed/questions-list-cleaned.json

Large diffs are not rendered by default.

101,923 changes: 101,923 additions & 0 deletions question-service/prisma/seed/questions-list.json

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions question-service/prisma/seed/seed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {PrismaClient} from '../../generated/prisma/index.js';
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';

// To use __dirname in ES modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const dataPath = path.join(__dirname, 'questions-list-cleaned.json');

// Initialize Prisma Client
const prisma = new PrismaClient();
async function main() {
//read from JSON file
const data = JSON.parse(fs.readFileSync(dataPath, 'utf-8'));

for (const q of data) {

// Skip if any compulsory field missing
if (!q.title || !q.description || !q.solution || !q.difficulty || !q.topic) continue;

// Skip if difficulty not one of EASY, MEDIUM, HARD
const difficulty = q.difficulty.toUpperCase();
if (!["EASY","MEDIUM","HARD"].includes(difficulty)) continue;

//create question
await prisma.question.create({
data: {
title: q.title, // question title
description: q.description, // question description
descriptionImages: q.description_images || [], // question images if any
constraints: q.constraints || [], // question constraints if any
examples: q.examples || null, // question output examples if any
solution: q.solution, // solution to question
difficulty: q.difficulty.toUpperCase(), // question difficulty (enum: EASY/MEDIUM/HARD)
language: q.language || null, // question language
topic: q.topic, // question topic
followUp: q.follow_up || null, // question follow up if any
},
});
}
console.log('question insert completed.');
}

// Execute the main function and handle errors
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});