A web application for online judge(algorithm questions), built with MEAN stack(MongoDB, Express, Angular and Node.js).
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.
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
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
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
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. |
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.
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).
Manually deploy the same git repo to two apps in heroku. Use Multi Procfile buildpack
to deploy multiple apps in a monorepo.
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
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
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
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.
{}
Create index.php
in src
folder. In index.php, add the following line:
<?php include_once("home.html"); ?>
Create src/home.html
by copying file src/index.html
.
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"
],
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/
You can do it through heroku CLI or its website.
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.
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.
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.
-----> 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
- deploy-static-site-heroku.md
- Deploying PHP Apps on Heroku
- https://gist.github.com/jojozhuang/884c24e79bf330ac521a9978717ac088
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:
Read portfolio Online Judge(MEAN) to learn the main functions of this MEAN stack app.
Read tutorial Online Judge - Building Web App with MEAN Stack to learn how this MEAN stack app is built.
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.
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"
],