Code Monkey home page Code Monkey logo

cl-judge's People

Contributors

cjchirag7 avatar dependabot[bot] avatar nbnaradhya avatar ridhishjain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

cl-judge's Issues

DB tables

Tables

  • contests table
id (primary key)
show_leaderboard (tiny int, 0/1)
public (tiny int, 0/1)
confidential (tiny int, default 0)
creator (username, admin only, foreign key from users table)
name (string)
start_time (timestamp)
end_time (timestamp)
participants_count (int)
about (string)
rules (string, can be null)
prizes (string, can be null)
  • contests_groups_map table
id (primary key)
contest_id (foreign key from `contests` table)
group_id (foreign key from `groups` table)
  • contests_moderators_map table
id (primary key)
contest_id (foreign key from `contests` table)
moderator_username (foreign key from `users` table)
  • contests_participants_map table
id (primary key)
contest_id (foreign key from `contests` table)
participant_username (foreign key from `users` table)
  • questions table
id (primary key)
creator (foreign key from `users` table)
type (tiny int, 0 - MCQ, similar)
name (string)
problem statement (string)
input_format (string)
output_format (string)
constraints (string)
options (string, JSON array)
correct (int, index of correct option)
difficulty (int, 1-easy, 2-medium, 3-hard, can be 0 by default - not specified)
  • questions_editors_map table
id (primary key)
question_id (foreign key from `questions` table)
editor_username (foreign key from `users` table)
  • tags table
id (primary key)
description (string)
name (string)
  • questions_tags_map table
id (primary key)
question_id (foreign key from `questions` table)
tag_id (foreign key from `tags` table)
  • contests_questions_map table
id (primary key)
question_id (foreign key from `questions` table)
contest_id (foreign key from `contests` table)
max_score (int)
  • submissions table
id (primary key)
question_id (foreign_key from `questions` table)
contest_id (foreign_key from `contests` table)
username (foreign_key from `users` table)
user_submission (string)
output (string)
submission_time (timestamp)
judged (tiny int, default 0)
score (int, default 0)
  • leaderboard table
id (primary key)
rank (int)
uesrname (foreign key from `users` table)
contest_id (foreign_key from `contests` table)
score (int, total score)
total_time (total penalty yet)
attempted_count (int)

Schemas

Schemas

Contests

  • POST /contests/: createContest
  • POST /contests/:contest_id/moderator: addModerator
  • DELETE /contests/:contest_id/moderator: removeModerator
    Not needed:
  • POST /contests/:contest_id/participate: participate
  • POST /contests/:contest_id/update: updateContest
  • GET /contests?active=true&past=true&upcoming=true&limit=3&offset=5: getContests
  • GET /contests/moderator_contests?limit=3&offset=5: getModeratorContests
  • GET /contests/:contest_id: getContest
  • GET /contests/:contest_id/moderators: getContestModerators
  • GET /contests/:contest_id/questions: getAllQuestions
  • GET /contests/:contest_id/questions/:question_id: getQuestion
  • GET /contests/:contest_id/participants: getAllParticipants
  • GET /contests/:contest_id/participants?details=true: getAllParticipantsDetails
  • GET /contests/:contest_id/leaderboard: getLeaderboard
  • GET /contests/:contest_id/questions/:question_id/leaderboard: getQuestionLeaderboard

Questions:

  • POST /questions/: createQuestion
  • GET /questions/moderator_questions?limit=5&search=’’: getModeratorQuestions
  • GET /questions/:question_id: to get the question
  • POST /questions/:question_id/update, Editor only: to edit the questions, the change will be reflected in all instances of the question
  • GET /questions/: - send all public questions with their contest_id (for practice section)
  • POST /questions/:question_id/editor Editor only: Add editor to a question
  • DELETE /questions/:question_id/editor Editor only: Remove editor to a question (creator can't be removed)
  • POST /questions/:question_id/fork Editor only: Return the id of the forked new question

Submissions

  • POST /contest/:contest_id/questions/:question_id/submit: createSubmission
    Not needed:
  • GET /contest/:contest_id/submissions/:submission_id: getSubmission
  • GET /contest/:contest_id/submissions?user=username: getAllUserSubmissions
  • GET /contest/:contest_id/submissions: getAllSubmissions

Tags

  • POST /tag: createTag
    Not needed:
  • GET /tags?search=keyword: getTags

Create endpoints related to 'notifications' and 'groups'

Notifications

Create a table notifications with the following fields -

  • id (primary key)
  • heading
  • description (optional)
  • created_at
  • link

Create a table user_notifications with the following fields -

The above table will contain mappings between user and notifications.

  • id (primary key)
  • username (foreign key from user table)
  • notification_id (foreign key from notification table)

The below endpoints would be available to all the users -

  • GET '/notifications?limit=3' : Get the most recent 3 notifications of the user

  • GET '/notifications' : Get all the notifications for the user

  • Frontend would provide only access_token of the user in request

Groups

Create a table groups with the following fields -

  • id (primary key)
  • name
  • confidential (boolean)
  • creator (username of the creator of group, as there can be multiple admins in a particular group)
  • member_count (number of members of that group)

Create a table user_groups with the following fields -

  • id (primary key)
  • username (foreign key from user table)
  • group_id (foreign key from group table)
  • admin (boolean)
    The above table will contain many-to-many mappings of user and groups.

These endpoints would only be accessible to admins only -

  • GET /groups/admin-groups - Returns a list of all (both confidential and non-confidential) the groups in which the user is present as an admin. This should contain name, creator and member_count of the groups.
  • POST /groups/add-group - Frontend would send name for group, confidential (boolean) and usernames ( a JSON array of usernames to be added in that group ). The array may be empty
  • POST groups/:group-id/add-members - Frontenend would send a JSON array of usernames to be added in the group with id as group-id
  • POST groups/:group-id/make-admin - Frontend would send a username who should be made an admin ( A group admin can create more group admins or remove group admins, except the creator of the group)
  • POST groups/:group-id/remove-admin - Frontend would send a username who should be removed from admin
  • POST groups/:group-id/update-name - Frontend would send new name for the group, which should be updated.
  • POST groups/:group-id/add-branch - Frontend would send a branch code and a department code. Users who are having those branch code and department code and not present in the group already, should be added to the group

These endpoints would be accessible to all users -

  • GET /groups - Returns a list of all non-confidential groups in which the user is present (not necessary, as admin)
  • GET /groups/:group-id - Returns group name and a list of members of the group. Each member object have the fields - Full Name, username, admin (boolean), profileImg . Note : For non-admins, these information would be accessible only if the group is not confidential.

The frontend would need to provide the access_token of user in the header of each of the requests

Note : Once, tables and endpoints for both notifications and groups have been created, make sure that following notifications are generated automatically :

  1. When users are added to a non-confidential group, they must receive a notification :
{ heading : 'Added to group ${group-name}',
description: `You have been added to the group ${group-name}` ,
created_at: "timestamp of the notification",
link: 'http://${FRONTEND_HOST}:${FRONTEND_PORT}/groups/${group-id}'}
  1. When a user is added as an admin, he must receive a notification :
{ heading : 'Promoted to admin of ${group-name}',
description: `You have been promoted to admin in the group ${group-name}` ,
created_at: "timestamp of the notification",
link: 'http://${FRONTEND_HOST}:${FRONTEND_PORT}/groups/${group-id}'}
  1. When a user is removed from an admin, he must receive a notification :
{ heading : 'Removed from admin of ${group-name}',
description: `You have been removed from admin in the group ${group-name}` ,
created_at: "timestamp of the notification",
link: 'http://${FRONTEND_HOST}:${FRONTEND_PORT}/groups/${group-id}'}

Suggestions for changes are welcome.

Dept and branch fields in user info

Add a dept, branch, and bio column in the user table, API change:

  • /signup (branch and department from frontend as integer)
  • /getUser (send branch and department as integer to frontend)
  • /updateUser (update value of branch and department integer taken from frontend in DB)

Bio:

  • /getUser (send bio as a string to frontend)
  • /updateUser (take bio as a string and update in DB)

Department:

INSERT INTO `department` (`
id`,
`dept_name
`) VALUES
(0, 'Electrical Engineering'),
(1, 'Computer Science and Engineering'),
(2, 'Electronics Engineering'),
(3, 'Applied Mathematics'),
(4, 'Applied Physics'),
(5, 'Mechanical Engineering'),
(6, 'Civil Engineering'),
(7, 'Chemical Engineering'),
(8, 'Environmental Science and Engineering'),
(9, 'Mining Engineering'),
(10, 'Petroleum Engineering'),
(11, 'Humanities and Social Sciences'),
(12, 'Management Studies'),
(13, 'Fuel and Mineral Engineering'),
(14, 'Mining Machinery Engineering');

Branch

INSERT INTO `branch` (`
id`,
`branch_name
`) VALUES
(0, 'B.Tech'),
(1, 'M.Tech'),
(2, 'Dual Degree'),
(3, 'Integrated B.Tech and M.Tech');

Travis CI integration

Set up travis for continuous integration for checking build status of the repo after every commit

Group and Notifications Endpoints Tracker

notifications table

  • id (primary key)
  • heading
  • description (optional, will contain link in markdown)
  • created_at
  • creator

user_notifications table

  • id (primary key)
  • username (foreign key from user table)
  • notification_id (foreign key from notification table)
  • read (boolean)

Notifications API (all users)

Frontend would provide only access_token of the user in request

  • GET /notifications?limit=3: Get the most recent 3 notifications of the user
  • GET /notifications: Get all the notifications for the user
  • POST /notifications Admin Only: Create a new notification, may be public or with some target_usernames
  • GET /notifications/creator_notifications Admin Only: Get all the notifications created by the user

groups table

  • id (primary key)
  • group_name
  • confidential (boolean)
  • creator (username of the creator of the group, as there can be multiple admins in a particular group)
  • member_count (number of members of that group)

user_groups table

  • id (primary key)
  • username (foreign key from user table)
  • group_id (foreign key from group table)
  • is_group_moderator (boolean)

Groups API

The frontend would need to provide the access_token of user in the header of each of the requests

  • POST /groups/ Admin only: Frontend would send group_name, confidential and usernames ( a JSON array of usernames to be added in that group ). The array may be empty.

  • DELETE /groups/:group_id Admin only: Only the creator should be able to delete a group.

  • POST groups/:group_id/branch Moderator only: receive a branch code, a department code and an admission_year . Users who are having those branch code, department code, and admission_year and not present in the group already, should be added to the group

  • DELETE groups/:group_id/branch Moderator only: receive a branch code, a department code and an admission_year . Users who are having those branch code, department code, and admission_year and present in the group, should be removed from the group

  • POST groups/:group_id/members Moderator only: receive a JSON array of usernames to be added in the group with id as group_id.

  • DELETE groups/:group_id/members Moderator only: receive a JSON array of usernames to be removed in the group with id as group_id.

  • POST groups/:group_id/moderator Moderator only: receive username who should be made an admin ( A group admin can create more group admins or remove group admins, except the creator of the group)

  • DELETE groups/:group_id/moderator Moderator only: receive a username who should be removed from admin

  • POST groups/:group_id/update Moderator only: receive a new group_name, which should be updated.

  • GET /groups: all non-confidential groups in which the user is present.

  • GET /groups/moderator_groups Moderator only: all (confidential and non-confidential) the groups in which the user is present as a moderator. This should contain group_name, creator and member_count of the groups.

  • GET /groups/:group_id: specific group (must be non-confidential for normal user, doesn't matter if moderator) with group_name, creator and a list of members of the group. Each member object have the fields - fullName, username, isGroupModerator, profileImg.

`verifyModerator` middlware for contests

verifyModerator middlware for contests:
i'll do this in a new PR for these APIs

  • createContest
    POST /contests/ Admin only: create a contest
  • updateContest
    POST /contests/:contest_id/update Moderator only: update contest
  • addModerator
    POST /contests/:contest_id/moderator Moderator only: Add moderator
  • removeModerator
    DELETE /contests/:contest_id/moderator Moderator only: remove moderator (creator can't be deleted)
  • addGroup
    POST /contests/:contest_id/:groups Moderator only: Add group
  • removeGroup
    DELETE /contests/:contest_id/groups Moderator only: remove group

and rest will be built accordingly

Originally posted by @ridhishjain in #77 (comment)

Contests and Questions tracker

Tables

  • contests table
id (primary key)
show_leaderboard (tiny int, 0/1)
public (tiny int, 0/1)
confidential_questions (tiny int, default 0)
creator (username, admin only, foreign key from users table)
name (string)
start_time (timestamp)
end_time (timestamp)
participants_count (int)
about (string)
rules (string, can be null)
prizes (string, can be null)
  • contests_groups_map table
id (primary key)
contest_id (foreign key from `contests` table)
group_id (foreign key from `groups` table)
  • contests_moderators_map table
id (primary key)
contest_id (foreign key from `contests` table)
moderator_username (foreign key from `users` table)
  • contests_participants_map table
id (primary key)
contest_id (foreign key from `contests` table)
participant_username (foreign key from `users` table)
  • questions table
id (primary key)
creator (foreign key from `users` table)
type (tiny int, 0 - MCQ, similar)
name (string)
problem statement (string)
input_format (string)
output_format (string)
constraints (string)
options (string, JSON array)
correct (int, index of correct option)
difficulty (int, 1-easy, 2-medium, 3-hard, can be 0 by default - not specified)
  • questions_editors_map table
id (primary key)
question_id (foreign key from `questions` table)
editor_username (foreign key from `users` table)
  • tags table
id (primary key)
description (string)
name (string)
  • questions_tags_map table
id (primary key)
question_id (foreign key from `questions` table)
tag_id (foreign key from `tags` table)
  • contests_questions_map table
id (primary key)
question_id (foreign key from `questions` table)
contest_id (foreign key from `contests` table)
max_score (int)
  • mcq_submissions table
id (primary key)
question_id (foreign_key from `questions` table)
contest_id (foreign_key from `contests` table)
username (foreign_key from `users` table)
response (int, index of option selected),
submission_time (timestamp)
judged (tiny int, default 0)
score (int, default 0)
  • subjective_submissions table
id (primary key)
question_id (foreign_key from `questions` table)
contest_id (foreign_key from `contests` table)
username (foreign_key from `users` table)
response (text),
submission_time (timestamp)
judged (tiny int, default 0)
score (int, default 0)
feedback (varchar, if the moderator wants to give any feedback after checking)
  • leaderboard table
id (primary key)
uesrname (foreign key from `users` table)
contest_id (foreign_key from `contests` table)
score (int, total score)
total_time (time, total penalty yet)
attempted_count (int)

API

Contests API

  • createContest
    POST /contests/ Admin only

  • updateContest
    POST /contests/:contest_id/update Moderator only

  • addModerator
    POST /contests/:contest_id/moderator Moderator only

  • removeModerator
    DELETE /contests/:contest_id/moderator Moderator only

  • addGroup
    POST /contests/:contest_id/:groups Moderator only

  • removeGroup
    DELETE /contests/:contest_id/groups Moderator only

  • getContests
    GET /contests?status=active&limit=5

  • getModeratorContests
    GET /contests/moderator_contests?limit=5 Moderator only

  • getContest
    GET /contests/:contest_id

  • getContestDetails
    GET /contests/:contest_id/details?only_name=false Moderator only

  • getContestModerators
    GET /contests/:contest_id/moderators Moderator only

  • getAllParticipants
    GET /contests/:contest_id/participants

  • getAllParticipantsDetails
    GET /contests/:contest_id/participants_details Moderator only

  • participate
    POST /contests/:contest_id/participate

  • addQuestion
    POST /contests/:contest_id/:questions

  • removeQuestion
    DELETE /contests/:contest_id/questions

  • getAllQuestions
    GET /contests/:contest_id/questions

  • getQuestion
    GET /contests/:contest_id/questions/:question_id

Questions API:

  • createQuestion
    POST /questions/ Admin only: to create a question

  • getModeratorQuestions
    GET /questions/moderator_questions?limit=5&search=’’ Moderator only: show the questions for which user is a moderator

  • getQuestion
    GET /questions/:question_id, Editor only: to get the question

  • updateQuestion
    POST /questions/:question_id/update, Editor only: to edit the questions, the change will be reflected in all instances of the question

  • getAllQuestions
    GET /questions/: - send all public questions with their contest_id (for practice section)

  • addEditor
    POST /questions/:question_id/editor Editor only: Add editor to a question

  • removeEditor
    DELETE /questions/:question_id/editor Editor only: Remove editor to a question (creator can't be removed)

  • forkQuestion
    POST /questions/:question_id/fork Editor only: Return the id of the forked new question

Submissions API

  • createSubmission
    POST /contests/:contest_id/questions/:question_id/submit All participants: everyone eligible for the contest should be allowed (For MCQ, allow only 1 attempt)

  • getAllSubmissions
    GET /contests/:contest_id/submissions Contest Moderator only: See all submissions (pagination, sorting, filtering and searching enabled)

  • getUserContestSubmissions
    GET /contests/:contest_id/users/:user_id/submissions The user only: get all submissions of a user

  • gradeSubjectiveSubmission
    POST /contests/:contest_id/subjective_submissions/:submission_id/grade Contest Moderator only: Grade a subjective submission providing a score along with an optional feedback. (If submission is already judged/graded, update it)

  • getMCQSubmission
    GET /contests/:contest_id/mcq_submissions/:submission_id Only the specific user: Get a specific MCQ submission
    GET /contests/:contest_id/mcq_submissions/:submission_id?moderator=true Contest Moderator only: Get a specific MCQ submission

  • getSubjectiveSubmission
    GET /contests/:contest_id/subjective_submissions/:submission_id Only the specific user: Get a specific subjective submission.
    GET /contests/:contest_id/subjective_submissions/:submission_id?moderator=true Contest Moderator only: Get a specific subjective submission

  • getContestLeaderboard
    GET /contests/:contest_id/leaderboard All participants: Everyone should be allowed, if show_leaderboard is true, otherwise allow only contest moderators.

  • getQuestionLeaderboard
    GET /contests/:contest_id/questions/:question_id/leaderboard:Everyone should be allowed, if show_leaderboard is true, otherwise allow only contest moderators.

  • getPracticeLeaderboard
    GET /practice/leaderboard: accessible to all

Tags API:

  • createTag
    POST /tag Admin only:

  • getTag
    GET /tag?search=keyword

Delete token from frontend when it gets expired

If the user sends a request with expired token, he receives the following response :

"error": {
        "name": "TokenExpiredError",
        "message": "jwt expired",
        "expiredAt": "2020-10-18T17:42:44.000Z"
    }

This needs to be handled, as well. Better way seems, we can delete the token once it has been expired, similar to what we are doing when a user logs out.

Auth APIs

  • verify_email => return "already verified" instead of error if the db column is verified already
  • forgot_password => check if the email is verified before sending the reset password link

Update Info APIs should be moved to a different directory to avoid confusion

here's an idea:
what if all the APIs under the auth folder which requires access_token are shifted to user folder... like this:
I think it will remove a lot of confusion.

    - auth
        - index.js
        - signup.js
        - login.js
        - resetPassword.js
        - forgotPassword.js
        - verifyEmail.js
        - verifyNewEmail.js
        - isCorrect.js
    -user
        - index.js
        - getUser.js
        - updateUser.js
        - updatePassword.js
        - updateProfileImage.js

Also, these upadteInfo APIs really dont come under auth section

Originally posted by @ridhishjain in #39 (comment)

Notifications

Note: Once, tables and endpoints for both notifications and groups have been created, make sure that the following notifications are generated automatically:

  • When users are added to a non-confidential group:
{
    heading : 'Added to group ${group-name}',
    description: `You have been added to the group [${group-name}](http://${FRONTEND_HOST}:${FRONTEND_PORT}/groups/${group-id})` ,
}
  • When a user is added as a moderator:
{
    heading : 'Promoted to moderator of ${group-name}',
    description: `You have been promoted to moderator of the group [${group-name}](http://${FRONTEND_HOST}:${FRONTEND_PORT}/groups/${group-id})` ,
}
  • When a user is removed from a moderator:
{
    heading : 'Removed from moderator of ${group-name}',
    description: `You are no longer a moderator of the group [${group-name}](http://${FRONTEND_HOST}:${FRONTEND_PORT}/groups/${group-id})` ,
}

Create an endpoint to resend OTP

  • After signing up, it may be possible that due to some issues, user has not received the OTP.
  • So, the user can be resent that OTP using this endpoint, if the user is not verified and the OTP has not expired yet. Otherwise, he should get an error message:
    OTP Expired. Try signing up again."
    (This should work because our OTP is valid for 24 hours)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.