online-judge-mean
online-judge-mean copied to clipboard
A web application for online judge, built with MEAN stack(MongoDB, Express, Angular and Node.js).
Online Judge
A web application for online judge(algorithm questions), built with MEAN stack(MongoDB, Express, Angular and Node.js).


Function
This application is used to solve algorithm questions. You can submit the solution to see if it passes all test cases. Below are the available features.
- Token Based Authentication - Register, Login, Auto Login, User Profile, Reset Password, etc.
- User Management - Create, Update, Delete user.
- Question Management - Create, Update, Delete question.
- Database Management - Import and Export data with csv files for users, questions and submissions.
- Judging System - Judging Engine, Solution Template, Submission History, Multi-programming language support.
- Programming Languages - Three languages are currently supported, including Java, Javascript and Python.
- UI - RichTextEditor, Code Editor, Progress Bar, Loading Image are applied.
The following functions are under development.
- Contest - Generate contest by randomly selecting four questions from the question library.
- Collaborative code editor - Different users can work on the same solution simultaneously.
Technology
The Server is built with Express and MongoDB. The used libraries for server are listed as follows.
- RESTful API: express, express router, mongoose, cors
- Logging: morgan, winston
- User Authentication: jsonwebtoken, passport, cookie-parser, express-jwt
- Import/Export Data: multer, csv-express, fast-csv
The Client is built with Angular and 3rd-party libraries, see below.
- CSS and Icon: bootstrap, font-awesome
- Rich Text Editor: ngx-quill
- Code Editor: ngx-monaco-editor
- Progress Bar: ngx-progressbar
Demo
Three available demos:
Live Demo on Heroku:https://online-judge-mean.herokuapp.com/Live Demo on Netlify:https://online-judge.netlify.com/Live Demo on Azure:https://online-judge.azurewebsites.net/
Note: The demo websites may be slow when you access them for the first time. Be patient!
Try it out on any live demo website with the following accounts:
- Regular User: demo / 123456
- Administrator: admin / 123456
Setup Locally
1. Source Files
git clone https://github.com/jojozhuang/online-judge-mean.git
cd online-judge-mean
npm install
npm run dev
Access http://localhost:9020/ in web browser, enjoy!
- If you run this on Windows, you need to install 'win-node-env' first. Otherwise, server will not get started and you will get 'NODE_ENV is not recognized' error, see “NODE_ENV” is not recognized as an internal or external command, operable command or batch file.
npm install -g win-node-env
2. Configuration
Notice, four different environments are configured for this app. Edit './server/config/server-config.js' to setup your site, especially the MongoDB connection url.
| Environment | Command | Description |
|---|---|---|
| local | npm run local | Development environment using local MongoDB. |
| dev | npm run dev | Development environment using remote MongoDB hosted on mLab. |
| stage | npm run stage | Testing environment using remote MongoDB hosted on mLab. |
| prod | npm run prod | Production environment for deployment. |
3. Master Date
When the server is initially started, use admin user 'jojozhuang' and password '111111' to login. Go to 'Database' to import data for 'users' and 'questions'. The data files are located in 'backup_csv' folder.
Deployment
Follow tutorial Online Judge - Deploying Full Stack Angular App to Heroku to deploy this app to Heroku(RESTful API + Frontend Angular).
Follow tutorial Online Judge - Continuously Deploy MEAN Stack App to Heroku and Netlify with Travis-CI to continuously deploy this Full Stack app to Heroku(RESTful API) and Netlify(Frontend Angular).
Steps(Updated on July 17, 2021)
Manually deploy the same git repo to two apps in heroku. Use Multi Procfile buildpack to deploy multiple apps in a monorepo.
Server
Create app online-judge-api for backend api.
cd online-judge-mean
heroku login
heroku create -a online-judge-api
heroku buildpacks:add -a online-judge-api heroku-community/multi-procfile
heroku buildpacks:add -a online-judge-api heroku/nodejs
heroku config:set -a online-judge-api PROCFILE=server/Procfile
git push https://git.heroku.com/online-judge-api.git HEAD:master
Output.
-----> Building on the Heroku-20 stack
-----> Using buildpacks:
1. heroku-community/multi-procfile
2. heroku/nodejs
-----> Multi-procfile app detected
Copied server/Procfile as Procfile successfully
-----> Node.js app detected
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): 14.16.1
engines.npm (package.json): 6.14.12
Resolving node version 14.16.1...
Downloading and installing node 14.16.1...
npm 6.14.12 already installed with node
-----> Installing dependencies
Installing node modules
> [email protected] install /tmp/build_8088dee8/node_modules/webpack-dev-server/node_modules/fsevents
> node install.js
Skipping 'fsevents' build as platform linux is not supported
> [email protected] postinstall /tmp/build_8088dee8/node_modules/@angular-devkit/build-angular/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"
> [email protected] postinstall /tmp/build_8088dee8/node_modules/nodemon
> node bin/postinstall || exit 0
Love nodemon? You can now support the project via the open collective:
> https://opencollective.com/nodemon/donate
> [email protected] postinstall /tmp/build_8088dee8/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"
> @angular/[email protected] postinstall /tmp/build_8088dee8/node_modules/@angular/cli
> node ./bin/postinstall/script.js
added 1973 packages in 35.405s
-----> Build
Running build
> [email protected] build /tmp/build_8088dee8
> ng build --configuration production
- Generating browser application bundles (phase: setup)...
Compiling @angular/core : es2015 as esm2015
Compiling @angular/common : es2015 as esm2015
Compiling @angular/platform-browser : es2015 as esm2015
Compiling @angular/platform-browser-dynamic : es2015 as esm2015
Compiling @angular/router : es2015 as esm2015
Compiling ngx-bootstrap/utils : es2015 as esm2015
Compiling ngx-bootstrap/alert : es2015 as esm2015
Compiling ngx-bootstrap/positioning : es2015 as esm2015
Compiling ngx-bootstrap/component-loader : es2015 as esm2015
Compiling ngx-bootstrap/modal : es2015 as esm2015
Compiling @angular/common/http : es2015 as esm2015
Compiling ngx-progressbar : es2015 as esm2015
Compiling ngx-progressbar/http : es2015 as esm2015
Compiling @angular/forms : es2015 as esm2015
Compiling ngx-quill : es2015 as esm2015
✔ Browser application bundle generation complete.
- Generating ES5 bundles for differential loading...
✔ Browser application bundle generation complete.
✔ ES5 bundle generation complete.
- Copying assets...
✔ Copying assets complete.
- Generating index html...
✔ Index html generation complete.
Initial Chunk Files | Names | Size
main-es5.90ba2f4cb80e5b7dd7ab.js | main | 601.20 kB
main-es2015.90ba2f4cb80e5b7dd7ab.js | main | 516.32 kB
scripts.21f0c1bd71e842514f91.js | scripts | 460.58 kB
styles.c5cddc00a67a7685f4e0.css | styles | 201.41 kB
polyfills-es5.848e1e43cddfc69fa565.js | polyfills-es5 | 132.31 kB
polyfills-es2015.656bc0fb7423ef9ac49a.js | polyfills | 36.13 kB
runtime-es2015.fa0d675be33153add91d.js | runtime | 3.50 kB
runtime-es5.fa0d675be33153add91d.js | runtime | 3.50 kB
| Initial ES5 Total | 1.37 MB
| Initial ES2015 Total | 1.19 MB
Lazy Chunk Files | Names | Size
161-es5.6c645a8d348aedb1bc37.js | - | 208.98 kB
161-es2015.6c645a8d348aedb1bc37.js | - | 208.98 kB
Build at: 2021-07-18T07:54:32.380Z - Hash: f951e994350c45380bd0 - Time: 159327ms
Warning: /tmp/build_8088dee8/src/app/interceptor/error.interceptor.ts depends on 'rxjs/add/operator/catch'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_8088dee8/src/app/interceptor/error.interceptor.ts depends on 'rxjs/add/operator/do'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_8088dee8/src/app/interceptor/error.interceptor.ts depends on 'rxjs/observable/throw'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_8088dee8/src/app/interceptor/timeout.interceptor.ts depends on 'rxjs/add/operator/timeout'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_8088dee8/src/app/services/alert.service.ts depends on 'rxjs/Subject'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_8088dee8/src/app/services/user.service.ts depends on 'rxjs/add/operator/map'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
-----> Caching build
- node_modules
-----> Pruning devDependencies
removed 1269 packages and audited 705 packages in 17.322s
44 packages are looking for funding
run `npm fund` for details
found 1 moderate severity vulnerability
run `npm audit fix` to fix them, or `npm audit` for details
-----> Build succeeded!
-----> Discovering process types
Procfile declares types -> web
-----> Compressing...
Done: 108.9M
-----> Launching...
Released v5
https://online-judge-api.herokuapp.com/ deployed to Heroku
Client
Create app online-judge-mean for client website.
cd online-judge-mean
heroku login
heroku create -a online-judge-mean
heroku buildpacks:add -a online-judge-mean heroku-community/multi-procfile
heroku buildpacks:add -a online-judge-mean heroku/nodejs
heroku config:set -a online-judge-mean PROCFILE=Procfile
git push https://git.heroku.com/online-judge-mean.git HEAD:master
Output.
-----> Building on the Heroku-20 stack
-----> Using buildpacks:
1. heroku-community/multi-procfile
2. heroku/nodejs
-----> Multi-procfile app detected
cp: '/tmp/build_d0cd865f/Procfile' and '/tmp/build_d0cd865f/Procfile' are the same file
Copied Procfile as Procfile successfully
-----> Node.js app detected
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): 14.16.1
engines.npm (package.json): 6.14.12
Resolving node version 14.16.1...
Downloading and installing node 14.16.1...
npm 6.14.12 already installed with node
-----> Installing dependencies
Installing node modules
> [email protected] install /tmp/build_d0cd865f/node_modules/webpack-dev-server/node_modules/fsevents
> node install.js
Skipping 'fsevents' build as platform linux is not supported
> [email protected] postinstall /tmp/build_d0cd865f/node_modules/@angular-devkit/build-angular/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"
> [email protected] postinstall /tmp/build_d0cd865f/node_modules/nodemon
> node bin/postinstall || exit 0
Love nodemon? You can now support the project via the open collective:
> https://opencollective.com/nodemon/donate
> [email protected] postinstall /tmp/build_d0cd865f/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"
> @angular/[email protected] postinstall /tmp/build_d0cd865f/node_modules/@angular/cli
> node ./bin/postinstall/script.js
added 1973 packages in 36.795s
-----> Build
Running build
> [email protected] build /tmp/build_d0cd865f
> ng build --configuration production
- Generating browser application bundles (phase: setup)...
Compiling @angular/core : es2015 as esm2015
Compiling @angular/common : es2015 as esm2015
Compiling @angular/platform-browser : es2015 as esm2015
Compiling @angular/platform-browser-dynamic : es2015 as esm2015
Compiling @angular/router : es2015 as esm2015
Compiling ngx-bootstrap/utils : es2015 as esm2015
Compiling ngx-bootstrap/alert : es2015 as esm2015
Compiling ngx-bootstrap/positioning : es2015 as esm2015
Compiling ngx-bootstrap/component-loader : es2015 as esm2015
Compiling ngx-bootstrap/modal : es2015 as esm2015
Compiling @angular/common/http : es2015 as esm2015
Compiling ngx-progressbar : es2015 as esm2015
Compiling ngx-progressbar/http : es2015 as esm2015
Compiling @angular/forms : es2015 as esm2015
Compiling ngx-quill : es2015 as esm2015
✔ Browser application bundle generation complete.
- Generating ES5 bundles for differential loading...
✔ Browser application bundle generation complete.
✔ ES5 bundle generation complete.
- Copying assets...
✔ Copying assets complete.
- Generating index html...
✔ Index html generation complete.
Initial Chunk Files | Names | Size
main-es5.90ba2f4cb80e5b7dd7ab.js | main | 601.20 kB
main-es2015.90ba2f4cb80e5b7dd7ab.js | main | 516.32 kB
scripts.21f0c1bd71e842514f91.js | scripts | 460.58 kB
styles.c5cddc00a67a7685f4e0.css | styles | 201.41 kB
polyfills-es5.848e1e43cddfc69fa565.js | polyfills-es5 | 132.31 kB
polyfills-es2015.656bc0fb7423ef9ac49a.js | polyfills | 36.13 kB
runtime-es2015.fa0d675be33153add91d.js | runtime | 3.50 kB
Warning: /tmp/build_d0cd865f/src/app/interceptor/error.interceptor.ts depends on 'rxjs/add/operator/catch'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_d0cd865f/src/app/interceptor/error.interceptor.ts depends on 'rxjs/add/operator/do'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_d0cd865f/src/app/interceptor/error.interceptor.ts depends on 'rxjs/observable/throw'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_d0cd865f/src/app/interceptor/timeout.interceptor.ts depends on 'rxjs/add/operator/timeout'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_d0cd865f/src/app/services/alert.service.ts depends on 'rxjs/Subject'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Warning: /tmp/build_d0cd865f/src/app/services/user.service.ts depends on 'rxjs/add/operator/map'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
runtime-es5.fa0d675be33153add91d.js | runtime | 3.50 kB
| Initial ES5 Total | 1.37 MB
| Initial ES2015 Total | 1.19 MB
Lazy Chunk Files | Names | Size
161-es5.6c645a8d348aedb1bc37.js | - | 208.98 kB
161-es2015.6c645a8d348aedb1bc37.js | - | 208.98 kB
Build at: 2021-07-18T07:59:51.947Z - Hash: 147819932479913ef35d - Time: 169249ms
-----> Caching build
- node_modules
-----> Pruning devDependencies
removed 1269 packages and audited 705 packages in 17.991s
44 packages are looking for funding
run `npm fund` for details
found 1 moderate severity vulnerability
run `npm audit fix` to fix them, or `npm audit` for details
-----> Build succeeded!
-----> Discovering process types
Procfile declares types -> web
-----> Compressing...
Done: 109M
-----> Launching...
Released v4
https://online-judge-mean.herokuapp.com/ deployed to Heroku
Update
Server.
cd online-judge-mean
heroku login
heroku git:remote -a online-judge-api
git commit --allow-empty -m "Upgrading to heroku-20"
git push heroku master
Client.
cd online-judge-mean
heroku login
heroku git:remote -a online-judge-mean
git commit --allow-empty -m "Upgrading to heroku-20"
git push heroku master
How to deploy Angular app to Heroku and serve it as static site(Fake PHP App)
1. composer.json
A PHP app on Heroku requires a composer.json at the root of the directory structure, or an index.php for legacy behavior.
Create composer.json in Angular root directory. In composer.json, add the following line.
{}
2. index.php
Create index.php in src folder. In index.php, add the following line:
<?php include_once("home.html"); ?>
3. home.html
Create src/home.html by copying file src/index.html.
4. Copy home.html and index.php to dist folder
Edit angular.json, modify build/options/index and add index.php to assets. Thus, home.html and index.php will be copied into the output folder dist during build.
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist",
"index": "src/home.html",
...
"assets": [
...
"src/index.php"
],
5. Procfile
A Procfile is a text file in the root directory of your application that defines process types and explicitly declares what command should be executed to start your app. Create Procfile as follows. It will direct heroku to start apache server to serve folder dist.
web: vendor/bin/heroku-php-apache2 dist/
6. Create heroku app and add buildpack
You can do it through heroku CLI or its website.
6.1 Heroku CLI
cd online-judge-mean
heroku login
heroku create -a online-judge-mean
heroku buildpacks:add -a online-judge-mean heroku/nodejs
heroku buildpacks:add -a online-judge-mean heroku/php
The above commands creates a heroku app named online-judge-mean. And adds nodejs buildpack and php buildpack. The nodejs buildpack will compile the Angular app and the php buildpack will serve the output static files as php site.
6.2 Heroku Dashboard
You can also create the app through heorku website. Go to https://dashboard.heroku.com/apps, click Create new app, provide the app name. Go to settings->Buildpacks->Add buildpack, heroku/nodejs first, heroku/php second.
7. Deploy site
Switch to Deploy tab and connect it to your GitHub repo. Then, click Deploy Branch button. Heroku will start the build and launch your site successfully.
8. Example logs
-----> Building on the Heroku-20 stack
-----> Using buildpacks:
1. heroku/nodejs
2. heroku/php
-----> Node.js app detected
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): 14.16.1
engines.npm (package.json): 6.14.12
Resolving node version 14.16.1...
Downloading and installing node 14.16.1...
npm 6.14.12 already installed with node
-----> Installing dependencies
Installing node modules
...
-----> Build
Running build
> [email protected] build /tmp/build_2955a863
> ng build --configuration production
...
-----> Caching build
- node_modules
...
-----> Build succeeded!
-----> PHP app detected
-----> Bootstrapping...
-----> Installing platform packages...
NOTICE: No runtime required in composer.lock; using PHP ^7.3.0 | ^8.0.0
- php (8.0.9)
- composer (1.10.22)
- apache (2.4.48)
- nginx (1.20.1)
-----> Installing dependencies...
Composer version 1.10.22 2021-04-27 13:10:45
-----> Preparing runtime environment...
-----> Checking for additional extensions to install...
-----> Discovering process types
Procfile declares types -> web
-----> Compressing...
Done: 123.2M
-----> Launching...
Released v3
https://online-judge-mean.herokuapp.com/ deployed to Heroku
9. References
- deploy-static-site-heroku.md
- Deploying PHP Apps on Heroku
- https://gist.github.com/jojozhuang/884c24e79bf330ac521a9978717ac088
Troubleshooting
Check the buildpack.
$ heroku git:remote -a online-judge-api
$ heroku buildpacks
=== online-judge-api Buildpack URLs
1. heroku-community/multi-procfile
2. heroku/nodejs
Use the default nodejs buildpack.
heroku buildpacks:set heroku/nodejs
Don't select "Wait for CI to pass before deploy" as Travis-CI is not configured for this GitHub repo.
References:
Portfolio
Read portfolio Online Judge(MEAN) to learn the main functions of this MEAN stack app.
Tutorial
Read tutorial Online Judge - Building Web App with MEAN Stack to learn how this MEAN stack app is built.
Docker
Build for production. All the compiled html files and js files will be generated in dist.
npm run build-nas
Create image with node.
docker build -t jojozhuang/online-judge-server .
docker build -t jojozhuang/online-judge-web .
Create container.
docker run --name online-judge-server -p 9021:80 -d jojozhuang/online-judge-server
docker run --name online-judge-web -p 9020:80 -d jojozhuang/online-judge-web
Access http://192.168.0.2:9020/ in browser.
Rich text editor
To show the math formula correctly in description or solution, need to install katex and add its css and js to angular.js.
"styles": [
"./node_modules/katex/dist/katex.min.css",
],
"scripts": [
"./node_modules/katex/dist/katex.min.js"
],