├── executor ├── .gitignore ├── requirements.txt ├── Dockerfile ├── executor_server.py └── executor_utils.py ├── oj-client ├── src │ ├── assets │ │ └── .gitkeep │ ├── app │ │ ├── app.component.css │ │ ├── components │ │ │ ├── navbar │ │ │ │ ├── navbar.component.css │ │ │ │ ├── navbar.component.spec.ts │ │ │ │ ├── navbar.component.ts │ │ │ │ └── navbar.component.html │ │ │ ├── new-problem │ │ │ │ ├── new-problem.component.css │ │ │ │ ├── new-problem.component.spec.ts │ │ │ │ ├── new-problem.component.ts │ │ │ │ └── new-problem.component.html │ │ │ ├── problem-detail │ │ │ │ ├── problem-detail.component.css │ │ │ │ ├── problem-detail.component.html │ │ │ │ ├── problem-detail.component.spec.ts │ │ │ │ └── problem-detail.component.ts │ │ │ ├── editor │ │ │ │ ├── editor.component.css │ │ │ │ ├── editor.component.spec.ts │ │ │ │ ├── editor.component.html │ │ │ │ └── editor.component.ts │ │ │ └── problem-list │ │ │ │ ├── problem-list.component.css │ │ │ │ ├── problem-list.component.html │ │ │ │ ├── problem-list.component.spec.ts │ │ │ │ └── problem-list.component.ts │ │ ├── app.component.html │ │ ├── models │ │ │ └── problem.model.ts │ │ ├── pipes │ │ │ ├── search.pipe.spec.ts │ │ │ └── search.pipe.ts │ │ ├── app.component.ts │ │ ├── services │ │ │ ├── data.service.spec.ts │ │ │ ├── input.service.spec.ts │ │ │ ├── input.service.ts │ │ │ ├── collaboration.service.spec.ts │ │ │ ├── collaboration.service.ts │ │ │ └── data.service.ts │ │ ├── app.routes.ts │ │ ├── app.component.spec.ts │ │ ├── app.module.ts │ │ └── mock-problems.ts │ ├── styles.css │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── typings.d.ts │ ├── tsconfig.app.json │ ├── index.html │ ├── tsconfig.spec.json │ ├── main.ts │ ├── test.ts │ └── polyfills.ts ├── e2e │ ├── app.po.ts │ ├── tsconfig.e2e.json │ └── app.e2e-spec.ts ├── .editorconfig ├── tsconfig.json ├── .gitignore ├── protractor.conf.js ├── karma.conf.js ├── README.md ├── package.json ├── .angular-cli.json └── tslint.json ├── oj-server ├── .gitignore ├── models │ └── problemModel.js ├── package.json ├── module │ └── redisClient.js ├── server.js ├── services │ ├── problemService.js │ └── editorSocketService.js ├── routes │ └── rest.js └── package-lock.json ├── public ├── favicon.ico ├── glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttf ├── glyphicons-halflings-regular.f4769f9bdb7466be6508.eot ├── glyphicons-halflings-regular.448c34a56d699c29117a.woff2 ├── glyphicons-halflings-regular.fa2772327f55d8198301.woff ├── index.html ├── inline.bundle.js.map ├── inline.bundle.js ├── main.bundle.js.map └── main.bundle.js ├── README.md └── launch.sh /executor/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc -------------------------------------------------------------------------------- /oj-client/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oj-server/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /oj-client/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /executor/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | docker 3 | -------------------------------------------------------------------------------- /oj-client/src/app/components/navbar/navbar.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oj-client/src/app/components/new-problem/new-problem.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-detail/problem-detail.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oj-client/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /oj-client/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /oj-client/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qichen90/Collaborative-Online-Judge-System/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /oj-client/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qichen90/Collaborative-Online-Judge-System/HEAD/oj-client/src/favicon.ico -------------------------------------------------------------------------------- /oj-client/src/app/models/problem.model.ts: -------------------------------------------------------------------------------- 1 | export class Problem { 2 | id: number; 3 | name: string; 4 | desc: string; 5 | difficulty: string; 6 | } -------------------------------------------------------------------------------- /oj-client/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /public/glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qichen90/Collaborative-Online-Judge-System/HEAD/public/glyphicons-halflings-regular.e18bbf611f2a2e43afc0.ttf -------------------------------------------------------------------------------- /public/glyphicons-halflings-regular.f4769f9bdb7466be6508.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qichen90/Collaborative-Online-Judge-System/HEAD/public/glyphicons-halflings-regular.f4769f9bdb7466be6508.eot -------------------------------------------------------------------------------- /public/glyphicons-halflings-regular.448c34a56d699c29117a.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qichen90/Collaborative-Online-Judge-System/HEAD/public/glyphicons-halflings-regular.448c34a56d699c29117a.woff2 -------------------------------------------------------------------------------- /public/glyphicons-halflings-regular.fa2772327f55d8198301.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qichen90/Collaborative-Online-Judge-System/HEAD/public/glyphicons-halflings-regular.fa2772327f55d8198301.woff -------------------------------------------------------------------------------- /oj-client/src/app/pipes/search.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { SearchPipe } from './search.pipe'; 2 | 3 | describe('SearchPipe', () => { 4 | it('create an instance', () => { 5 | const pipe = new SearchPipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /oj-client/e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /oj-client/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'app'; 10 | } 11 | -------------------------------------------------------------------------------- /executor/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | LABEL maintainer="qichen90" 3 | 4 | RUN apt-get update 5 | RUN apt-get install -y openjdk-8-jdk 6 | RUN apt-get install -y python3 7 | # need to build image again 8 | # docker build -t $imagename -f Dockerfile 9 | RUN apt-get install -y g++ 10 | -------------------------------------------------------------------------------- /oj-client/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "es2015", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test.ts", 11 | "**/*.spec.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /oj-client/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /oj-client/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Collaborative-Online-Judge-System 2 | 3 | This online judge system is Google-Doc like collaborative code editor. 4 | 5 | Major parts: 6 | oj-client : Angular2-based front end with bootstrap 7 | oj-server : node.js backend platform with express.js middleware 8 | executor: Python Flask server with Docker Engine API 9 | 10 | -------------------------------------------------------------------------------- /oj-server/models/problemModel.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | // Capitalize Number, String. 3 | const ProblemSchema = mongoose.Schema({ 4 | id: Number, 5 | name: String, 6 | desc: String, 7 | difficulty: String 8 | }); 9 | 10 | const ProblemModel = mongoose.model('ProblemModel', ProblemSchema); 11 | 12 | module.exports = ProblemModel; -------------------------------------------------------------------------------- /oj-client/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('oj-client App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('Welcome to app!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /oj-client/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OjClient 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /oj-client/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "types": [ 8 | "jasmine", 9 | "node" 10 | ] 11 | }, 12 | "files": [ 13 | "test.ts" 14 | ], 15 | "include": [ 16 | "**/*.spec.ts", 17 | "**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /oj-client/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.log(err)); 13 | -------------------------------------------------------------------------------- /oj-client/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /oj-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "target": "es5", 11 | "typeRoots": [ 12 | "node_modules/@types" 13 | ], 14 | "lib": [ 15 | "es2017", 16 | "dom" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-detail/problem-detail.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |

6 | {{problem.id}}. {{problem.name}} 7 |

8 |

9 | {{problem.desc}} 10 |

11 |
12 |
13 | 16 |
-------------------------------------------------------------------------------- /oj-client/src/app/services/data.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { DataService } from './data.service'; 4 | 5 | describe('DataService', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [DataService] 9 | }); 10 | }); 11 | 12 | it('should be created', inject([DataService], (service: DataService) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /oj-client/src/app/pipes/search.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { Problem } from '../models/problem.model'; 3 | 4 | @Pipe({ 5 | name: 'search' 6 | }) 7 | export class SearchPipe implements PipeTransform { 8 | 9 | transform(problems: Problem[], term: string): Problem[] { 10 | // get filtered problem list 11 | return problems.filter( 12 | problem => problem.name.toLowerCase().includes(term)); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /oj-client/src/app/services/input.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { InputService } from './input.service'; 4 | 5 | describe('InputService', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [InputService] 9 | }); 10 | }); 11 | 12 | it('should be created', inject([InputService], (service: InputService) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /oj-client/src/app/components/editor/editor.component.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | #editor { 3 | height: 600px; 4 | } 5 | .lang-select { 6 | width: 100px; 7 | margin-right: 10px; 8 | } 9 | header .btn { 10 | margin: 0 5px; 11 | } 12 | footer .btn { 13 | margin: 0 5px; 14 | } 15 | .editor-footer, .editor-header { 16 | margin: 10px 0; 17 | } 18 | .cursor { 19 | /*position:absolute;*/ 20 | background: rgba(0, 250, 0, 0.5); 21 | z-index: 40; 22 | width: 2px !important; 23 | } 24 | } -------------------------------------------------------------------------------- /oj-client/src/app/services/input.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 3 | import { Observable } from 'rxjs/Rx'; 4 | 5 | @Injectable() 6 | export class InputService { 7 | private inputSubject$ = new BehaviorSubject(''); 8 | constructor() { } 9 | 10 | changeInput(term) { 11 | this.inputSubject$.next(term); 12 | } 13 | 14 | getInput(): Observable { 15 | return this.inputSubject$.asObservable(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /oj-client/src/app/services/collaboration.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { CollaborationService } from './collaboration.service'; 4 | 5 | describe('CollaborationService', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [CollaborationService] 9 | }); 10 | }); 11 | 12 | it('should be created', inject([CollaborationService], (service: CollaborationService) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /oj-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oj-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.18.2", 14 | "express": "^4.16.2", 15 | "mongoose": "^5.0.3", 16 | "node-rest-client": "^3.1.0", 17 | "redis": "^2.8.0", 18 | "socket.io": "^2.0.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-list/problem-list.component.css: -------------------------------------------------------------------------------- 1 | .difficulty { 2 | min-width: 65px; 3 | margin-right: 10px; 4 | } 5 | 6 | .label.difficulty { 7 | padding-top: 0.6em; 8 | color: #fbfdfa; 9 | font-size: 12px; 10 | } 11 | 12 | .title { 13 | font-size: 1.2em; 14 | } 15 | 16 | .diff-easy { 17 | background-color: #42ebf4; 18 | } 19 | 20 | .diff-medium { 21 | background-color: #92cf5c; 22 | } 23 | 24 | .diff-hard { 25 | background-color: #dd0d1e; 26 | } 27 | 28 | .diff-super { 29 | background-color: #8d16e2; 30 | } -------------------------------------------------------------------------------- /launch.sh: -------------------------------------------------------------------------------- 1 | #! bin/bash 2 | # bash for launching the application in mac os 3 | # sh launch.sh 4 | 5 | # fuser -k 3000/tcp #not working on mac os 6 | # fuser -k 5000/tcp 7 | 8 | # brew services restart redis 9 | 10 | # cd ./oj-client 11 | # ng build --watch & 12 | 13 | cd ./oj-server 14 | npm start & 15 | 16 | cd ./executor 17 | # pip3 install requirements.txt 18 | python3 executor_server.py & 19 | 20 | echo "===app runing===" 21 | read -p "PRESS [enter] to terminate processes." PRESSKEY 22 | 23 | # fuser -k 3000/tcp 24 | # fuser -k 5000/tcp 25 | brew services stop redis -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-list/problem-list.component.html: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /executor/executor_server.py: -------------------------------------------------------------------------------- 1 | import json 2 | from flask import Flask 3 | app = Flask(__name__) 4 | from flask import jsonify 5 | from flask import request 6 | 7 | import executor_utils as eu 8 | 9 | @app.route('/build_and_run', methods=['POST']) 10 | def build_and_run(): 11 | data = request.get_json() 12 | if 'code' not in data or 'lang' not in data: 13 | return 'No code or language found' 14 | code = data['code'] 15 | lang = data['lang'] 16 | 17 | print("API got called with code: %s in %s" % (code, lang)) 18 | 19 | result = eu.build_and_run(code, lang) 20 | 21 | return jsonify(result) 22 | 23 | if __name__ == '__main__': 24 | eu.load_image() # load docker image 25 | app.run(debug=True) -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OjClient 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /oj-client/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /dist-server 6 | /tmp 7 | /out-tsc 8 | 9 | # dependencies 10 | /node_modules 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.sass-cache 30 | /connect.lock 31 | /coverage 32 | /libpeerconnection.log 33 | npm-debug.log 34 | testem.log 35 | /typings 36 | 37 | # e2e 38 | /e2e/*.js 39 | /e2e/*.map 40 | 41 | # System Files 42 | .DS_Store 43 | Thumbs.db 44 | -------------------------------------------------------------------------------- /oj-client/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /oj-client/src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes, RouterModule} from '@angular/router'; 2 | import { ProblemListComponent } from './components/problem-list/problem-list.component'; 3 | import { ProblemDetailComponent } from './components/problem-detail/problem-detail.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | redirectTo: 'problems', 9 | pathMatch: 'full'//exactly match 10 | }, 11 | { 12 | path: 'problems', 13 | component: ProblemListComponent 14 | }, 15 | { 16 | path: 'problems/:id', 17 | component: ProblemDetailComponent 18 | }, 19 | { 20 | path: '**', 21 | redirectTo: 'problems' 22 | } 23 | ] 24 | 25 | export const routing = RouterModule.forRoot(routes); -------------------------------------------------------------------------------- /oj-client/src/app/components/editor/editor.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { EditorComponent } from './editor.component'; 4 | 5 | describe('EditorComponent', () => { 6 | let component: EditorComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ EditorComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(EditorComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /oj-client/src/app/components/navbar/navbar.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NavbarComponent } from './navbar.component'; 4 | 5 | describe('NavbarComponent', () => { 6 | let component: NavbarComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ NavbarComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NavbarComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /oj-client/src/app/components/new-problem/new-problem.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NewProblemComponent } from './new-problem.component'; 4 | 5 | describe('NewProblemComponent', () => { 6 | let component: NewProblemComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ NewProblemComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NewProblemComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-list/problem-list.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProblemListComponent } from './problem-list.component'; 4 | 5 | describe('ProblemListComponent', () => { 6 | let component: ProblemListComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProblemListComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProblemListComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-detail/problem-detail.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ProblemDetailComponent } from './problem-detail.component'; 4 | 5 | describe('ProblemDetailComponent', () => { 6 | let component: ProblemDetailComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ProblemDetailComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProblemDetailComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /oj-client/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /oj-server/module/redisClient.js: -------------------------------------------------------------------------------- 1 | var redis = require('redis'); 2 | 3 | // only one client created 4 | var client = redis.createClient(); 5 | 6 | function set(key, value, callback) { 7 | client.set(key, value, function(err, res) { 8 | if(err) { 9 | console.log(err); 10 | return ; 11 | } 12 | callback(res); 13 | }); 14 | } 15 | 16 | function get(key, callback) { 17 | client.get(key, function(err, res){ 18 | if(err) { 19 | console.log(err); 20 | return ; 21 | } 22 | callback(res); 23 | }); 24 | } 25 | 26 | // since redis is used as cache, data only valid for a period 27 | function expire(key, timeInSeconds){ 28 | client.expire(key, timeInSeconds); 29 | } 30 | 31 | function quit() { 32 | client.quit(); 33 | } 34 | 35 | module.exports = { 36 | get: get, 37 | set: set, 38 | expire: expire, 39 | quit: quit, 40 | redisPrint: redis.print 41 | }; -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-detail/problem-detail.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { DataService } from '../../services/data.service'; 3 | import { Problem } from '../../models/problem.model'; 4 | import { ActivatedRoute, Params } from '@angular/router'; 5 | 6 | @Component({ 7 | selector: 'app-problem-detail', 8 | templateUrl: './problem-detail.component.html', 9 | styleUrls: ['./problem-detail.component.css'] 10 | }) 11 | export class ProblemDetailComponent implements OnInit { 12 | problem: Problem; 13 | 14 | constructor(private dataService: DataService, 15 | private route: ActivatedRoute) { } 16 | 17 | ngOnInit() { 18 | // subscribe: when params changes, this.problem will be updated 19 | // +: conver string to int 20 | this.route.params.subscribe(params => { 21 | this.dataService.getProblem(+params['id']) 22 | .then(problem => this.problem = problem); 23 | }); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /oj-client/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular/cli'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular/cli/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | angularCli: { 23 | environment: 'dev' 24 | }, 25 | reporters: ['progress', 'kjhtml'], 26 | port: 9876, 27 | colors: true, 28 | logLevel: config.LOG_INFO, 29 | autoWatch: true, 30 | browsers: ['Chrome'], 31 | singleRun: false 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /oj-client/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | describe('AppComponent', () => { 4 | beforeEach(async(() => { 5 | TestBed.configureTestingModule({ 6 | declarations: [ 7 | AppComponent 8 | ], 9 | }).compileComponents(); 10 | })); 11 | it('should create the app', async(() => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.debugElement.componentInstance; 14 | expect(app).toBeTruthy(); 15 | })); 16 | it(`should have as title 'app'`, async(() => { 17 | const fixture = TestBed.createComponent(AppComponent); 18 | const app = fixture.debugElement.componentInstance; 19 | expect(app.title).toEqual('app'); 20 | })); 21 | it('should render title in a h1 tag', async(() => { 22 | const fixture = TestBed.createComponent(AppComponent); 23 | fixture.detectChanges(); 24 | const compiled = fixture.debugElement.nativeElement; 25 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); 26 | })); 27 | }); 28 | -------------------------------------------------------------------------------- /oj-server/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const restRouter = require('./routes/rest'); 4 | const mongoose = require('mongoose'); 5 | const path = require('path'); 6 | const http = require('http'); 7 | 8 | // remeber to add database user 9 | mongoose.connect('mongodb://qichen90:cs5036@ds125068.mlab.com:25068/problems-db') 10 | 11 | app.use('/api/v1', restRouter); 12 | 13 | app.use(express.static(path.join(__dirname,'../public'))); 14 | app.use((req, res) => { 15 | res.sendFile('index.html', {root: path.join(__dirname, '../public')}); 16 | }); 17 | 18 | 19 | var socketIO = require('socket.io'); 20 | var io = socketIO(); 21 | var editorSocketService = require('./services/editorSocketService')(io); // function call 22 | //connect io with server 23 | const server = http.createServer(app); 24 | io.attach(server); 25 | server.listen(3000); 26 | server.on('listening', onListening); 27 | 28 | // listening call back 29 | function onListening(){ 30 | console.log('App listening on port 3000...'); 31 | } 32 | 33 | // app.listen(3000, () => console.log('Example app listening on port 3000!')); -------------------------------------------------------------------------------- /oj-client/README.md: -------------------------------------------------------------------------------- 1 | # OjClient 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.6.7. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /oj-client/src/app/components/navbar/navbar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormControl } from '@angular/forms'; 3 | import { Subscription } from 'rxjs/Subscription'; 4 | import { Router } from '@angular/router'; 5 | import { InputService } from '../../services/input.service'; 6 | import 'rxjs/add/operator/debounceTime'; 7 | 8 | @Component({ 9 | selector: 'app-navbar', 10 | templateUrl: './navbar.component.html', 11 | styleUrls: ['./navbar.component.css'] 12 | }) 13 | export class NavbarComponent implements OnInit { 14 | title = 'LabCode'; 15 | searchBox: FormControl = new FormControl(); 16 | subscription: Subscription; 17 | 18 | constructor(private inputService: InputService, 19 | private router: Router) { } 20 | 21 | ngOnInit() { 22 | this.subscription = this.searchBox 23 | .valueChanges 24 | .debounceTime(200) 25 | .subscribe(term => {this.inputService.changeInput(term)}); 26 | } 27 | 28 | ngOnDestroy() { 29 | this.subscription.unsubscribe(); 30 | } 31 | 32 | searchProblem(): void { 33 | this.router.navigate(['/problems']); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /oj-client/src/app/components/problem-list/problem-list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Problem } from '../../models/problem.model'; 3 | import { DataService } from '../../services/data.service'; 4 | import { Subscription } from 'rxjs/Subscription'; 5 | import { InputService } from '../../services/input.service'; 6 | 7 | @Component({ 8 | selector: 'app-problem-list', 9 | templateUrl: './problem-list.component.html', 10 | styleUrls: ['./problem-list.component.css'] 11 | }) 12 | export class ProblemListComponent implements OnInit { 13 | problems: Problem[]; 14 | subcriptionProblems: Subscription; 15 | // for navbar 16 | searchTerm: String = ''; 17 | subscriptionInput: Subscription; 18 | 19 | constructor(private dataService: DataService, 20 | private inputService: InputService) { } 21 | 22 | ngOnInit() { 23 | this.getProblems(); 24 | this.getSearchTerm(); 25 | } 26 | ngOnDestroy() { 27 | this.subcriptionProblems.unsubscribe(); 28 | } 29 | 30 | getProblems() { 31 | this.subcriptionProblems = this.dataService.getProblems() 32 | .subscribe(problems => { 33 | this.problems = problems; 34 | }); 35 | } 36 | 37 | getSearchTerm(): void { 38 | this.subscriptionInput = this.inputService.getInput() 39 | .subscribe(term => this.searchTerm = term); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /oj-client/src/app/components/navbar/navbar.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /oj-client/src/app/components/new-problem/new-problem.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Problem } from '../../models/problem.model'; 3 | import { DataService } from '../../services/data.service'; 4 | 5 | const DEFAULT_PROBLEM: Problem = Object.freeze({ 6 | id: 0, 7 | name: '', 8 | desc: '', 9 | difficulty: 'easy' 10 | }) 11 | 12 | @Component({ 13 | selector: 'app-new-problem', 14 | templateUrl: './new-problem.component.html', 15 | styleUrls: ['./new-problem.component.css'] 16 | }) 17 | export class NewProblemComponent implements OnInit { 18 | // create a shadow copy of problem and assign it to newProblem 19 | // Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value. 20 | newProblem: Problem = Object.assign({}, DEFAULT_PROBLEM); 21 | difficulties: string[] = ['easy', 'medium', 'hard', 'super']; 22 | 23 | constructor(private dataService: DataService) { } 24 | 25 | ngOnInit() { 26 | } 27 | 28 | addProblem(){ 29 | this.dataService.addProblem(this.newProblem); 30 | // assign newProblem a new problem instance 31 | // Otherwise newProblem have same reference as the one we added to the list 32 | // then when next time add new problem, it will override the problem we have already add into the problem list. 33 | this.newProblem = Object.assign({}, DEFAULT_PROBLEM); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /oj-client/src/app/components/new-problem/new-problem.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 6 | 7 | 9 |
10 |
11 | 12 | 14 |
15 |
16 | 17 | 22 |
23 |
24 |
25 | 27 |
28 |
29 |
30 |
-------------------------------------------------------------------------------- /oj-client/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 4 | import { HttpClientModule } from '@angular/common/http'; 5 | import { CollaborationService } from './services/collaboration.service'; 6 | 7 | 8 | import { AppComponent } from './app.component'; 9 | import { ProblemListComponent } from './components/problem-list/problem-list.component'; 10 | 11 | import { DataService } from './services/data.service'; 12 | import { ProblemDetailComponent } from './components/problem-detail/problem-detail.component'; 13 | import { InputService } from './services/input.service'; 14 | 15 | import { routing } from './app.routes'; 16 | import { NewProblemComponent } from './components/new-problem/new-problem.component'; 17 | import { NavbarComponent } from './components/navbar/navbar.component'; 18 | import { EditorComponent } from './components/editor/editor.component'; 19 | import { SearchPipe } from './pipes/search.pipe' 20 | 21 | 22 | @NgModule({ 23 | declarations: [ 24 | AppComponent, 25 | ProblemListComponent, 26 | ProblemDetailComponent, 27 | NewProblemComponent, 28 | NavbarComponent, 29 | EditorComponent, 30 | SearchPipe 31 | ], 32 | imports: [ 33 | BrowserModule, 34 | routing, 35 | FormsModule, 36 | HttpClientModule, 37 | ReactiveFormsModule 38 | ], 39 | providers: [DataService, 40 | CollaborationService, 41 | InputService 42 | ], 43 | bootstrap: [AppComponent] 44 | }) 45 | export class AppModule { } 46 | -------------------------------------------------------------------------------- /oj-client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oj-client", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve", 8 | "build": "ng build --prod", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@angular/animations": "^5.2.0", 16 | "@angular/common": "^5.2.0", 17 | "@angular/compiler": "^5.2.0", 18 | "@angular/core": "^5.2.0", 19 | "@angular/forms": "^5.2.0", 20 | "@angular/http": "^5.2.0", 21 | "@angular/platform-browser": "^5.2.0", 22 | "@angular/platform-browser-dynamic": "^5.2.0", 23 | "@angular/router": "^5.2.0", 24 | "ace-builds": "^1.3.0", 25 | "bootstrap": "^3.3.7", 26 | "core-js": "^2.4.1", 27 | "jquery": "^3.3.1", 28 | "rxjs": "^5.5.6", 29 | "socket.io": "^2.0.4", 30 | "zone.js": "^0.8.19" 31 | }, 32 | "devDependencies": { 33 | "@angular/cli": "1.6.7", 34 | "@angular/compiler-cli": "^5.2.0", 35 | "@angular/language-service": "^5.2.0", 36 | "@types/jasmine": "~2.8.3", 37 | "@types/jasminewd2": "~2.0.2", 38 | "@types/node": "~6.0.60", 39 | "codelyzer": "^4.0.1", 40 | "jasmine-core": "~2.8.0", 41 | "jasmine-spec-reporter": "~4.2.1", 42 | "karma": "~2.0.0", 43 | "karma-chrome-launcher": "~2.2.0", 44 | "karma-coverage-istanbul-reporter": "^1.2.1", 45 | "karma-jasmine": "~1.1.0", 46 | "karma-jasmine-html-reporter": "^0.2.2", 47 | "protractor": "~5.1.2", 48 | "ts-node": "~4.1.0", 49 | "tslint": "~5.9.1", 50 | "typescript": "~2.5.3" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /oj-client/src/app/mock-problems.ts: -------------------------------------------------------------------------------- 1 | import { Problem } from './models/problem.model'; 2 | 3 | export const PROBLEMS: Problem[] = [ 4 | { 5 | "id":1, 6 | "name":"Two Sum", 7 | "desc":"Given an array of integers, find two numbers such that they add up to a specific target number.\n\nThe function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are NOT zero-based.", 8 | "difficulty":"easy" 9 | }, 10 | { 11 | "id":2, 12 | "name":"3Sum", 13 | "desc":"Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.", 14 | "difficulty":"medium" 15 | }, 16 | { 17 | "id":3, 18 | "name":"4Sum", 19 | "desc":"Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target?\n\nFind all unique quadruplets in the array which gives the sum of target.", 20 | "difficulty":"medium" 21 | }, 22 | { 23 | "id":4, 24 | "name":"Triangle Count", 25 | "desc":"Given an array of integers, how many three numbers can be found in the array, so that we can build an triangle whose three edges length is the three numbers that we find?", 26 | "difficulty":"hard"}, 27 | { 28 | "id":5, 29 | "name":"Sliding Window Maximum", 30 | "desc":"Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration from the start of the array, find the maximum number inside the window at each moving.", 31 | "difficulty":"super" 32 | } 33 | ]; -------------------------------------------------------------------------------- /oj-client/src/app/services/collaboration.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Observable } from 'rxjs/Observable'; 3 | import { Subject } from 'rxjs/Subject'; 4 | 5 | declare var io: any; // io is already imported in angular.cli.json 6 | 7 | @Injectable() 8 | export class CollaborationService { 9 | collaborationSocket: any; 10 | private _userSource = new Subject(); 11 | constructor() { } 12 | 13 | init(editor: any, sessionId: string): Observable { 14 | // send to server 15 | this.collaborationSocket = io(window.location.origin, {query: 'sessionId=' + sessionId}); 16 | // //wait for 'message' event from server 17 | // this.collaborationSocket.on("message", (message) => { 18 | // console.log('message received from the server: ' + message); 19 | // }) 20 | 21 | // handle the changes from server 22 | this.collaborationSocket.on('change', (delta: string) => { 23 | console.log('collaboration: editor changes by ' + delta); 24 | delta = JSON.parse(delta); 25 | editor.lastAppliedChange = delta; 26 | // apply the changes on editor 27 | editor.getSession().getDocument().applyDeltas([delta]); 28 | }); 29 | // handle user changes 30 | this.collaborationSocket.on('userchange', (users: string[]) => { 31 | console.log('user changed: ' + users); 32 | this._userSource.next(users.toString()); 33 | }) 34 | 35 | return this._userSource.asObservable(); 36 | } 37 | 38 | // emit event to make changes and inform server and other collaborators 39 | change(delta: string): void { 40 | // emit "change" event 41 | this.collaborationSocket.emit('change', delta); 42 | } 43 | 44 | restoreBuffer(): void { 45 | // let the server handle the event 46 | this.collaborationSocket.emit('restoreBuffer'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /oj-server/services/problemService.js: -------------------------------------------------------------------------------- 1 | const ProblemModel = require('../models/problemModel'); 2 | 3 | const getProblems = function(){ 4 | // in the callback function, the first argument is error 5 | // do not forget to handle error 6 | return new Promise((resolve, reject) => { 7 | ProblemModel.find({}, (err, problems) => { 8 | if(err) { 9 | reject(err); 10 | }else { 11 | resolve(problems); 12 | } 13 | }); 14 | }); 15 | }; 16 | 17 | const getProblem = function(id){ 18 | return new Promise((resolve, reject) => { 19 | ProblemModel.findOne({id: id}, (err, problem) => { 20 | if(err) { 21 | reject(err); 22 | }else { 23 | resolve(problem); 24 | } 25 | }); 26 | }); 27 | }; 28 | 29 | const addProblem = function(newProblem){ 30 | return new Promise((resolve, reject) => { 31 | ProblemModel.findOne({name: newProblem.name}, (err, problem) => { 32 | //if problem already exists 33 | if(problem) { 34 | reject("Problem name already exists!"); 35 | }else { 36 | ProblemModel.count({}, (err, num) => { 37 | if(err){ 38 | reject(err); 39 | } 40 | newProblem.id = num + 1; 41 | // create mongodb object 42 | let mongoProblem = new ProblemModel(newProblem); 43 | mongoProblem.save(); 44 | resolve(mongoProblem); 45 | }); 46 | } 47 | }); 48 | }); 49 | }; 50 | 51 | // modify problem 52 | const editProblem = function(editedProblem){ 53 | return new Promise((resolve, reject) => { 54 | ProblemModel.update({name: editedProblem.name}, (err, problem) => { 55 | if(!problem){ 56 | reject('No problem exists!'); 57 | }else{ 58 | resolve(problem); 59 | } 60 | }); 61 | }); 62 | }; 63 | 64 | module.exports = { 65 | getProblems, 66 | getProblem, 67 | addProblem, 68 | editProblem 69 | }; -------------------------------------------------------------------------------- /oj-client/src/app/components/editor/editor.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 9 | 10 | 11 | 14 | 15 | 16 | 36 |
37 |
38 |
39 |
40 |
41 | Output: {{output}} 42 |
43 |
44 | Users: {{users}} 45 |
46 |
47 |
48 | 50 |
51 |
-------------------------------------------------------------------------------- /oj-server/routes/rest.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | // request body is json format, json parser is used to parse the body 5 | const bodyParser = require('body-parser'); 6 | const jsonParser = bodyParser.json(); 7 | 8 | const problemService = require('../services/problemService'); 9 | 10 | const nodeRestClient = require('node-rest-client').Client; 11 | const restClient = new nodeRestClient(); 12 | EXECUTOR_SERVER_URL = 'http://localhost:5000/build_and_run'; 13 | restClient.registerMethod('build_and_run', EXECUTOR_SERVER_URL, 'POST'); 14 | 15 | //GET all problems 16 | router.get('/problems', (req, res) => { 17 | problemService.getProblems() 18 | .then(problems => res.json(problems)); 19 | }); 20 | 21 | //GET problem by id 22 | router.get('/problems/:id', (req, res) => { 23 | const id = req.params.id; 24 | problemService.getProblem(+id) 25 | .then(problem => res.json(problem)); 26 | }); 27 | 28 | //POST new problem 29 | router.post('/problems', jsonParser, (req, res) => { 30 | problemService.addProblem(req.body) 31 | .then(problem => res.json(problem), 32 | error => res.status(400).send("Problem name already exists!") 33 | ); 34 | }); 35 | 36 | // build and run problem 37 | router.post('/build_and_run', jsonParser, (req, res) => { 38 | const userCode = req.body.code; 39 | const lang = req.body.lang; 40 | console.log('lang: ' + lang + ', code: ' + userCode); 41 | const args = {data: {code: userCode, lang: lang}, 42 | headers: {'Content-Type': 'application/json'}}; 43 | 44 | restClient.methods.build_and_run( 45 | args, 46 | (data, response) => { 47 | const text = `Build output: ${data['build']}, execute output: ${data['run']}`; 48 | console.log(text); 49 | res.json(text); 50 | } 51 | ); 52 | }); 53 | 54 | // edit problem 55 | router.put('/problems', jsonParser, (req, res) => { 56 | problemService.editProblem(req.body) 57 | .then(problem => res.json(problem), 58 | error => res.status(400).send("Failed to update problem")); 59 | }); 60 | 61 | module.exports = router; -------------------------------------------------------------------------------- /oj-client/.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "oj-client" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "../public", 10 | "assets": [ 11 | "assets", 12 | "favicon.ico" 13 | ], 14 | "index": "index.html", 15 | "main": "main.ts", 16 | "polyfills": "polyfills.ts", 17 | "test": "test.ts", 18 | "tsconfig": "tsconfig.app.json", 19 | "testTsconfig": "tsconfig.spec.json", 20 | "prefix": "app", 21 | "styles": [ 22 | "styles.css", 23 | "../node_modules/bootstrap/dist/css/bootstrap.min.css" 24 | ], 25 | "scripts": [ 26 | "../node_modules/jquery/dist/jquery.js", 27 | "../node_modules/bootstrap/dist/js/bootstrap.js", 28 | "../node_modules/ace-builds/src-min-noconflict/ace.js", 29 | "../node_modules/ace-builds/src-min-noconflict/theme-eclipse.js", 30 | "../node_modules/ace-builds/src-min-noconflict/mode-java.js", 31 | "../node_modules/ace-builds/src-min-noconflict/mode-python.js", 32 | "../node_modules/ace-builds/src-min-noconflict/mode-c_cpp.js", 33 | "../node_modules/socket.io-client/dist/socket.io.js" 34 | ], 35 | "environmentSource": "environments/environment.ts", 36 | "environments": { 37 | "dev": "environments/environment.ts", 38 | "prod": "environments/environment.prod.ts" 39 | } 40 | } 41 | ], 42 | "e2e": { 43 | "protractor": { 44 | "config": "./protractor.conf.js" 45 | } 46 | }, 47 | "lint": [ 48 | { 49 | "project": "src/tsconfig.app.json", 50 | "exclude": "**/node_modules/**" 51 | }, 52 | { 53 | "project": "src/tsconfig.spec.json", 54 | "exclude": "**/node_modules/**" 55 | }, 56 | { 57 | "project": "e2e/tsconfig.e2e.json", 58 | "exclude": "**/node_modules/**" 59 | } 60 | ], 61 | "test": { 62 | "karma": { 63 | "config": "./karma.conf.js" 64 | } 65 | }, 66 | "defaults": { 67 | "styleExt": "css", 68 | "component": {} 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /oj-client/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following for the Reflect API. */ 41 | // import 'core-js/es6/reflect'; 42 | 43 | 44 | /** Evergreen browsers require these. **/ 45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 46 | import 'core-js/es7/reflect'; 47 | 48 | 49 | /** 50 | * Required to support Web Animations `@angular/platform-browser/animations`. 51 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation 52 | **/ 53 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 54 | 55 | 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js/dist/zone'; // Included with Angular CLI. 61 | 62 | 63 | 64 | /*************************************************************************************************** 65 | * APPLICATION IMPORTS 66 | */ 67 | -------------------------------------------------------------------------------- /oj-client/src/app/services/data.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Problem } from '../models/problem.model'; 3 | import { HttpClient, HttpRequest, HttpResponse } from '@angular/common/http'; 4 | import { Observable } from 'rxjs/Rx'; 5 | import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 6 | import { HttpHeaders } from '@angular/common/http'; 7 | 8 | @Injectable() 9 | export class DataService { 10 | private _problemSource = new BehaviorSubject([]); 11 | 12 | constructor(private httpClient: HttpClient) { } 13 | 14 | // return a list of problems 15 | getProblems(): Observable { 16 | this.httpClient.get('api/v1/problems') 17 | .toPromise() 18 | .then((res: any) => { 19 | this._problemSource.next(res); 20 | }) 21 | .catch(this.handleError); 22 | return this._problemSource.asObservable(); 23 | 24 | } 25 | //use subscribe 26 | // getProblems(): Observable { 27 | // this.httpClient.get('api/v1/problems') 28 | // .subscribe((res:any) => this._problemSource.next(res)); 29 | // return this._problemSource.asObservable(); 30 | 31 | // } 32 | 33 | // return a problem by id 34 | getProblem(id: number): Promise { 35 | return this.httpClient.get(`api/v1/problems/${id}`) 36 | .toPromise() 37 | .then((res: any) => res) 38 | .catch(this.handleError); 39 | } 40 | 41 | // add problem 42 | addProblem(problem: Problem){ 43 | const options = {headers: new HttpHeaders({'Content-Type': 'application/json'})}; 44 | return this.httpClient.post('api/v1/problems', problem, options) 45 | .toPromise() 46 | .then((res: any) => { 47 | this.getProblems(); 48 | return res; 49 | }) 50 | .catch(this.handleError); 51 | } 52 | 53 | // build and run: POST 54 | buildAndRun(data): Promise{ 55 | const options = {headers: new HttpHeaders({'Content-Type': 'application/json'})}; 56 | return this.httpClient.post('api/v1/build_and_run', data, options) 57 | .toPromise() 58 | .then(res => { 59 | console.log(res); 60 | return res; 61 | }) 62 | .catch(this.handleError); 63 | } 64 | 65 | // // modify problem 66 | // editProblem(problem: Problem) { 67 | // const options = {headers: new HttpHeaders({'Content-Type': 'application/json'})}; 68 | // return this.httpClient.post('api/v1/problems', problem, options) 69 | // .toPromise() 70 | // . 71 | // } 72 | 73 | // handle errors 74 | private handleError(error: any): Promise{ 75 | console.error('Error reference', error); 76 | return Promise.reject(error.body || error); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /oj-client/src/app/components/editor/editor.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { CollaborationService } from '../../services/collaboration.service'; 3 | import { ActivatedRoute, Params } from '@angular/router'; 4 | import { DataService } from '../../services/data.service'; 5 | import { Subscription } from 'rxjs/Subscription'; 6 | 7 | declare var ace: any;// must be declared 8 | @Component({ 9 | selector: 'app-editor', 10 | templateUrl: './editor.component.html', 11 | styleUrls: ['./editor.component.css'] 12 | }) 13 | export class EditorComponent implements OnInit { 14 | editor: any; 15 | 16 | defaultContent = { 17 | 'Java': `public class Solution{ 18 | public static void main(String[] args){ 19 | // Please type your code here... 20 | } 21 | }`, 22 | 'Python': `class Solution: 23 | def example(): 24 | # Please type your code here... 25 | `, 26 | 'C++':`int main(){ 27 | /* Please type your code here... */ 28 | }` 29 | } 30 | 31 | languages: string[] = ['Java', 'Python', 'C++']; 32 | language: string = 'Java'; 33 | sessionId: string; 34 | 35 | output: string; 36 | 37 | users: string; 38 | subscriptionUsers: Subscription; 39 | 40 | // inject route service and collaborationService 41 | constructor(private collaboration: CollaborationService, 42 | private route: ActivatedRoute, 43 | private dataService: DataService) { } 44 | 45 | ngOnInit() { 46 | this.route.params 47 | .subscribe(params => { 48 | this.sessionId = params['id']; 49 | this.initEditor(); 50 | this.collaboration.restoreBuffer(); 51 | }); 52 | } 53 | 54 | resetEditor(): void { 55 | this.editor.setValue(this.defaultContent[this.language]); 56 | this.editor.getSession().setMode("ace/mode/" + this.language.toLowerCase()); 57 | } 58 | 59 | setLanguage(language: string): void { 60 | this.language = language; 61 | this.resetEditor(); 62 | } 63 | 64 | submit(): void { 65 | let user_code = this.editor.getValue(); 66 | console.log(user_code); 67 | 68 | const data = { 69 | code: user_code, 70 | lang: this.language.toLocaleLowerCase() 71 | }; 72 | 73 | this.dataService.buildAndRun(data) 74 | .then(res => this.output = res); 75 | } 76 | 77 | initEditor(): void { 78 | // editor basic setting 79 | this.editor = ace.edit("editor"); 80 | this.editor.setTheme("ace/theme/eclipse"); 81 | this.resetEditor(); 82 | 83 | // initialize collaborationService 84 | this.subscriptionUsers = this.collaboration.init(this.editor, this.sessionId) 85 | .subscribe(users => this.users = users); 86 | this.editor.lastAppliedChange = null; 87 | 88 | // register change callback 89 | this.editor.on("change", e => { 90 | console.log('editor changes: ' + JSON.stringify(e)); 91 | // if the change is the same as the last one, then skip 92 | if(this.editor.lastAppliedChange != e){ 93 | this.collaboration.change(JSON.stringify(e)); 94 | } 95 | }); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /executor/executor_utils.py: -------------------------------------------------------------------------------- 1 | import docker 2 | import os, sys 3 | import shutil 4 | import uuid 5 | 6 | from docker.errors import APIError 7 | from docker.errors import ContainerError 8 | from docker.errors import ImageNotFound 9 | 10 | # get current directory 11 | CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) 12 | IMAGE_NAME = 'qichen90/cs503_1801' 13 | 14 | client = docker.from_env() 15 | 16 | #store the code in tmp folder 17 | TEMP_BUILD_DIR = "%s/tmp" % CURRENT_DIR 18 | CONTAINER_NAME = "%s:latest" % IMAGE_NAME 19 | 20 | SOURCE_FILE_NAMES = { 21 | "java": "Solution.java", 22 | "python": "solution.py", 23 | "c++": "solution.cpp" 24 | } 25 | 26 | BINARY_NAMES = { 27 | "java": "Solution", 28 | "python": "solution.py", 29 | "c++": "./a.out" 30 | } 31 | 32 | BUILD_COMMANDS = { 33 | "java": "javac", 34 | "python": "python3", 35 | "c++": "g++" 36 | } 37 | 38 | EXECUTE_COMMANDS = { 39 | "java": "java", 40 | "python": "python3", 41 | "c++": "" 42 | } 43 | 44 | # load docker image 45 | def load_image(): 46 | try: 47 | client.images.get(IMAGE_NAME) 48 | print("Docker image exists locally...") 49 | except ImageNotFound: 50 | # load from hub 51 | print("Loading image from docker hub....") 52 | client.image.pull(IMAGE_NAME) 53 | except APIError: 54 | # fail to connect to docker 55 | print("Cannot connect to docker") 56 | return 57 | 58 | def make_dir(dir): 59 | try: 60 | os.makedirs(dir) 61 | except OSError: 62 | print("cannot create directory") 63 | 64 | def build_and_run(code, lang): 65 | result = {'build': None, 'run': None, 'error': None} 66 | # use the uuid to create unique file name 67 | source_file_parent_dir_name = uuid.uuid4() 68 | source_file_host_dir = "%s/%s" % (TEMP_BUILD_DIR, source_file_parent_dir_name) 69 | source_file_guest_dir = "/test/%s" % (source_file_parent_dir_name) 70 | make_dir(source_file_host_dir) 71 | 72 | # write code into source file 73 | with open("%s/%s" % (source_file_host_dir, SOURCE_FILE_NAMES[lang]), 'w') as source_file: 74 | source_file.write(code) 75 | 76 | # build code 77 | try: 78 | client.containers.run( 79 | image=IMAGE_NAME, 80 | command="%s %s" % (BUILD_COMMANDS[lang], SOURCE_FILE_NAMES[lang]), 81 | volumes={source_file_host_dir:{'bind': source_file_guest_dir, 'mode': 'rw'}}, 82 | working_dir=source_file_guest_dir 83 | ) 84 | print("source built") 85 | result['build'] = 'OK' 86 | except ContainerError as e: 87 | print("error") 88 | result['build'] = str(e.stderr, 'utf-8') 89 | # remove host dir 90 | shutil.rmtree(source_file_host_dir) 91 | return result 92 | 93 | # run code 94 | try: 95 | log = client.containers.run( 96 | image=IMAGE_NAME, 97 | command="%s %s" % (EXECUTE_COMMANDS[lang], BINARY_NAMES[lang]), 98 | volumes={source_file_host_dir:{'bind': source_file_guest_dir, 'mode': 'rw'}}, 99 | working_dir=source_file_guest_dir 100 | ) 101 | 102 | log = str(log, 'utf-8') 103 | result['run'] = log 104 | print("code run") 105 | except ContainerError as e: 106 | result['run'] = str(e.stderr, 'utf-8') 107 | shutil.rmtree(source_file_host_dir) 108 | return result 109 | 110 | shutil.rmtree(source_file_host_dir) 111 | return result -------------------------------------------------------------------------------- /oj-client/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs", 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": [ 26 | true, 27 | "spaces" 28 | ], 29 | "interface-over-type-literal": true, 30 | "label-position": true, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-access": false, 36 | "member-ordering": [ 37 | true, 38 | { 39 | "order": [ 40 | "static-field", 41 | "instance-field", 42 | "static-method", 43 | "instance-method" 44 | ] 45 | } 46 | ], 47 | "no-arg": true, 48 | "no-bitwise": true, 49 | "no-console": [ 50 | true, 51 | "debug", 52 | "info", 53 | "time", 54 | "timeEnd", 55 | "trace" 56 | ], 57 | "no-construct": true, 58 | "no-debugger": true, 59 | "no-duplicate-super": true, 60 | "no-empty": false, 61 | "no-empty-interface": true, 62 | "no-eval": true, 63 | "no-inferrable-types": [ 64 | true, 65 | "ignore-params" 66 | ], 67 | "no-misused-new": true, 68 | "no-non-null-assertion": true, 69 | "no-shadowed-variable": true, 70 | "no-string-literal": false, 71 | "no-string-throw": true, 72 | "no-switch-case-fall-through": true, 73 | "no-trailing-whitespace": true, 74 | "no-unnecessary-initializer": true, 75 | "no-unused-expression": true, 76 | "no-use-before-declare": true, 77 | "no-var-keyword": true, 78 | "object-literal-sort-keys": false, 79 | "one-line": [ 80 | true, 81 | "check-open-brace", 82 | "check-catch", 83 | "check-else", 84 | "check-whitespace" 85 | ], 86 | "prefer-const": true, 87 | "quotemark": [ 88 | true, 89 | "single" 90 | ], 91 | "radix": true, 92 | "semicolon": [ 93 | true, 94 | "always" 95 | ], 96 | "triple-equals": [ 97 | true, 98 | "allow-null-check" 99 | ], 100 | "typedef-whitespace": [ 101 | true, 102 | { 103 | "call-signature": "nospace", 104 | "index-signature": "nospace", 105 | "parameter": "nospace", 106 | "property-declaration": "nospace", 107 | "variable-declaration": "nospace" 108 | } 109 | ], 110 | "unified-signatures": true, 111 | "variable-name": false, 112 | "whitespace": [ 113 | true, 114 | "check-branch", 115 | "check-decl", 116 | "check-operator", 117 | "check-separator", 118 | "check-type" 119 | ], 120 | "directive-selector": [ 121 | true, 122 | "attribute", 123 | "app", 124 | "camelCase" 125 | ], 126 | "component-selector": [ 127 | true, 128 | "element", 129 | "app", 130 | "kebab-case" 131 | ], 132 | "no-output-on-prefix": true, 133 | "use-input-property-decorator": true, 134 | "use-output-property-decorator": true, 135 | "use-host-property-decorator": true, 136 | "no-input-rename": true, 137 | "no-output-rename": true, 138 | "use-life-cycle-interface": true, 139 | "use-pipe-transform-interface": true, 140 | "component-class-suffix": true, 141 | "directive-class-suffix": true 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /public/inline.bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack/bootstrap 02c288825ed0b877ec73"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAY,2BAA2B;AACvC;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,kDAA0C,WAAW,EAAE;AACvD;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAI;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA,kDAA0C,oBAAoB,WAAW","file":"inline.bundle.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t\"inline\": 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tvar installedChunkData = installedChunks[chunkId];\n \t\tif(installedChunkData === 0) {\n \t\t\treturn new Promise(function(resolve) { resolve(); });\n \t\t}\n\n \t\t// a Promise means \"currently loading\".\n \t\tif(installedChunkData) {\n \t\t\treturn installedChunkData[2];\n \t\t}\n\n \t\t// setup Promise in chunk cache\n \t\tvar promise = new Promise(function(resolve, reject) {\n \t\t\tinstalledChunkData = installedChunks[chunkId] = [resolve, reject];\n \t\t});\n \t\tinstalledChunkData[2] = promise;\n\n \t\t// start chunk loading\n \t\tvar head = document.getElementsByTagName('head')[0];\n \t\tvar script = document.createElement('script');\n \t\tscript.type = 'text/javascript';\n \t\tscript.charset = 'utf-8';\n \t\tscript.async = true;\n \t\tscript.timeout = 120000;\n\n \t\tif (__webpack_require__.nc) {\n \t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n \t\t}\n \t\tscript.src = __webpack_require__.p + \"\" + chunkId + \".chunk.js\";\n \t\tvar timeout = setTimeout(onScriptComplete, 120000);\n \t\tscript.onerror = script.onload = onScriptComplete;\n \t\tfunction onScriptComplete() {\n \t\t\t// avoid mem leaks in IE.\n \t\t\tscript.onerror = script.onload = null;\n \t\t\tclearTimeout(timeout);\n \t\t\tvar chunk = installedChunks[chunkId];\n \t\t\tif(chunk !== 0) {\n \t\t\t\tif(chunk) {\n \t\t\t\t\tchunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));\n \t\t\t\t}\n \t\t\t\tinstalledChunks[chunkId] = undefined;\n \t\t\t}\n \t\t};\n \t\thead.appendChild(script);\n\n \t\treturn promise;\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 02c288825ed0b877ec73"],"sourceRoot":"webpack:///"} -------------------------------------------------------------------------------- /oj-server/services/editorSocketService.js: -------------------------------------------------------------------------------- 1 | var redisClient = require('../module/redisClient'); 2 | const TIMEOUT_IN_SECONDS = 3600; 3 | 4 | module.exports = function(io) { 5 | //collaboration sessions 6 | //record all the participants in each session so that server can send changes to all cparticipants in a session 7 | var collaborations = {}; 8 | 9 | // map from socketId to sessionId 10 | var socketId2SessionId = {}; 11 | 12 | // each application has their own session 13 | var sessionPath = '/temp_session'; 14 | 15 | // wait for the connection 16 | io.on('connection', socket => { 17 | let sessionId = socket.handshake.query['sessionId']; 18 | socketId2SessionId[socket.id] = sessionId; 19 | 20 | if(sessionId in collaborations){ 21 | collaborations[sessionId]['participants'].push(socket.id); 22 | 23 | let participants = collaborations[sessionId]['participants']; 24 | for(let i = 0; i < participants.length; i++){ 25 | io.to(participants[i]).emit('userchange', participants); 26 | } 27 | }else{ 28 | // not in memory then check in redis 29 | redisClient.get(sessionPath + '/' + sessionId, function(data) { 30 | if(data){ 31 | console.log("get session data back from redis"); 32 | collaborations[sessionId] = { 33 | 'cachedInstructions': JSON.parse(data), 34 | 'participants': [] 35 | } 36 | }else{ 37 | console.log("create new session"); 38 | collaborations[sessionId] = { 39 | 'cachedInstructions': [], 40 | 'participants': [] 41 | }; 42 | } 43 | collaborations[sessionId]['participants'].push(socket.id); 44 | io.to(socket.id).emit('userchange', socket.id); 45 | }); 46 | } 47 | 48 | // collaborations[sessionId]['participants'].push(socket.id); 49 | 50 | // socket event listeners 51 | // delta is the change info 52 | // it records the row and cloumn of the changes 53 | socket.on('change', delta => { 54 | // for debugging 55 | console.log("change " + socketId2SessionId[socket.id] + " " + delta); 56 | 57 | // get session id based on socket.id 58 | let sessionId = socketId2SessionId[socket.id]; 59 | if(sessionId in collaborations){ 60 | collaborations[sessionId]['cachedInstructions'].push(['change', delta, Date.now()]); 61 | let participants = collaborations[sessionId]['participants']; 62 | // send changes to all participants 63 | for(let i = 0; i < participants.length; i++){ 64 | // skip the one who created this change 65 | if(socket.id != participants[i]){ 66 | io.to(participants[i]).emit('change', delta); 67 | } 68 | } 69 | }else{ 70 | console.log("cound not tie socket id to any collaboration"); 71 | } 72 | }); 73 | 74 | // show all stored data 75 | socket.on('restoreBuffer', () => { 76 | let sessionId = socketId2SessionId[socket.id]; 77 | console.log('restore buffer for session ' + sessionId + ', socket id: ' + socket.id); 78 | 79 | if(sessionId in collaborations){ 80 | let instructions = collaborations[sessionId]['cachedInstructions']; 81 | for(let i = 0; i < instructions.length; i++){ 82 | socket.emit(instructions[i][0], instructions[i][1]); // change + delta 83 | } 84 | }else{ 85 | console.log('could not find any collcation for this session'); 86 | } 87 | }); 88 | 89 | socket.on('disconnect', function(){ 90 | let sessionId = socketId2SessionId[socket.id]; 91 | console.log('disconnect session ' + sessionId + ', socket id: ' + socket.id); 92 | 93 | let foundAndRemoved = false; 94 | 95 | if(sessionId in collaborations){ 96 | let participants = collaborations[sessionId]['participants']; 97 | let index = participants.indexOf(socket.id); 98 | 99 | if(index >= 0){ 100 | participants.splice(index, 1); 101 | foundAndRemoved = true; 102 | 103 | if(participants.length == 0){ 104 | console.log('last participant left, committing to redis and remove from memory'); 105 | let key = sessionPath + '/' + sessionId; 106 | let value = JSON.stringify(collaborations[sessionId]['cachedInstructions']); 107 | 108 | redisClient.set(key, value, redisClient.redisPrint); 109 | redisClient.expire(key, TIMEOUT_IN_SECONDS); 110 | delete collaborations[sessionId]; 111 | } 112 | } 113 | // emit the new user list 114 | for(let i = 0; i < participants.length; i++){ 115 | io.to(participants[i]).emit('userchange', participants); 116 | } 117 | } 118 | 119 | if(!foundAndRemoved){ 120 | console.log('Could not find the socket.id in collaboration'); 121 | } 122 | }); 123 | 124 | // reply to socket.id, emit 'message' event so that client side can get the message 125 | // io.to(socket.id).emit('message', 'here from server'); 126 | }); 127 | } -------------------------------------------------------------------------------- /public/inline.bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // install a JSONP callback for chunk loading 3 | /******/ var parentJsonpFunction = window["webpackJsonp"]; 4 | /******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) { 5 | /******/ // add "moreModules" to the modules object, 6 | /******/ // then flag all "chunkIds" as loaded and fire callback 7 | /******/ var moduleId, chunkId, i = 0, resolves = [], result; 8 | /******/ for(;i < chunkIds.length; i++) { 9 | /******/ chunkId = chunkIds[i]; 10 | /******/ if(installedChunks[chunkId]) { 11 | /******/ resolves.push(installedChunks[chunkId][0]); 12 | /******/ } 13 | /******/ installedChunks[chunkId] = 0; 14 | /******/ } 15 | /******/ for(moduleId in moreModules) { 16 | /******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { 17 | /******/ modules[moduleId] = moreModules[moduleId]; 18 | /******/ } 19 | /******/ } 20 | /******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules); 21 | /******/ while(resolves.length) { 22 | /******/ resolves.shift()(); 23 | /******/ } 24 | /******/ if(executeModules) { 25 | /******/ for(i=0; i < executeModules.length; i++) { 26 | /******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]); 27 | /******/ } 28 | /******/ } 29 | /******/ return result; 30 | /******/ }; 31 | /******/ 32 | /******/ // The module cache 33 | /******/ var installedModules = {}; 34 | /******/ 35 | /******/ // objects to store loaded and loading chunks 36 | /******/ var installedChunks = { 37 | /******/ "inline": 0 38 | /******/ }; 39 | /******/ 40 | /******/ // The require function 41 | /******/ function __webpack_require__(moduleId) { 42 | /******/ 43 | /******/ // Check if module is in cache 44 | /******/ if(installedModules[moduleId]) { 45 | /******/ return installedModules[moduleId].exports; 46 | /******/ } 47 | /******/ // Create a new module (and put it into the cache) 48 | /******/ var module = installedModules[moduleId] = { 49 | /******/ i: moduleId, 50 | /******/ l: false, 51 | /******/ exports: {} 52 | /******/ }; 53 | /******/ 54 | /******/ // Execute the module function 55 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 56 | /******/ 57 | /******/ // Flag the module as loaded 58 | /******/ module.l = true; 59 | /******/ 60 | /******/ // Return the exports of the module 61 | /******/ return module.exports; 62 | /******/ } 63 | /******/ 64 | /******/ // This file contains only the entry chunk. 65 | /******/ // The chunk loading function for additional chunks 66 | /******/ __webpack_require__.e = function requireEnsure(chunkId) { 67 | /******/ var installedChunkData = installedChunks[chunkId]; 68 | /******/ if(installedChunkData === 0) { 69 | /******/ return new Promise(function(resolve) { resolve(); }); 70 | /******/ } 71 | /******/ 72 | /******/ // a Promise means "currently loading". 73 | /******/ if(installedChunkData) { 74 | /******/ return installedChunkData[2]; 75 | /******/ } 76 | /******/ 77 | /******/ // setup Promise in chunk cache 78 | /******/ var promise = new Promise(function(resolve, reject) { 79 | /******/ installedChunkData = installedChunks[chunkId] = [resolve, reject]; 80 | /******/ }); 81 | /******/ installedChunkData[2] = promise; 82 | /******/ 83 | /******/ // start chunk loading 84 | /******/ var head = document.getElementsByTagName('head')[0]; 85 | /******/ var script = document.createElement('script'); 86 | /******/ script.type = 'text/javascript'; 87 | /******/ script.charset = 'utf-8'; 88 | /******/ script.async = true; 89 | /******/ script.timeout = 120000; 90 | /******/ 91 | /******/ if (__webpack_require__.nc) { 92 | /******/ script.setAttribute("nonce", __webpack_require__.nc); 93 | /******/ } 94 | /******/ script.src = __webpack_require__.p + "" + chunkId + ".chunk.js"; 95 | /******/ var timeout = setTimeout(onScriptComplete, 120000); 96 | /******/ script.onerror = script.onload = onScriptComplete; 97 | /******/ function onScriptComplete() { 98 | /******/ // avoid mem leaks in IE. 99 | /******/ script.onerror = script.onload = null; 100 | /******/ clearTimeout(timeout); 101 | /******/ var chunk = installedChunks[chunkId]; 102 | /******/ if(chunk !== 0) { 103 | /******/ if(chunk) { 104 | /******/ chunk[1](new Error('Loading chunk ' + chunkId + ' failed.')); 105 | /******/ } 106 | /******/ installedChunks[chunkId] = undefined; 107 | /******/ } 108 | /******/ }; 109 | /******/ head.appendChild(script); 110 | /******/ 111 | /******/ return promise; 112 | /******/ }; 113 | /******/ 114 | /******/ // expose the modules object (__webpack_modules__) 115 | /******/ __webpack_require__.m = modules; 116 | /******/ 117 | /******/ // expose the module cache 118 | /******/ __webpack_require__.c = installedModules; 119 | /******/ 120 | /******/ // define getter function for harmony exports 121 | /******/ __webpack_require__.d = function(exports, name, getter) { 122 | /******/ if(!__webpack_require__.o(exports, name)) { 123 | /******/ Object.defineProperty(exports, name, { 124 | /******/ configurable: false, 125 | /******/ enumerable: true, 126 | /******/ get: getter 127 | /******/ }); 128 | /******/ } 129 | /******/ }; 130 | /******/ 131 | /******/ // getDefaultExport function for compatibility with non-harmony modules 132 | /******/ __webpack_require__.n = function(module) { 133 | /******/ var getter = module && module.__esModule ? 134 | /******/ function getDefault() { return module['default']; } : 135 | /******/ function getModuleExports() { return module; }; 136 | /******/ __webpack_require__.d(getter, 'a', getter); 137 | /******/ return getter; 138 | /******/ }; 139 | /******/ 140 | /******/ // Object.prototype.hasOwnProperty.call 141 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 142 | /******/ 143 | /******/ // __webpack_public_path__ 144 | /******/ __webpack_require__.p = ""; 145 | /******/ 146 | /******/ // on error function for async loading 147 | /******/ __webpack_require__.oe = function(err) { console.error(err); throw err; }; 148 | /******/ }) 149 | /************************************************************************/ 150 | /******/ ([]); 151 | //# sourceMappingURL=inline.bundle.js.map -------------------------------------------------------------------------------- /oj-server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oj-server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.4", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", 10 | "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", 11 | "requires": { 12 | "mime-types": "2.1.17", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "after": { 17 | "version": "0.8.2", 18 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 19 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 20 | }, 21 | "array-flatten": { 22 | "version": "1.1.1", 23 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 24 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 25 | }, 26 | "arraybuffer.slice": { 27 | "version": "0.0.7", 28 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 29 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 30 | }, 31 | "async": { 32 | "version": "2.1.4", 33 | "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", 34 | "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", 35 | "requires": { 36 | "lodash": "4.17.5" 37 | } 38 | }, 39 | "async-limiter": { 40 | "version": "1.0.0", 41 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", 42 | "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" 43 | }, 44 | "backo2": { 45 | "version": "1.0.2", 46 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 47 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 48 | }, 49 | "base64-arraybuffer": { 50 | "version": "0.1.5", 51 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", 52 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" 53 | }, 54 | "base64id": { 55 | "version": "1.0.0", 56 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", 57 | "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" 58 | }, 59 | "better-assert": { 60 | "version": "1.0.2", 61 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", 62 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", 63 | "requires": { 64 | "callsite": "1.0.0" 65 | } 66 | }, 67 | "blob": { 68 | "version": "0.0.4", 69 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", 70 | "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" 71 | }, 72 | "bluebird": { 73 | "version": "3.5.0", 74 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", 75 | "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" 76 | }, 77 | "body-parser": { 78 | "version": "1.18.2", 79 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 80 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 81 | "requires": { 82 | "bytes": "3.0.0", 83 | "content-type": "1.0.4", 84 | "debug": "2.6.9", 85 | "depd": "1.1.2", 86 | "http-errors": "1.6.2", 87 | "iconv-lite": "0.4.19", 88 | "on-finished": "2.3.0", 89 | "qs": "6.5.1", 90 | "raw-body": "2.3.2", 91 | "type-is": "1.6.15" 92 | } 93 | }, 94 | "bson": { 95 | "version": "1.0.4", 96 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", 97 | "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" 98 | }, 99 | "bytes": { 100 | "version": "3.0.0", 101 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 102 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 103 | }, 104 | "callsite": { 105 | "version": "1.0.0", 106 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 107 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" 108 | }, 109 | "component-bind": { 110 | "version": "1.0.0", 111 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 112 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 113 | }, 114 | "component-emitter": { 115 | "version": "1.2.1", 116 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 117 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 118 | }, 119 | "component-inherit": { 120 | "version": "0.0.3", 121 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 122 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 123 | }, 124 | "content-disposition": { 125 | "version": "0.5.2", 126 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 127 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 128 | }, 129 | "content-type": { 130 | "version": "1.0.4", 131 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 132 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 133 | }, 134 | "cookie": { 135 | "version": "0.3.1", 136 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 137 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 138 | }, 139 | "cookie-signature": { 140 | "version": "1.0.6", 141 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 142 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 143 | }, 144 | "debug": { 145 | "version": "2.6.9", 146 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 147 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 148 | "requires": { 149 | "ms": "2.0.0" 150 | } 151 | }, 152 | "depd": { 153 | "version": "1.1.2", 154 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 155 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 156 | }, 157 | "destroy": { 158 | "version": "1.0.4", 159 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 160 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 161 | }, 162 | "double-ended-queue": { 163 | "version": "2.1.0-0", 164 | "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", 165 | "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" 166 | }, 167 | "ee-first": { 168 | "version": "1.1.1", 169 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 170 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 171 | }, 172 | "encodeurl": { 173 | "version": "1.0.2", 174 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 175 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 176 | }, 177 | "engine.io": { 178 | "version": "3.1.4", 179 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.4.tgz", 180 | "integrity": "sha1-PQIRtwpVLOhB/8fahiezAamkFi4=", 181 | "requires": { 182 | "accepts": "1.3.3", 183 | "base64id": "1.0.0", 184 | "cookie": "0.3.1", 185 | "debug": "2.6.9", 186 | "engine.io-parser": "2.1.2", 187 | "uws": "0.14.5", 188 | "ws": "3.3.3" 189 | }, 190 | "dependencies": { 191 | "accepts": { 192 | "version": "1.3.3", 193 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", 194 | "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", 195 | "requires": { 196 | "mime-types": "2.1.17", 197 | "negotiator": "0.6.1" 198 | } 199 | } 200 | } 201 | }, 202 | "engine.io-client": { 203 | "version": "3.1.4", 204 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.4.tgz", 205 | "integrity": "sha1-T88TcLRxY70s6b4nM5ckMDUNTqE=", 206 | "requires": { 207 | "component-emitter": "1.2.1", 208 | "component-inherit": "0.0.3", 209 | "debug": "2.6.9", 210 | "engine.io-parser": "2.1.2", 211 | "has-cors": "1.1.0", 212 | "indexof": "0.0.1", 213 | "parseqs": "0.0.5", 214 | "parseuri": "0.0.5", 215 | "ws": "3.3.3", 216 | "xmlhttprequest-ssl": "1.5.5", 217 | "yeast": "0.1.2" 218 | } 219 | }, 220 | "engine.io-parser": { 221 | "version": "2.1.2", 222 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", 223 | "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", 224 | "requires": { 225 | "after": "0.8.2", 226 | "arraybuffer.slice": "0.0.7", 227 | "base64-arraybuffer": "0.1.5", 228 | "blob": "0.0.4", 229 | "has-binary2": "1.0.2" 230 | } 231 | }, 232 | "escape-html": { 233 | "version": "1.0.3", 234 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 235 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 236 | }, 237 | "etag": { 238 | "version": "1.8.1", 239 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 240 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 241 | }, 242 | "express": { 243 | "version": "4.16.2", 244 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", 245 | "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", 246 | "requires": { 247 | "accepts": "1.3.4", 248 | "array-flatten": "1.1.1", 249 | "body-parser": "1.18.2", 250 | "content-disposition": "0.5.2", 251 | "content-type": "1.0.4", 252 | "cookie": "0.3.1", 253 | "cookie-signature": "1.0.6", 254 | "debug": "2.6.9", 255 | "depd": "1.1.2", 256 | "encodeurl": "1.0.2", 257 | "escape-html": "1.0.3", 258 | "etag": "1.8.1", 259 | "finalhandler": "1.1.0", 260 | "fresh": "0.5.2", 261 | "merge-descriptors": "1.0.1", 262 | "methods": "1.1.2", 263 | "on-finished": "2.3.0", 264 | "parseurl": "1.3.2", 265 | "path-to-regexp": "0.1.7", 266 | "proxy-addr": "2.0.2", 267 | "qs": "6.5.1", 268 | "range-parser": "1.2.0", 269 | "safe-buffer": "5.1.1", 270 | "send": "0.16.1", 271 | "serve-static": "1.13.1", 272 | "setprototypeof": "1.1.0", 273 | "statuses": "1.3.1", 274 | "type-is": "1.6.15", 275 | "utils-merge": "1.0.1", 276 | "vary": "1.1.2" 277 | } 278 | }, 279 | "finalhandler": { 280 | "version": "1.1.0", 281 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", 282 | "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", 283 | "requires": { 284 | "debug": "2.6.9", 285 | "encodeurl": "1.0.2", 286 | "escape-html": "1.0.3", 287 | "on-finished": "2.3.0", 288 | "parseurl": "1.3.2", 289 | "statuses": "1.3.1", 290 | "unpipe": "1.0.0" 291 | } 292 | }, 293 | "follow-redirects": { 294 | "version": "1.4.1", 295 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", 296 | "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", 297 | "requires": { 298 | "debug": "3.1.0" 299 | }, 300 | "dependencies": { 301 | "debug": { 302 | "version": "3.1.0", 303 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 304 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 305 | "requires": { 306 | "ms": "2.0.0" 307 | } 308 | } 309 | } 310 | }, 311 | "forwarded": { 312 | "version": "0.1.2", 313 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 314 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 315 | }, 316 | "fresh": { 317 | "version": "0.5.2", 318 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 319 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 320 | }, 321 | "has-binary2": { 322 | "version": "1.0.2", 323 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", 324 | "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", 325 | "requires": { 326 | "isarray": "2.0.1" 327 | } 328 | }, 329 | "has-cors": { 330 | "version": "1.1.0", 331 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 332 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 333 | }, 334 | "http-errors": { 335 | "version": "1.6.2", 336 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 337 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 338 | "requires": { 339 | "depd": "1.1.1", 340 | "inherits": "2.0.3", 341 | "setprototypeof": "1.0.3", 342 | "statuses": "1.3.1" 343 | }, 344 | "dependencies": { 345 | "depd": { 346 | "version": "1.1.1", 347 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 348 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 349 | }, 350 | "setprototypeof": { 351 | "version": "1.0.3", 352 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 353 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 354 | } 355 | } 356 | }, 357 | "iconv-lite": { 358 | "version": "0.4.19", 359 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 360 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 361 | }, 362 | "indexof": { 363 | "version": "0.0.1", 364 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 365 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 366 | }, 367 | "inherits": { 368 | "version": "2.0.3", 369 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 370 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 371 | }, 372 | "ipaddr.js": { 373 | "version": "1.5.2", 374 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", 375 | "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" 376 | }, 377 | "isarray": { 378 | "version": "2.0.1", 379 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 380 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 381 | }, 382 | "kareem": { 383 | "version": "2.0.3", 384 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.0.3.tgz", 385 | "integrity": "sha512-WloXk3nyByx9FEB5WY7WFEXIZB/QA+zy7c2kJMjnZCebjepEyQcJzazgLiKcTS/ltZeEoeEQ1A1pau1fEDlnIA==" 386 | }, 387 | "lodash": { 388 | "version": "4.17.5", 389 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", 390 | "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" 391 | }, 392 | "lodash.get": { 393 | "version": "4.4.2", 394 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 395 | "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" 396 | }, 397 | "media-typer": { 398 | "version": "0.3.0", 399 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 400 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 401 | }, 402 | "merge-descriptors": { 403 | "version": "1.0.1", 404 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 405 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 406 | }, 407 | "methods": { 408 | "version": "1.1.2", 409 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 410 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 411 | }, 412 | "mime": { 413 | "version": "1.4.1", 414 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 415 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 416 | }, 417 | "mime-db": { 418 | "version": "1.30.0", 419 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 420 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 421 | }, 422 | "mime-types": { 423 | "version": "2.1.17", 424 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 425 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 426 | "requires": { 427 | "mime-db": "1.30.0" 428 | } 429 | }, 430 | "mongodb": { 431 | "version": "3.0.2", 432 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.0.2.tgz", 433 | "integrity": "sha512-E50FmpSQchZAimn2uPIegoNoH9UQYR1yiGHtQPmmg8/Ekc97w6owHoqaBoz+assnd9V5LxMzmQ/VEWMsQMgZhQ==", 434 | "requires": { 435 | "mongodb-core": "3.0.2" 436 | } 437 | }, 438 | "mongodb-core": { 439 | "version": "3.0.2", 440 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.0.2.tgz", 441 | "integrity": "sha512-p1B0qwFQUw6C1OlFJnrOJp8KaX7MuGoogRbTaupRt0y+pPRkMllHWtE9V6i1CDtTvI3/3sy2sQwqWez7zuXEAA==", 442 | "requires": { 443 | "bson": "1.0.4", 444 | "require_optional": "1.0.1" 445 | } 446 | }, 447 | "mongoose": { 448 | "version": "5.0.3", 449 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.0.3.tgz", 450 | "integrity": "sha512-y4NlLzZaQe5vJHjcEjHLKK6utjs7sVEPN971+d1vVJJGrmA+zeeFA1MEmC1J0ujD34eOSghnExXJPwCrxHHZCw==", 451 | "requires": { 452 | "async": "2.1.4", 453 | "bson": "1.0.4", 454 | "kareem": "2.0.3", 455 | "lodash.get": "4.4.2", 456 | "mongodb": "3.0.2", 457 | "mongoose-legacy-pluralize": "1.0.2", 458 | "mpath": "0.3.0", 459 | "mquery": "3.0.0", 460 | "ms": "2.0.0", 461 | "regexp-clone": "0.0.1", 462 | "sliced": "1.0.1" 463 | } 464 | }, 465 | "mongoose-legacy-pluralize": { 466 | "version": "1.0.2", 467 | "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", 468 | "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" 469 | }, 470 | "mpath": { 471 | "version": "0.3.0", 472 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", 473 | "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" 474 | }, 475 | "mquery": { 476 | "version": "3.0.0", 477 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.0.0.tgz", 478 | "integrity": "sha512-WL1Lk8v4l8VFSSwN3yCzY9TXw+fKVYKn6f+w86TRzOLSE8k1yTgGaLBPUByJQi8VcLbOdnUneFV/y3Kv874pnQ==", 479 | "requires": { 480 | "bluebird": "3.5.0", 481 | "debug": "2.6.9", 482 | "regexp-clone": "0.0.1", 483 | "sliced": "0.0.5" 484 | }, 485 | "dependencies": { 486 | "sliced": { 487 | "version": "0.0.5", 488 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", 489 | "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" 490 | } 491 | } 492 | }, 493 | "ms": { 494 | "version": "2.0.0", 495 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 496 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 497 | }, 498 | "negotiator": { 499 | "version": "0.6.1", 500 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 501 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 502 | }, 503 | "node-rest-client": { 504 | "version": "3.1.0", 505 | "resolved": "https://registry.npmjs.org/node-rest-client/-/node-rest-client-3.1.0.tgz", 506 | "integrity": "sha1-4L623aeyDMC2enhHzxLF/EGcN8M=", 507 | "requires": { 508 | "debug": "2.2.0", 509 | "follow-redirects": "1.4.1", 510 | "xml2js": "0.4.19" 511 | }, 512 | "dependencies": { 513 | "debug": { 514 | "version": "2.2.0", 515 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 516 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 517 | "requires": { 518 | "ms": "0.7.1" 519 | } 520 | }, 521 | "ms": { 522 | "version": "0.7.1", 523 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 524 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" 525 | } 526 | } 527 | }, 528 | "object-component": { 529 | "version": "0.0.3", 530 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 531 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" 532 | }, 533 | "on-finished": { 534 | "version": "2.3.0", 535 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 536 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 537 | "requires": { 538 | "ee-first": "1.1.1" 539 | } 540 | }, 541 | "parseqs": { 542 | "version": "0.0.5", 543 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 544 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 545 | "requires": { 546 | "better-assert": "1.0.2" 547 | } 548 | }, 549 | "parseuri": { 550 | "version": "0.0.5", 551 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 552 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 553 | "requires": { 554 | "better-assert": "1.0.2" 555 | } 556 | }, 557 | "parseurl": { 558 | "version": "1.3.2", 559 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 560 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 561 | }, 562 | "path-to-regexp": { 563 | "version": "0.1.7", 564 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 565 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 566 | }, 567 | "proxy-addr": { 568 | "version": "2.0.2", 569 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", 570 | "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", 571 | "requires": { 572 | "forwarded": "0.1.2", 573 | "ipaddr.js": "1.5.2" 574 | } 575 | }, 576 | "qs": { 577 | "version": "6.5.1", 578 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 579 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" 580 | }, 581 | "range-parser": { 582 | "version": "1.2.0", 583 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 584 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 585 | }, 586 | "raw-body": { 587 | "version": "2.3.2", 588 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 589 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 590 | "requires": { 591 | "bytes": "3.0.0", 592 | "http-errors": "1.6.2", 593 | "iconv-lite": "0.4.19", 594 | "unpipe": "1.0.0" 595 | } 596 | }, 597 | "redis": { 598 | "version": "2.8.0", 599 | "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", 600 | "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", 601 | "requires": { 602 | "double-ended-queue": "2.1.0-0", 603 | "redis-commands": "1.3.1", 604 | "redis-parser": "2.6.0" 605 | } 606 | }, 607 | "redis-commands": { 608 | "version": "1.3.1", 609 | "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz", 610 | "integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs=" 611 | }, 612 | "redis-parser": { 613 | "version": "2.6.0", 614 | "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", 615 | "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" 616 | }, 617 | "regexp-clone": { 618 | "version": "0.0.1", 619 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", 620 | "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" 621 | }, 622 | "require_optional": { 623 | "version": "1.0.1", 624 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 625 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 626 | "requires": { 627 | "resolve-from": "2.0.0", 628 | "semver": "5.5.0" 629 | } 630 | }, 631 | "resolve-from": { 632 | "version": "2.0.0", 633 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 634 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 635 | }, 636 | "safe-buffer": { 637 | "version": "5.1.1", 638 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 639 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 640 | }, 641 | "sax": { 642 | "version": "1.2.4", 643 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 644 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 645 | }, 646 | "semver": { 647 | "version": "5.5.0", 648 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", 649 | "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" 650 | }, 651 | "send": { 652 | "version": "0.16.1", 653 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", 654 | "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", 655 | "requires": { 656 | "debug": "2.6.9", 657 | "depd": "1.1.2", 658 | "destroy": "1.0.4", 659 | "encodeurl": "1.0.2", 660 | "escape-html": "1.0.3", 661 | "etag": "1.8.1", 662 | "fresh": "0.5.2", 663 | "http-errors": "1.6.2", 664 | "mime": "1.4.1", 665 | "ms": "2.0.0", 666 | "on-finished": "2.3.0", 667 | "range-parser": "1.2.0", 668 | "statuses": "1.3.1" 669 | } 670 | }, 671 | "serve-static": { 672 | "version": "1.13.1", 673 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", 674 | "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", 675 | "requires": { 676 | "encodeurl": "1.0.2", 677 | "escape-html": "1.0.3", 678 | "parseurl": "1.3.2", 679 | "send": "0.16.1" 680 | } 681 | }, 682 | "setprototypeof": { 683 | "version": "1.1.0", 684 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 685 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 686 | }, 687 | "sliced": { 688 | "version": "1.0.1", 689 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 690 | "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" 691 | }, 692 | "socket.io": { 693 | "version": "2.0.4", 694 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", 695 | "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", 696 | "requires": { 697 | "debug": "2.6.9", 698 | "engine.io": "3.1.4", 699 | "socket.io-adapter": "1.1.1", 700 | "socket.io-client": "2.0.4", 701 | "socket.io-parser": "3.1.2" 702 | } 703 | }, 704 | "socket.io-adapter": { 705 | "version": "1.1.1", 706 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", 707 | "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" 708 | }, 709 | "socket.io-client": { 710 | "version": "2.0.4", 711 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", 712 | "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", 713 | "requires": { 714 | "backo2": "1.0.2", 715 | "base64-arraybuffer": "0.1.5", 716 | "component-bind": "1.0.0", 717 | "component-emitter": "1.2.1", 718 | "debug": "2.6.9", 719 | "engine.io-client": "3.1.4", 720 | "has-cors": "1.1.0", 721 | "indexof": "0.0.1", 722 | "object-component": "0.0.3", 723 | "parseqs": "0.0.5", 724 | "parseuri": "0.0.5", 725 | "socket.io-parser": "3.1.2", 726 | "to-array": "0.1.4" 727 | } 728 | }, 729 | "socket.io-parser": { 730 | "version": "3.1.2", 731 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.2.tgz", 732 | "integrity": "sha1-28IoIVH8T6675Aru3Ady66YZ9/I=", 733 | "requires": { 734 | "component-emitter": "1.2.1", 735 | "debug": "2.6.9", 736 | "has-binary2": "1.0.2", 737 | "isarray": "2.0.1" 738 | } 739 | }, 740 | "statuses": { 741 | "version": "1.3.1", 742 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 743 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 744 | }, 745 | "to-array": { 746 | "version": "0.1.4", 747 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 748 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 749 | }, 750 | "type-is": { 751 | "version": "1.6.15", 752 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 753 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", 754 | "requires": { 755 | "media-typer": "0.3.0", 756 | "mime-types": "2.1.17" 757 | } 758 | }, 759 | "ultron": { 760 | "version": "1.1.1", 761 | "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", 762 | "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" 763 | }, 764 | "unpipe": { 765 | "version": "1.0.0", 766 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 767 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 768 | }, 769 | "utils-merge": { 770 | "version": "1.0.1", 771 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 772 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 773 | }, 774 | "uws": { 775 | "version": "0.14.5", 776 | "resolved": "https://registry.npmjs.org/uws/-/uws-0.14.5.tgz", 777 | "integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=", 778 | "optional": true 779 | }, 780 | "vary": { 781 | "version": "1.1.2", 782 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 783 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 784 | }, 785 | "ws": { 786 | "version": "3.3.3", 787 | "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", 788 | "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", 789 | "requires": { 790 | "async-limiter": "1.0.0", 791 | "safe-buffer": "5.1.1", 792 | "ultron": "1.1.1" 793 | } 794 | }, 795 | "xml2js": { 796 | "version": "0.4.19", 797 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 798 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 799 | "requires": { 800 | "sax": "1.2.4", 801 | "xmlbuilder": "9.0.7" 802 | } 803 | }, 804 | "xmlbuilder": { 805 | "version": "9.0.7", 806 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 807 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" 808 | }, 809 | "xmlhttprequest-ssl": { 810 | "version": "1.5.5", 811 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 812 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" 813 | }, 814 | "yeast": { 815 | "version": "0.1.2", 816 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 817 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 818 | } 819 | } 820 | } 821 | -------------------------------------------------------------------------------- /public/main.bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/$_lazy_route_resource lazy","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.component.css","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.component.html","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.component.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.module.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.routes.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/editor/editor.component.css","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/editor/editor.component.html","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/editor/editor.component.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/navbar/navbar.component.css","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/navbar/navbar.component.html","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/navbar/navbar.component.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/new-problem/new-problem.component.css","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/new-problem/new-problem.component.html","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/new-problem/new-problem.component.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-detail/problem-detail.component.css","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-detail/problem-detail.component.html","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-detail/problem-detail.component.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-list/problem-list.component.css","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-list/problem-list.component.html","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-list/problem-list.component.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/pipes/search.pipe.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/services/collaboration.service.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/services/data.service.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/services/input.service.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/environments/environment.ts","/Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/main.ts"],"names":[],"mappings":";;;;;AAAA;AACA;AACA;AACA;AACA;AACA,EAAE;AACF;AACA,4CAA4C,WAAW;AACvD;AACA;AACA,yF;;;;;;;ACVA;AACA;;;AAGA;AACA;;AAEA;;;AAGA;AACA,2C;;;;;;;ACXA,iF;;;;;;;;;;;;;;;;ACA0C;AAO1C;IALA;QAME,UAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAFY,YAAY;QALxB,wEAAS,CAAC;YACT,QAAQ,EAAE,UAAU;;;SAGrB,CAAC;OACW,YAAY,CAExB;IAAD,mBAAC;CAAA;AAFwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACPiC;AACjB;AACyB;AACV;AACgB;AAGzB;AACyC;AAElC;AACwC;AACtC;AAEjB;AAC8C;AACd;AACA;AACvB;AA0BhD;IAAA;IAAyB,CAAC;IAAb,SAAS;QAvBrB,uEAAQ,CAAC;YACR,YAAY,EAAE;gBACZ,oEAAY;gBACZ,6GAAoB;gBACpB,mHAAsB;gBACtB,2GAAmB;gBACnB,6FAAe;gBACf,6FAAe;gBACf,uEAAU;aACX;YACD,OAAO,EAAE;gBACP,gFAAa;gBACb,6DAAO;gBACP,mEAAW;gBACX,8EAAgB;gBAChB,2EAAmB;aACpB;YACD,SAAS,EAAE,CAAC,2EAAW;gBACrB,6FAAoB;gBACpB,6EAAY;aACb;YACD,SAAS,EAAE,CAAC,oEAAY,CAAC;SAC1B,CAAC;OACW,SAAS,CAAI;IAAD,gBAAC;CAAA;AAAJ;;;;;;;;;;;;;AC5CgC;AACkC;AACM;AAE9F,IAAM,MAAM,GAAW;IACnB;QACI,IAAI,EAAE,EAAE;QACR,UAAU,EAAE,UAAU;QACtB,SAAS,EAAE,MAAM,gBAAe;KACnC;IACD;QACI,IAAI,EAAE,UAAU;QAChB,SAAS,EAAE,6GAAoB;KAClC;IACD;QACI,IAAI,EAAE,cAAc;QACpB,SAAS,EAAE,mHAAsB;KACpC;IACD;QACI,IAAI,EAAE,IAAI;QACV,UAAU,EAAE,UAAU;KACzB;CACJ;AAEM,IAAM,OAAO,GAAG,qEAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;;;;;;;;ACxBpD;AACA;;;AAGA;AACA,wCAAyC,aAAa,oBAAoB,KAAK,kBAAkB,mBAAmB,yBAAyB,KAAK,iBAAiB,oBAAoB,KAAK,iBAAiB,oBAAoB,KAAK,oCAAoC,qBAAqB,KAAK,aAAa,0BAA0B,yCAAyC,kBAAkB,4BAA4B,KAAK,GAAG;;AAE1a;;;AAGA;AACA,2C;;;;;;;ACXA,qSAAqS,UAAU,2uBAA2uB,2mBAA2mB,QAAQ,wCAAwC,OAAO,uO;;;;;;;;;;;;;;;;;;;;;;ACA1oD;AAC0B;AACnB;AACC;AAS1D;IA2BE,gDAAgD;IAChD,yBAAoB,aAAmC,EACnC,KAAqB,EACrB,WAAwB;QAFxB,kBAAa,GAAb,aAAa,CAAsB;QACnC,UAAK,GAAL,KAAK,CAAgB;QACrB,gBAAW,GAAX,WAAW,CAAa;QA3B5C,mBAAc,GAAG;YACf,MAAM,EAAE,iIAIN;YACF,QAAQ,EAAE,sFAGT;YACD,KAAK,EAAC,mEAEF;SACL;QAED,cAAS,GAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChD,aAAQ,GAAW,MAAM,CAAC;IAWsB,CAAC;IAEjD,kCAAQ,GAAR;QAAA,iBAOC;QANC,IAAI,CAAC,KAAK,CAAC,MAAM;aACd,SAAS,CAAC,gBAAM;YACf,KAAI,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,KAAI,CAAC,UAAU,EAAE,CAAC;YAClB,KAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,qCAAW,GAAX;QACE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,qCAAW,GAAX,UAAY,QAAgB;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,gCAAM,GAAN;QAAA,iBAWC;QAVC,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEvB,IAAM,IAAI,GAAG;YACX,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE;SACxC,CAAC;QAEF,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC;aAC/B,IAAI,CAAC,aAAG,IAAI,YAAI,CAAC,MAAM,GAAG,GAAG,EAAjB,CAAiB,CAAC,CAAC;IACpC,CAAC;IAED,oCAAU,GAAV;QAAA,iBAmBC;QAlBC,uBAAuB;QACvB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,kCAAkC;QAClC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;aAC1E,SAAS,CAAC,eAAK,IAAI,YAAI,CAAC,KAAK,GAAG,KAAK,EAAlB,CAAkB,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAErC,2BAA2B;QAC3B,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAC;YACxB,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,uDAAuD;YACvD,EAAE,EAAC,KAAI,CAAC,MAAM,CAAC,iBAAiB,IAAI,CAAC,CAAC,EAAC;gBACrC,KAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAnFU,eAAe;QAL3B,wEAAS,CAAC;YACT,QAAQ,EAAE,YAAY;;;SAGvB,CAAC;yCA6BmC,6FAAoB;YAC5B,uEAAc;YACR,2EAAW;OA9BjC,eAAe,CAoF3B;IAAD,sBAAC;CAAA;AApF2B;;;;;;;;ACZ5B;AACA;;;AAGA;AACA;;AAEA;;;AAGA;AACA,2C;;;;;;;ACXA,mlBAAmlB,OAAO,4wB;;;;;;;;;;;;;;;;;;;;;;;ACAxiB;AACL;AAEJ;AACmB;AACpB;AAOxC;IAKE,yBAAoB,YAA0B,EAC1B,MAAc;QADd,iBAAY,GAAZ,YAAY,CAAc;QAC1B,WAAM,GAAN,MAAM,CAAQ;QALlC,UAAK,GAAG,SAAS,CAAC;QAClB,cAAS,GAAgB,IAAI,mEAAW,EAAE,CAAC;IAIL,CAAC;IAEvC,kCAAQ,GAAR;QAAA,iBAKC;QAJC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,SAAS;aACb,YAAY;aACZ,YAAY,CAAC,GAAG,CAAC;aACjB,SAAS,CAAC,cAAI,IAAK,KAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,GAAC,CAAC,CAAC;IAChF,CAAC;IAED,qCAAW,GAAX;QACE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;IAED,uCAAa,GAAb;QACE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IACtC,CAAC;IArBU,eAAe;QAL3B,wEAAS,CAAC;YACT,QAAQ,EAAE,YAAY;;;SAGvB,CAAC;yCAMkC,6EAAY;YAClB,+DAAM;OANvB,eAAe,CAsB3B;IAAD,sBAAC;CAAA;AAtB2B;;;;;;;;ACZ5B;AACA;;;AAGA;AACA;;AAEA;;;AAGA;AACA,2C;;;;;;;ACXA,gkCAAgkC,YAAY,sR;;;;;;;;;;;;;;;;;;;;ACA1hC;AAEQ;AAE1D,IAAM,eAAe,GAAY,MAAM,CAAC,MAAM,CAAC;IAC7C,EAAE,EAAE,CAAC;IACL,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,UAAU,EAAE,MAAM;CACnB,CAAC;AAOF;IAME,6BAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;QAL5C,8DAA8D;QAC9D,gIAAgI;QAChI,eAAU,GAAY,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;QACzD,iBAAY,GAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAEb,CAAC;IAEjD,sCAAQ,GAAR;IACA,CAAC;IAED,wCAAU,GAAV;QACE,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,2CAA2C;QAC3C,2EAA2E;QAC3E,+GAA+G;QAC/G,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;IACvD,CAAC;IAjBU,mBAAmB;QAL/B,wEAAS,CAAC;YACT,QAAQ,EAAE,iBAAiB;;;SAG5B,CAAC;yCAOiC,2EAAW;OANjC,mBAAmB,CAkB/B;IAAD,0BAAC;CAAA;AAlB+B;;;;;;;;AChBhC;AACA;;;AAGA;AACA;;AAEA;;;AAGA;AACA,2C;;;;;;;ACXA,qKAAqK,YAAY,IAAI,cAAc,oCAAoC,cAAc,oI;;;;;;;;;;;;;;;;;;;;;ACAnM;AACQ;AAED;AAOzD;IAGE,gCAAoB,WAAwB,EACxB,KAAqB;QADrB,gBAAW,GAAX,WAAW,CAAa;QACxB,UAAK,GAAL,KAAK,CAAgB;IAAI,CAAC;IAE9C,yCAAQ,GAAR;QAAA,iBAOC;QANC,+DAA+D;QAC/D,0BAA0B;QAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAM;YAChC,KAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;iBACvC,IAAI,CAAC,iBAAO,IAAI,YAAI,CAAC,OAAO,GAAG,OAAO,EAAtB,CAAsB,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;IAbU,sBAAsB;QALlC,wEAAS,CAAC;YACT,QAAQ,EAAE,oBAAoB;;;SAG/B,CAAC;yCAIiC,2EAAW;YACjB,uEAAc;OAJ9B,sBAAsB,CAelC;IAAD,6BAAC;CAAA;AAfkC;;;;;;;;ACVnC;AACA;;;AAGA;AACA,sCAAuC,oBAAoB,uBAAuB,GAAG,uBAAuB,uBAAuB,mBAAmB,oBAAoB,GAAG,YAAY,qBAAqB,GAAG,gBAAgB,8BAA8B,GAAG,kBAAkB,8BAA8B,GAAG,gBAAgB,8BAA8B,GAAG,iBAAiB,8BAA8B,GAAG;;AAExZ;;;AAGA;AACA,2C;;;;;;;ACXA,+TAA+T,6EAA6E,eAAe,oBAAoB,iDAAiD,YAAY,IAAI,cAAc,wC;;;;;;;;;;;;;;;;;;;;;ACA5c;AAEQ;AAEE;AAO5D;IAOE,8BAAoB,WAAwB,EAClC,YAA0B;QADhB,gBAAW,GAAX,WAAW,CAAa;QAClC,iBAAY,GAAZ,YAAY,CAAc;QALpC,aAAa;QACb,eAAU,GAAW,EAAE,CAAC;IAIgB,CAAC;IAEzC,uCAAQ,GAAR;QACE,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IACD,0CAAW,GAAX;QACE,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC;IAED,0CAAW,GAAX;QAAA,iBAKC;QAJC,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE;aACxD,SAAS,CAAC,kBAAQ;YACjB,KAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,4CAAa,GAAb;QAAA,iBAGC;QAFC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;aAChD,SAAS,CAAC,cAAI,IAAI,YAAI,CAAC,UAAU,GAAG,IAAI,EAAtB,CAAsB,CAAC,CAAC;IACjD,CAAC;IA5BU,oBAAoB;QALhC,wEAAS,CAAC;YACT,QAAQ,EAAE,kBAAkB;;;SAG7B,CAAC;yCAQiC,2EAAW;YACpB,6EAAY;OARzB,oBAAoB,CA6BhC;IAAD,2BAAC;CAAA;AA7BgC;;;;;;;;;;;;;;;;;ACXmB;AAMpD;IAAA;IAQA,CAAC;IANC,8BAAS,GAAT,UAAU,QAAmB,EAAE,IAAY;QACzC,4BAA4B;QAC5B,MAAM,CAAC,QAAQ,CAAC,MAAM,CACpB,iBAAO,IAAI,cAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAzC,CAAyC,CAAC,CAAC;IAC1D,CAAC;IANU,UAAU;QAHtB,mEAAI,CAAC;YACJ,IAAI,EAAE,QAAQ;SACf,CAAC;OACW,UAAU,CAQtB;IAAD,iBAAC;CAAA;AARsB;;;;;;;;;;;;;;;;;;;;;ACNoB;AAEJ;AAKvC;IAGE;QADQ,gBAAW,GAAG,IAAI,6DAAO,EAAU,CAAC;IAC5B,CAAC;IAEjB,mCAAI,GAAJ,UAAK,MAAW,EAAE,SAAiB;QAAnC,iBAuBC;QAtBC,iBAAiB;QACjB,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAC,KAAK,EAAE,YAAY,GAAG,SAAS,EAAC,CAAC,CAAC;QACzF,yCAAyC;QACzC,wDAAwD;QACxD,iEAAiE;QACjE,KAAK;QAEL,iCAAiC;QACjC,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAC,KAAa;YAClD,OAAO,CAAC,GAAG,CAAC,mCAAmC,GAAG,KAAK,CAAC,CAAC;YACzD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC;YACjC,8BAA8B;YAC9B,MAAM,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QACH,sBAAsB;QACtB,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,UAAC,KAAe;YACxD,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,KAAK,CAAC,CAAC;YACtC,KAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1C,CAAC,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;IACzC,CAAC;IAED,uEAAuE;IACvE,qCAAM,GAAN,UAAO,KAAa;QAClB,sBAAsB;QACtB,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,4CAAa,GAAb;QACE,kCAAkC;QAClC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACjD,CAAC;IAvCU,oBAAoB;QADhC,yEAAU,EAAE;;OACA,oBAAoB,CAwChC;IAAD,2BAAC;CAAA;AAxCgC;;;;;;;;;;;;;;;;;;;;;;ACPU;AAEkC;AAEtB;AACJ;AAGnD;IAGE,qBAAoB,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;QAFlC,mBAAc,GAAG,IAAI,6EAAe,CAAY,EAAE,CAAC,CAAC;IAEd,CAAC;IAE/C,4BAA4B;IAC5B,iCAAW,GAAX;QAAA,iBASC;QARC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,iBAAiB,CAAC;aACnC,SAAS,EAAE;aACX,IAAI,CAAC,UAAC,GAAQ;YACb,KAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC,CAAC;aACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC;IAE5C,CAAC;IACD,eAAe;IACf,yCAAyC;IACzC,2CAA2C;IAC3C,8DAA8D;IAC9D,+CAA+C;IAE/C,IAAI;IAEJ,yBAAyB;IACzB,gCAAU,GAAV,UAAW,EAAU;QACnB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,qBAAmB,EAAI,CAAC;aAChD,SAAS,EAAE;aACX,IAAI,CAAC,UAAC,GAAQ,IAAK,UAAG,EAAH,CAAG,CAAC;aACvB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IAED,cAAc;IACd,gCAAU,GAAV,UAAW,OAAgB;QAA3B,iBASC;QARC,IAAM,OAAO,GAAG,EAAC,OAAO,EAAE,IAAI,yEAAW,CAAC,EAAC,cAAc,EAAE,kBAAkB,EAAC,CAAC,EAAC,CAAC;QACjF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,EAAE,OAAO,EAAE,OAAO,CAAC;aAC7D,SAAS,EAAE;aACX,IAAI,CAAC,UAAC,GAAQ;YACb,KAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC;QACb,CAAC,CAAC;aACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IAED,sBAAsB;IACtB,iCAAW,GAAX,UAAY,IAAI;QACd,IAAM,OAAO,GAAG,EAAC,OAAO,EAAE,IAAI,yEAAW,CAAC,EAAC,cAAc,EAAE,kBAAkB,EAAC,CAAC,EAAC,CAAC;QACjF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,sBAAsB,EAAE,IAAI,EAAE,OAAO,CAAC;aAC/D,SAAS,EAAE;aACX,IAAI,CAAC,aAAG;YACP,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC;QACb,CAAC,CAAC;aACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;IAED,oBAAoB;IACpB,kCAAkC;IAClC,sFAAsF;IACtF,qEAAqE;IACrE,mBAAmB;IACnB,QAAQ;IACR,IAAI;IAEJ,gBAAgB;IACR,iCAAW,GAAnB,UAAoB,KAAU;QAC5B,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;IAC7C,CAAC;IApEU,WAAW;QADvB,yEAAU,EAAE;yCAIqB,wEAAU;OAH/B,WAAW,CAqEvB;IAAD,kBAAC;CAAA;AArEuB;;;;;;;;;;;;;;;;;;;;;ACRmB;AACY;AAIvD;IAEE;QADQ,kBAAa,GAAG,IAAI,6EAAe,CAAS,EAAE,CAAC,CAAC;IACxC,CAAC;IAEjB,kCAAW,GAAX,UAAY,IAAI;QACd,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,+BAAQ,GAAR;QACE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;IAC3C,CAAC;IAVU,YAAY;QADxB,yEAAU,EAAE;;OACA,YAAY,CAWxB;IAAD,mBAAC;CAAA;AAXwB;;;;;;;;;ACLzB;AAAA,mFAAmF;AACnF,8FAA8F;AAC9F,yEAAyE;AACzE,gFAAgF;AAEzE,IAAM,WAAW,GAAG;IACzB,UAAU,EAAE,KAAK;CAClB,CAAC;;;;;;;;;;;;;;ACP6C;AAC4B;AAE9B;AACY;AAEzD,EAAE,CAAC,CAAC,8EAAW,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3B,+EAAc,EAAE,CAAC;AACnB,CAAC;AAED,yGAAsB,EAAE,CAAC,eAAe,CAAC,kEAAS,CAAC;KAChD,KAAK,CAAC,aAAG,IAAI,cAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAhB,CAAgB,CAAC,CAAC","file":"main.bundle.js","sourcesContent":["function webpackEmptyAsyncContext(req) {\n\t// Here Promise.resolve().then() is used instead of new Promise() to prevent\n\t// uncatched exception popping up in devtools\n\treturn Promise.resolve().then(function() {\n\t\tthrow new Error(\"Cannot find module '\" + req + \"'.\");\n\t});\n}\nwebpackEmptyAsyncContext.keys = function() { return []; };\nwebpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;\nmodule.exports = webpackEmptyAsyncContext;\nwebpackEmptyAsyncContext.id = \"../../../../../src/$$_lazy_route_resource lazy recursive\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/$$_lazy_route_resource lazy\n// module id = ../../../../../src/$$_lazy_route_resource lazy recursive\n// module chunks = main","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \"\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.component.css\n// module id = ../../../../../src/app/app.component.css\n// module chunks = main","module.exports = \"\\n\\n\\n\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.component.html\n// module id = ../../../../../src/app/app.component.html\n// module chunks = main","import { Component } from '@angular/core';\n\n@Component({\n selector: 'app-root',\n templateUrl: './app.component.html',\n styleUrls: ['./app.component.css']\n})\nexport class AppComponent {\n title = 'app';\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.component.ts","import { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { HttpClientModule } from '@angular/common/http';\nimport { CollaborationService } from './services/collaboration.service';\n\n\nimport { AppComponent } from './app.component';\nimport { ProblemListComponent } from './components/problem-list/problem-list.component';\n\nimport { DataService } from './services/data.service';\nimport { ProblemDetailComponent } from './components/problem-detail/problem-detail.component';\nimport { InputService } from './services/input.service';\n\nimport { routing } from './app.routes';\nimport { NewProblemComponent } from './components/new-problem/new-problem.component';\nimport { NavbarComponent } from './components/navbar/navbar.component';\nimport { EditorComponent } from './components/editor/editor.component';\nimport { SearchPipe } from './pipes/search.pipe'\n\n\n@NgModule({\n declarations: [\n AppComponent,\n ProblemListComponent,\n ProblemDetailComponent,\n NewProblemComponent,\n NavbarComponent,\n EditorComponent,\n SearchPipe\n ],\n imports: [\n BrowserModule,\n routing,\n FormsModule,\n HttpClientModule,\n ReactiveFormsModule\n ],\n providers: [DataService,\n CollaborationService,\n InputService\n ],\n bootstrap: [AppComponent]\n})\nexport class AppModule { }\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.module.ts","import { Routes, RouterModule} from '@angular/router';\nimport { ProblemListComponent } from './components/problem-list/problem-list.component';\nimport { ProblemDetailComponent } from './components/problem-detail/problem-detail.component';\n\nconst routes: Routes = [\n {\n path: '',\n redirectTo: 'problems',\n pathMatch: 'full'//exactly match\n },\n {\n path: 'problems',\n component: ProblemListComponent\n },\n {\n path: 'problems/:id',\n component: ProblemDetailComponent\n },\n {\n path: '**',\n redirectTo: 'problems'\n }\n]\n\nexport const routing = RouterModule.forRoot(routes);\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/app.routes.ts","exports = module.exports = require(\"../../../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \"@media screen {\\n\\t#editor {\\n\\t\\theight: 600px;\\n\\t}\\n\\t.lang-select {\\n\\t\\twidth: 100px;\\n\\t\\tmargin-right: 10px;\\n\\t}\\n\\theader .btn {\\n\\t\\tmargin: 0 5px;\\n\\t}\\n\\tfooter .btn {\\n\\t\\tmargin: 0 5px;\\n\\t}\\n\\t.editor-footer, .editor-header {\\n\\t\\tmargin: 10px 0;\\n\\t}\\n\\t.cursor {\\n\\t\\t/*position:absolute;*/\\n\\t\\tbackground: rgba(0, 250, 0, 0.5);\\n\\t\\tz-index: 40;\\n\\t\\twidth: 2px !important;\\n\\t}\\n}\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/editor/editor.component.css\n// module id = ../../../../../src/app/components/editor/editor.component.css\n// module chunks = main","module.exports = \"
\\n
\\n \\n \\n \\n \\n\\n \\n
\\n
\\n
\\n
\\n
Are you sure
\\n \\n
\\n
\\n You will lose current code in the editor, are you sure?\\n
\\n
\\n \\n \\n
\\n
\\n
\\n
\\n
\\n
\\n
\\n
\\n
\\n Output: {{output}}\\n
\\n
\\n Users: {{users}}\\n
\\n
\\n
\\n \\n
\\n
\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/editor/editor.component.html\n// module id = ../../../../../src/app/components/editor/editor.component.html\n// module chunks = main","import { Component, OnInit } from '@angular/core';\nimport { CollaborationService } from '../../services/collaboration.service';\nimport { ActivatedRoute, Params } from '@angular/router';\nimport { DataService } from '../../services/data.service';\nimport { Subscription } from 'rxjs/Subscription';\n\ndeclare var ace: any;// must be declared\n@Component({\n selector: 'app-editor',\n templateUrl: './editor.component.html',\n styleUrls: ['./editor.component.css']\n})\nexport class EditorComponent implements OnInit {\n editor: any;\n\n defaultContent = {\n 'Java': `public class Solution{\n public static void main(String[] args){\n // Please type your code here...\n }\n }`,\n 'Python': `class Solution:\n def example():\n # Please type your code here...\n `,\n 'C++':`int main(){\n /* Please type your code here... */\n }`\n }\n\n languages: string[] = ['Java', 'Python', 'C++'];\n language: string = 'Java';\n sessionId: string;\n\n output: string;\n\n users: string;\n subscriptionUsers: Subscription;\n\n // inject route service and collaborationService\n constructor(private collaboration: CollaborationService,\n private route: ActivatedRoute,\n private dataService: DataService) { }\n\n ngOnInit() {\n this.route.params\n .subscribe(params => {\n this.sessionId = params['id'];\n this.initEditor();\n this.collaboration.restoreBuffer();\n });\n }\n\n resetEditor(): void {\n this.editor.setValue(this.defaultContent[this.language]);\n this.editor.getSession().setMode(\"ace/mode/\" + this.language.toLowerCase()); \n }\n\n setLanguage(language: string): void {\n this.language = language;\n this.resetEditor();\n }\n\n submit(): void {\n let user_code = this.editor.getValue();\n console.log(user_code);\n\n const data = {\n code: user_code,\n lang: this.language.toLocaleLowerCase()\n };\n\n this.dataService.buildAndRun(data)\n .then(res => this.output = res);\n }\n\n initEditor(): void {\n // editor basic setting\n this.editor = ace.edit(\"editor\");\n this.editor.setTheme(\"ace/theme/eclipse\");\n this.resetEditor();\n\n // initialize collaborationService\n this.subscriptionUsers = this.collaboration.init(this.editor, this.sessionId)\n .subscribe(users => this.users = users);\n this.editor.lastAppliedChange = null;\n\n // register change callback\n this.editor.on(\"change\", e => {\n console.log('editor changes: ' + JSON.stringify(e));\n // if the change is the same as the last one, then skip\n if(this.editor.lastAppliedChange != e){\n this.collaboration.change(JSON.stringify(e));\n }\n }); \n }\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/editor/editor.component.ts","exports = module.exports = require(\"../../../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \"\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/navbar/navbar.component.css\n// module id = ../../../../../src/app/components/navbar/navbar.component.css\n// module chunks = main","module.exports = \"\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/navbar/navbar.component.html\n// module id = ../../../../../src/app/components/navbar/navbar.component.html\n// module chunks = main","import { Component, OnInit } from '@angular/core';\nimport { FormControl } from '@angular/forms';\nimport { Subscription } from 'rxjs/Subscription';\nimport { Router } from '@angular/router';\nimport { InputService } from '../../services/input.service';\nimport 'rxjs/add/operator/debounceTime'; \n\n@Component({\n selector: 'app-navbar',\n templateUrl: './navbar.component.html',\n styleUrls: ['./navbar.component.css']\n})\nexport class NavbarComponent implements OnInit {\n title = 'LabCode';\n searchBox: FormControl = new FormControl();\n subscription: Subscription;\n\n constructor(private inputService: InputService,\n private router: Router) { }\n\n ngOnInit() {\n this.subscription = this.searchBox\n .valueChanges\n .debounceTime(200)\n .subscribe(term => {this.inputService.changeInput(term)});\n }\n\n ngOnDestroy() {\n this.subscription.unsubscribe();\n }\n\n searchProblem(): void {\n this.router.navigate(['/problems']);\n }\n} \n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/navbar/navbar.component.ts","exports = module.exports = require(\"../../../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \"\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/new-problem/new-problem.component.css\n// module id = ../../../../../src/app/components/new-problem/new-problem.component.css\n// module chunks = main","module.exports = \"
\\n \\n
\\n
\\n \\n \\n \\n
\\n
\\n \\n \\n
\\n
\\n \\n \\n
\\n
\\n
\\n \\n
\\n
\\n
\\n
\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/new-problem/new-problem.component.html\n// module id = ../../../../../src/app/components/new-problem/new-problem.component.html\n// module chunks = main","import { Component, OnInit } from '@angular/core';\nimport { Problem } from '../../models/problem.model';\nimport { DataService } from '../../services/data.service';\n\nconst DEFAULT_PROBLEM: Problem = Object.freeze({\n id: 0,\n name: '',\n desc: '',\n difficulty: 'easy'\n})\n\n@Component({\n selector: 'app-new-problem',\n templateUrl: './new-problem.component.html',\n styleUrls: ['./new-problem.component.css']\n})\nexport class NewProblemComponent implements OnInit {\n // create a shadow copy of problem and assign it to newProblem\n // Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value.\n newProblem: Problem = Object.assign({}, DEFAULT_PROBLEM);\n difficulties: string[] = ['easy', 'medium', 'hard', 'super'];\n\n constructor(private dataService: DataService) { }\n\n ngOnInit() {\n }\n \n addProblem(){\n this.dataService.addProblem(this.newProblem);\n // assign newProblem a new problem instance\n // Otherwise newProblem have same reference as the one we added to the list\n // then when next time add new problem, it will override the problem we have already add into the problem list.\n this.newProblem = Object.assign({}, DEFAULT_PROBLEM);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/new-problem/new-problem.component.ts","exports = module.exports = require(\"../../../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \"\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-detail/problem-detail.component.css\n// module id = ../../../../../src/app/components/problem-detail/problem-detail.component.css\n// module chunks = main","module.exports = \"\\n
\\n
\\n
\\n

\\n {{problem.id}}. {{problem.name}}\\n

\\n

\\n {{problem.desc}}\\n

\\n
\\n
\\n
\\n \\n
\\n
\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-detail/problem-detail.component.html\n// module id = ../../../../../src/app/components/problem-detail/problem-detail.component.html\n// module chunks = main","import { Component, OnInit } from '@angular/core';\nimport { DataService } from '../../services/data.service';\nimport { Problem } from '../../models/problem.model';\nimport { ActivatedRoute, Params } from '@angular/router';\n\n@Component({\n selector: 'app-problem-detail',\n templateUrl: './problem-detail.component.html',\n styleUrls: ['./problem-detail.component.css']\n})\nexport class ProblemDetailComponent implements OnInit {\n problem: Problem;\n\n constructor(private dataService: DataService,\n private route: ActivatedRoute) { }\n\n ngOnInit() {\n // subscribe: when params changes, this.problem will be updated\n // +: conver string to int\n this.route.params.subscribe(params => {\n this.dataService.getProblem(+params['id'])\n .then(problem => this.problem = problem);\n });\n }\n\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-detail/problem-detail.component.ts","exports = module.exports = require(\"../../../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \".difficulty {\\n min-width: 65px;\\n margin-right: 10px;\\n}\\n\\n.label.difficulty {\\n padding-top: 0.6em;\\n color: #fbfdfa;\\n font-size: 12px;\\n}\\n\\n.title {\\n font-size: 1.2em;\\n}\\n\\n.diff-easy {\\n background-color: #42ebf4;\\n}\\n\\n.diff-medium {\\n background-color: #92cf5c;\\n}\\n\\n.diff-hard {\\n background-color: #dd0d1e;\\n}\\n\\n.diff-super {\\n background-color: #8d16e2;\\n}\", \"\"]);\n\n// exports\n\n\n/*** EXPORTS FROM exports-loader ***/\nmodule.exports = module.exports.toString();\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-list/problem-list.component.css\n// module id = ../../../../../src/app/components/problem-list/problem-list.component.css\n// module chunks = main","module.exports = \"\\n\"\n\n\n//////////////////\n// WEBPACK FOOTER\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-list/problem-list.component.html\n// module id = ../../../../../src/app/components/problem-list/problem-list.component.html\n// module chunks = main","import { Component, OnInit } from '@angular/core';\nimport { Problem } from '../../models/problem.model';\nimport { DataService } from '../../services/data.service';\nimport { Subscription } from 'rxjs/Subscription';\nimport { InputService } from '../../services/input.service';\n\n@Component({\n selector: 'app-problem-list',\n templateUrl: './problem-list.component.html',\n styleUrls: ['./problem-list.component.css']\n})\nexport class ProblemListComponent implements OnInit {\n problems: Problem[];\n subcriptionProblems: Subscription;\n // for navbar\n searchTerm: String = '';\n subscriptionInput: Subscription;\n\n constructor(private dataService: DataService,\n private inputService: InputService) { }\n\n ngOnInit() {\n this.getProblems();\n this.getSearchTerm();\n }\n ngOnDestroy() {\n this.subcriptionProblems.unsubscribe();\n }\n \n getProblems() {\n this.subcriptionProblems = this.dataService.getProblems()\n .subscribe(problems => {\n this.problems = problems;\n });\n }\n\n getSearchTerm(): void { \n this.subscriptionInput = this.inputService.getInput()\n .subscribe(term => this.searchTerm = term);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/components/problem-list/problem-list.component.ts","import { Pipe, PipeTransform } from '@angular/core';\nimport { Problem } from '../models/problem.model';\n\n@Pipe({\n name: 'search'\n})\nexport class SearchPipe implements PipeTransform {\n\n transform(problems: Problem[], term: string): Problem[] {\n // get filtered problem list\n return problems.filter(\n problem => problem.name.toLowerCase().includes(term));\n }\n\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/pipes/search.pipe.ts","import { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs/Observable';\nimport { Subject } from 'rxjs/Subject';\n\ndeclare var io: any; // io is already imported in angular.cli.json\n\n@Injectable()\nexport class CollaborationService {\n collaborationSocket: any;\n private _userSource = new Subject();\n constructor() { }\n\n init(editor: any, sessionId: string): Observable {\n // send to server\n this.collaborationSocket = io(window.location.origin, {query: 'sessionId=' + sessionId});\n // //wait for 'message' event from server\n // this.collaborationSocket.on(\"message\", (message) => {\n // console.log('message received from the server: ' + message);\n // })\n \n // handle the changes from server\n this.collaborationSocket.on('change', (delta: string) => {\n console.log('collaboration: editor changes by ' + delta);\n delta = JSON.parse(delta);\n editor.lastAppliedChange = delta;\n // apply the changes on editor\n editor.getSession().getDocument().applyDeltas([delta]);\n });\n // handle user changes\n this.collaborationSocket.on('userchange', (users: string[]) => {\n console.log('user changed: ' + users);\n this._userSource.next(users.toString());\n })\n\n return this._userSource.asObservable();\n }\n\n // emit event to make changes and inform server and other collaborators\n change(delta: string): void {\n // emit \"change\" event\n this.collaborationSocket.emit('change', delta);\n }\n\n restoreBuffer(): void {\n // let the server handle the event\n this.collaborationSocket.emit('restoreBuffer');\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/services/collaboration.service.ts","import { Injectable } from '@angular/core';\nimport { Problem } from '../models/problem.model';\nimport { HttpClient, HttpRequest, HttpResponse } from '@angular/common/http';\nimport { Observable } from 'rxjs/Rx';\nimport { BehaviorSubject } from 'rxjs/BehaviorSubject';\nimport { HttpHeaders } from '@angular/common/http';\n\n@Injectable()\nexport class DataService {\n private _problemSource = new BehaviorSubject([]);\n\n constructor(private httpClient: HttpClient) { }\n \n // return a list of problems\n getProblems(): Observable {\n this.httpClient.get('api/v1/problems')\n .toPromise()\n .then((res: any) => {\n this._problemSource.next(res);\n })\n .catch(this.handleError);\n return this._problemSource.asObservable();\n\n }\n //use subscribe\n // getProblems(): Observable {\n // this.httpClient.get('api/v1/problems')\n // .subscribe((res:any) => this._problemSource.next(res));\n // return this._problemSource.asObservable();\n\n // }\n\n // return a problem by id\n getProblem(id: number): Promise {\n return this.httpClient.get(`api/v1/problems/${id}`)\n .toPromise()\n .then((res: any) => res)\n .catch(this.handleError);\n }\n\n // add problem\n addProblem(problem: Problem){\n const options = {headers: new HttpHeaders({'Content-Type': 'application/json'})};\n return this.httpClient.post('api/v1/problems', problem, options)\n .toPromise()\n .then((res: any) => {\n this.getProblems();\n return res;\n })\n .catch(this.handleError);\n }\n\n // build and run: POST\n buildAndRun(data): Promise{\n const options = {headers: new HttpHeaders({'Content-Type': 'application/json'})};\n return this.httpClient.post('api/v1/build_and_run', data, options)\n .toPromise()\n .then(res => {\n console.log(res);\n return res;\n })\n .catch(this.handleError);\n }\n\n // // modify problem\n // editProblem(problem: Problem) {\n // const options = {headers: new HttpHeaders({'Content-Type': 'application/json'})};\n // return this.httpClient.post('api/v1/problems', problem, options)\n // .toPromise()\n // .\n // }\n\n // handle errors\n private handleError(error: any): Promise{\n console.error('Error reference', error);\n return Promise.reject(error.body || error);\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/services/data.service.ts","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs/BehaviorSubject';\nimport { Observable } from 'rxjs/Rx';\n\n@Injectable()\nexport class InputService {\n private inputSubject$ = new BehaviorSubject('');\n constructor() { }\n\n changeInput(term) {\n this.inputSubject$.next(term);\n }\n\n getInput(): Observable {\n return this.inputSubject$.asObservable();\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/app/services/input.service.ts","// The file contents for the current environment will overwrite these during build.\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\n// The list of which env maps to which file can be found in `.angular-cli.json`.\n\nexport const environment = {\n production: false\n};\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/environments/environment.ts","import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule)\n .catch(err => console.log(err));\n\n\n\n// WEBPACK FOOTER //\n// /Users/ChenQi/BitTiger-CS503-1801/week3/oj-client/src/main.ts"],"sourceRoot":"webpack:///"} -------------------------------------------------------------------------------- /public/main.bundle.js: -------------------------------------------------------------------------------- 1 | webpackJsonp(["main"],{ 2 | 3 | /***/ "../../../../../src/$$_lazy_route_resource lazy recursive": 4 | /***/ (function(module, exports) { 5 | 6 | function webpackEmptyAsyncContext(req) { 7 | // Here Promise.resolve().then() is used instead of new Promise() to prevent 8 | // uncatched exception popping up in devtools 9 | return Promise.resolve().then(function() { 10 | throw new Error("Cannot find module '" + req + "'."); 11 | }); 12 | } 13 | webpackEmptyAsyncContext.keys = function() { return []; }; 14 | webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext; 15 | module.exports = webpackEmptyAsyncContext; 16 | webpackEmptyAsyncContext.id = "../../../../../src/$$_lazy_route_resource lazy recursive"; 17 | 18 | /***/ }), 19 | 20 | /***/ "../../../../../src/app/app.component.css": 21 | /***/ (function(module, exports, __webpack_require__) { 22 | 23 | exports = module.exports = __webpack_require__("../../../../css-loader/lib/css-base.js")(false); 24 | // imports 25 | 26 | 27 | // module 28 | exports.push([module.i, "", ""]); 29 | 30 | // exports 31 | 32 | 33 | /*** EXPORTS FROM exports-loader ***/ 34 | module.exports = module.exports.toString(); 35 | 36 | /***/ }), 37 | 38 | /***/ "../../../../../src/app/app.component.html": 39 | /***/ (function(module, exports) { 40 | 41 | module.exports = "\n\n\n" 42 | 43 | /***/ }), 44 | 45 | /***/ "../../../../../src/app/app.component.ts": 46 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 47 | 48 | "use strict"; 49 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AppComponent; }); 50 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 51 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 52 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 53 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 54 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 55 | return c > 3 && r && Object.defineProperty(target, key, r), r; 56 | }; 57 | 58 | var AppComponent = /** @class */ (function () { 59 | function AppComponent() { 60 | this.title = 'app'; 61 | } 62 | AppComponent = __decorate([ 63 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ 64 | selector: 'app-root', 65 | template: __webpack_require__("../../../../../src/app/app.component.html"), 66 | styles: [__webpack_require__("../../../../../src/app/app.component.css")] 67 | }) 68 | ], AppComponent); 69 | return AppComponent; 70 | }()); 71 | 72 | 73 | 74 | /***/ }), 75 | 76 | /***/ "../../../../../src/app/app.module.ts": 77 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 78 | 79 | "use strict"; 80 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AppModule; }); 81 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_platform_browser__ = __webpack_require__("../../../platform-browser/esm5/platform-browser.js"); 82 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 83 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__angular_forms__ = __webpack_require__("../../../forms/esm5/forms.js"); 84 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__angular_common_http__ = __webpack_require__("../../../common/esm5/http.js"); 85 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__services_collaboration_service__ = __webpack_require__("../../../../../src/app/services/collaboration.service.ts"); 86 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__app_component__ = __webpack_require__("../../../../../src/app/app.component.ts"); 87 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__components_problem_list_problem_list_component__ = __webpack_require__("../../../../../src/app/components/problem-list/problem-list.component.ts"); 88 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__services_data_service__ = __webpack_require__("../../../../../src/app/services/data.service.ts"); 89 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__components_problem_detail_problem_detail_component__ = __webpack_require__("../../../../../src/app/components/problem-detail/problem-detail.component.ts"); 90 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__services_input_service__ = __webpack_require__("../../../../../src/app/services/input.service.ts"); 91 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__app_routes__ = __webpack_require__("../../../../../src/app/app.routes.ts"); 92 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__components_new_problem_new_problem_component__ = __webpack_require__("../../../../../src/app/components/new-problem/new-problem.component.ts"); 93 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__components_navbar_navbar_component__ = __webpack_require__("../../../../../src/app/components/navbar/navbar.component.ts"); 94 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__components_editor_editor_component__ = __webpack_require__("../../../../../src/app/components/editor/editor.component.ts"); 95 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__pipes_search_pipe__ = __webpack_require__("../../../../../src/app/pipes/search.pipe.ts"); 96 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 97 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 98 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 99 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 100 | return c > 3 && r && Object.defineProperty(target, key, r), r; 101 | }; 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | var AppModule = /** @class */ (function () { 118 | function AppModule() { 119 | } 120 | AppModule = __decorate([ 121 | Object(__WEBPACK_IMPORTED_MODULE_1__angular_core__["I" /* NgModule */])({ 122 | declarations: [ 123 | __WEBPACK_IMPORTED_MODULE_5__app_component__["a" /* AppComponent */], 124 | __WEBPACK_IMPORTED_MODULE_6__components_problem_list_problem_list_component__["a" /* ProblemListComponent */], 125 | __WEBPACK_IMPORTED_MODULE_8__components_problem_detail_problem_detail_component__["a" /* ProblemDetailComponent */], 126 | __WEBPACK_IMPORTED_MODULE_11__components_new_problem_new_problem_component__["a" /* NewProblemComponent */], 127 | __WEBPACK_IMPORTED_MODULE_12__components_navbar_navbar_component__["a" /* NavbarComponent */], 128 | __WEBPACK_IMPORTED_MODULE_13__components_editor_editor_component__["a" /* EditorComponent */], 129 | __WEBPACK_IMPORTED_MODULE_14__pipes_search_pipe__["a" /* SearchPipe */] 130 | ], 131 | imports: [ 132 | __WEBPACK_IMPORTED_MODULE_0__angular_platform_browser__["a" /* BrowserModule */], 133 | __WEBPACK_IMPORTED_MODULE_10__app_routes__["a" /* routing */], 134 | __WEBPACK_IMPORTED_MODULE_2__angular_forms__["b" /* FormsModule */], 135 | __WEBPACK_IMPORTED_MODULE_3__angular_common_http__["b" /* HttpClientModule */], 136 | __WEBPACK_IMPORTED_MODULE_2__angular_forms__["c" /* ReactiveFormsModule */] 137 | ], 138 | providers: [__WEBPACK_IMPORTED_MODULE_7__services_data_service__["a" /* DataService */], 139 | __WEBPACK_IMPORTED_MODULE_4__services_collaboration_service__["a" /* CollaborationService */], 140 | __WEBPACK_IMPORTED_MODULE_9__services_input_service__["a" /* InputService */] 141 | ], 142 | bootstrap: [__WEBPACK_IMPORTED_MODULE_5__app_component__["a" /* AppComponent */]] 143 | }) 144 | ], AppModule); 145 | return AppModule; 146 | }()); 147 | 148 | 149 | 150 | /***/ }), 151 | 152 | /***/ "../../../../../src/app/app.routes.ts": 153 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 154 | 155 | "use strict"; 156 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return routing; }); 157 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_router__ = __webpack_require__("../../../router/esm5/router.js"); 158 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__components_problem_list_problem_list_component__ = __webpack_require__("../../../../../src/app/components/problem-list/problem-list.component.ts"); 159 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_problem_detail_problem_detail_component__ = __webpack_require__("../../../../../src/app/components/problem-detail/problem-detail.component.ts"); 160 | 161 | 162 | 163 | var routes = [ 164 | { 165 | path: '', 166 | redirectTo: 'problems', 167 | pathMatch: 'full' //exactly match 168 | }, 169 | { 170 | path: 'problems', 171 | component: __WEBPACK_IMPORTED_MODULE_1__components_problem_list_problem_list_component__["a" /* ProblemListComponent */] 172 | }, 173 | { 174 | path: 'problems/:id', 175 | component: __WEBPACK_IMPORTED_MODULE_2__components_problem_detail_problem_detail_component__["a" /* ProblemDetailComponent */] 176 | }, 177 | { 178 | path: '**', 179 | redirectTo: 'problems' 180 | } 181 | ]; 182 | var routing = __WEBPACK_IMPORTED_MODULE_0__angular_router__["c" /* RouterModule */].forRoot(routes); 183 | 184 | 185 | /***/ }), 186 | 187 | /***/ "../../../../../src/app/components/editor/editor.component.css": 188 | /***/ (function(module, exports, __webpack_require__) { 189 | 190 | exports = module.exports = __webpack_require__("../../../../css-loader/lib/css-base.js")(false); 191 | // imports 192 | 193 | 194 | // module 195 | exports.push([module.i, "@media screen {\n\t#editor {\n\t\theight: 600px;\n\t}\n\t.lang-select {\n\t\twidth: 100px;\n\t\tmargin-right: 10px;\n\t}\n\theader .btn {\n\t\tmargin: 0 5px;\n\t}\n\tfooter .btn {\n\t\tmargin: 0 5px;\n\t}\n\t.editor-footer, .editor-header {\n\t\tmargin: 10px 0;\n\t}\n\t.cursor {\n\t\t/*position:absolute;*/\n\t\tbackground: rgba(0, 250, 0, 0.5);\n\t\tz-index: 40;\n\t\twidth: 2px !important;\n\t}\n}", ""]); 196 | 197 | // exports 198 | 199 | 200 | /*** EXPORTS FROM exports-loader ***/ 201 | module.exports = module.exports.toString(); 202 | 203 | /***/ }), 204 | 205 | /***/ "../../../../../src/app/components/editor/editor.component.html": 206 | /***/ (function(module, exports) { 207 | 208 | module.exports = "
\n
\n \n \n \n \n\n \n
\n
\n
\n
\n
Are you sure
\n \n
\n
\n You will lose current code in the editor, are you sure?\n
\n
\n \n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n Output: {{output}}\n
\n
\n Users: {{users}}\n
\n
\n
\n \n
\n
" 209 | 210 | /***/ }), 211 | 212 | /***/ "../../../../../src/app/components/editor/editor.component.ts": 213 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 214 | 215 | "use strict"; 216 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return EditorComponent; }); 217 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 218 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__services_collaboration_service__ = __webpack_require__("../../../../../src/app/services/collaboration.service.ts"); 219 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__angular_router__ = __webpack_require__("../../../router/esm5/router.js"); 220 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__services_data_service__ = __webpack_require__("../../../../../src/app/services/data.service.ts"); 221 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 222 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 223 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 224 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 225 | return c > 3 && r && Object.defineProperty(target, key, r), r; 226 | }; 227 | var __metadata = (this && this.__metadata) || function (k, v) { 228 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 229 | }; 230 | 231 | 232 | 233 | 234 | var EditorComponent = /** @class */ (function () { 235 | // inject route service and collaborationService 236 | function EditorComponent(collaboration, route, dataService) { 237 | this.collaboration = collaboration; 238 | this.route = route; 239 | this.dataService = dataService; 240 | this.defaultContent = { 241 | 'Java': "public class Solution{\n public static void main(String[] args){\n // Please type your code here...\n }\n }", 242 | 'Python': "class Solution:\n def example():\n # Please type your code here...\n ", 243 | 'C++': "int main(){\n /* Please type your code here... */\n }" 244 | }; 245 | this.languages = ['Java', 'Python', 'C++']; 246 | this.language = 'Java'; 247 | } 248 | EditorComponent.prototype.ngOnInit = function () { 249 | var _this = this; 250 | this.route.params 251 | .subscribe(function (params) { 252 | _this.sessionId = params['id']; 253 | _this.initEditor(); 254 | _this.collaboration.restoreBuffer(); 255 | }); 256 | }; 257 | EditorComponent.prototype.resetEditor = function () { 258 | this.editor.setValue(this.defaultContent[this.language]); 259 | this.editor.getSession().setMode("ace/mode/" + this.language.toLowerCase()); 260 | }; 261 | EditorComponent.prototype.setLanguage = function (language) { 262 | this.language = language; 263 | this.resetEditor(); 264 | }; 265 | EditorComponent.prototype.submit = function () { 266 | var _this = this; 267 | var user_code = this.editor.getValue(); 268 | console.log(user_code); 269 | var data = { 270 | code: user_code, 271 | lang: this.language.toLocaleLowerCase() 272 | }; 273 | this.dataService.buildAndRun(data) 274 | .then(function (res) { return _this.output = res; }); 275 | }; 276 | EditorComponent.prototype.initEditor = function () { 277 | var _this = this; 278 | // editor basic setting 279 | this.editor = ace.edit("editor"); 280 | this.editor.setTheme("ace/theme/eclipse"); 281 | this.resetEditor(); 282 | // initialize collaborationService 283 | this.subscriptionUsers = this.collaboration.init(this.editor, this.sessionId) 284 | .subscribe(function (users) { return _this.users = users; }); 285 | this.editor.lastAppliedChange = null; 286 | // register change callback 287 | this.editor.on("change", function (e) { 288 | console.log('editor changes: ' + JSON.stringify(e)); 289 | // if the change is the same as the last one, then skip 290 | if (_this.editor.lastAppliedChange != e) { 291 | _this.collaboration.change(JSON.stringify(e)); 292 | } 293 | }); 294 | }; 295 | EditorComponent = __decorate([ 296 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ 297 | selector: 'app-editor', 298 | template: __webpack_require__("../../../../../src/app/components/editor/editor.component.html"), 299 | styles: [__webpack_require__("../../../../../src/app/components/editor/editor.component.css")] 300 | }), 301 | __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_1__services_collaboration_service__["a" /* CollaborationService */], 302 | __WEBPACK_IMPORTED_MODULE_2__angular_router__["a" /* ActivatedRoute */], 303 | __WEBPACK_IMPORTED_MODULE_3__services_data_service__["a" /* DataService */]]) 304 | ], EditorComponent); 305 | return EditorComponent; 306 | }()); 307 | 308 | 309 | 310 | /***/ }), 311 | 312 | /***/ "../../../../../src/app/components/navbar/navbar.component.css": 313 | /***/ (function(module, exports, __webpack_require__) { 314 | 315 | exports = module.exports = __webpack_require__("../../../../css-loader/lib/css-base.js")(false); 316 | // imports 317 | 318 | 319 | // module 320 | exports.push([module.i, "", ""]); 321 | 322 | // exports 323 | 324 | 325 | /*** EXPORTS FROM exports-loader ***/ 326 | module.exports = module.exports.toString(); 327 | 328 | /***/ }), 329 | 330 | /***/ "../../../../../src/app/components/navbar/navbar.component.html": 331 | /***/ (function(module, exports) { 332 | 333 | module.exports = "" 334 | 335 | /***/ }), 336 | 337 | /***/ "../../../../../src/app/components/navbar/navbar.component.ts": 338 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 339 | 340 | "use strict"; 341 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return NavbarComponent; }); 342 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 343 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_forms__ = __webpack_require__("../../../forms/esm5/forms.js"); 344 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__angular_router__ = __webpack_require__("../../../router/esm5/router.js"); 345 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__services_input_service__ = __webpack_require__("../../../../../src/app/services/input.service.ts"); 346 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_rxjs_add_operator_debounceTime__ = __webpack_require__("../../../../rxjs/_esm5/add/operator/debounceTime.js"); 347 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 348 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 349 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 350 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 351 | return c > 3 && r && Object.defineProperty(target, key, r), r; 352 | }; 353 | var __metadata = (this && this.__metadata) || function (k, v) { 354 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 355 | }; 356 | 357 | 358 | 359 | 360 | 361 | var NavbarComponent = /** @class */ (function () { 362 | function NavbarComponent(inputService, router) { 363 | this.inputService = inputService; 364 | this.router = router; 365 | this.title = 'LabCode'; 366 | this.searchBox = new __WEBPACK_IMPORTED_MODULE_1__angular_forms__["a" /* FormControl */](); 367 | } 368 | NavbarComponent.prototype.ngOnInit = function () { 369 | var _this = this; 370 | this.subscription = this.searchBox 371 | .valueChanges 372 | .debounceTime(200) 373 | .subscribe(function (term) { _this.inputService.changeInput(term); }); 374 | }; 375 | NavbarComponent.prototype.ngOnDestroy = function () { 376 | this.subscription.unsubscribe(); 377 | }; 378 | NavbarComponent.prototype.searchProblem = function () { 379 | this.router.navigate(['/problems']); 380 | }; 381 | NavbarComponent = __decorate([ 382 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ 383 | selector: 'app-navbar', 384 | template: __webpack_require__("../../../../../src/app/components/navbar/navbar.component.html"), 385 | styles: [__webpack_require__("../../../../../src/app/components/navbar/navbar.component.css")] 386 | }), 387 | __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_3__services_input_service__["a" /* InputService */], 388 | __WEBPACK_IMPORTED_MODULE_2__angular_router__["b" /* Router */]]) 389 | ], NavbarComponent); 390 | return NavbarComponent; 391 | }()); 392 | 393 | 394 | 395 | /***/ }), 396 | 397 | /***/ "../../../../../src/app/components/new-problem/new-problem.component.css": 398 | /***/ (function(module, exports, __webpack_require__) { 399 | 400 | exports = module.exports = __webpack_require__("../../../../css-loader/lib/css-base.js")(false); 401 | // imports 402 | 403 | 404 | // module 405 | exports.push([module.i, "", ""]); 406 | 407 | // exports 408 | 409 | 410 | /*** EXPORTS FROM exports-loader ***/ 411 | module.exports = module.exports.toString(); 412 | 413 | /***/ }), 414 | 415 | /***/ "../../../../../src/app/components/new-problem/new-problem.component.html": 416 | /***/ (function(module, exports) { 417 | 418 | module.exports = "
\n \n
\n
\n \n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n \n
\n
\n
\n
" 419 | 420 | /***/ }), 421 | 422 | /***/ "../../../../../src/app/components/new-problem/new-problem.component.ts": 423 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 424 | 425 | "use strict"; 426 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return NewProblemComponent; }); 427 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 428 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__services_data_service__ = __webpack_require__("../../../../../src/app/services/data.service.ts"); 429 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 430 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 431 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 432 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 433 | return c > 3 && r && Object.defineProperty(target, key, r), r; 434 | }; 435 | var __metadata = (this && this.__metadata) || function (k, v) { 436 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 437 | }; 438 | 439 | 440 | var DEFAULT_PROBLEM = Object.freeze({ 441 | id: 0, 442 | name: '', 443 | desc: '', 444 | difficulty: 'easy' 445 | }); 446 | var NewProblemComponent = /** @class */ (function () { 447 | function NewProblemComponent(dataService) { 448 | this.dataService = dataService; 449 | // create a shadow copy of problem and assign it to newProblem 450 | // Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value. 451 | this.newProblem = Object.assign({}, DEFAULT_PROBLEM); 452 | this.difficulties = ['easy', 'medium', 'hard', 'super']; 453 | } 454 | NewProblemComponent.prototype.ngOnInit = function () { 455 | }; 456 | NewProblemComponent.prototype.addProblem = function () { 457 | this.dataService.addProblem(this.newProblem); 458 | // assign newProblem a new problem instance 459 | // Otherwise newProblem have same reference as the one we added to the list 460 | // then when next time add new problem, it will override the problem we have already add into the problem list. 461 | this.newProblem = Object.assign({}, DEFAULT_PROBLEM); 462 | }; 463 | NewProblemComponent = __decorate([ 464 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ 465 | selector: 'app-new-problem', 466 | template: __webpack_require__("../../../../../src/app/components/new-problem/new-problem.component.html"), 467 | styles: [__webpack_require__("../../../../../src/app/components/new-problem/new-problem.component.css")] 468 | }), 469 | __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_1__services_data_service__["a" /* DataService */]]) 470 | ], NewProblemComponent); 471 | return NewProblemComponent; 472 | }()); 473 | 474 | 475 | 476 | /***/ }), 477 | 478 | /***/ "../../../../../src/app/components/problem-detail/problem-detail.component.css": 479 | /***/ (function(module, exports, __webpack_require__) { 480 | 481 | exports = module.exports = __webpack_require__("../../../../css-loader/lib/css-base.js")(false); 482 | // imports 483 | 484 | 485 | // module 486 | exports.push([module.i, "", ""]); 487 | 488 | // exports 489 | 490 | 491 | /*** EXPORTS FROM exports-loader ***/ 492 | module.exports = module.exports.toString(); 493 | 494 | /***/ }), 495 | 496 | /***/ "../../../../../src/app/components/problem-detail/problem-detail.component.html": 497 | /***/ (function(module, exports) { 498 | 499 | module.exports = "\n
\n
\n
\n

\n {{problem.id}}. {{problem.name}}\n

\n

\n {{problem.desc}}\n

\n
\n
\n
\n \n
\n
" 500 | 501 | /***/ }), 502 | 503 | /***/ "../../../../../src/app/components/problem-detail/problem-detail.component.ts": 504 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 505 | 506 | "use strict"; 507 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ProblemDetailComponent; }); 508 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 509 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__services_data_service__ = __webpack_require__("../../../../../src/app/services/data.service.ts"); 510 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__angular_router__ = __webpack_require__("../../../router/esm5/router.js"); 511 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 512 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 513 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 514 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 515 | return c > 3 && r && Object.defineProperty(target, key, r), r; 516 | }; 517 | var __metadata = (this && this.__metadata) || function (k, v) { 518 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 519 | }; 520 | 521 | 522 | 523 | var ProblemDetailComponent = /** @class */ (function () { 524 | function ProblemDetailComponent(dataService, route) { 525 | this.dataService = dataService; 526 | this.route = route; 527 | } 528 | ProblemDetailComponent.prototype.ngOnInit = function () { 529 | var _this = this; 530 | // subscribe: when params changes, this.problem will be updated 531 | // +: conver string to int 532 | this.route.params.subscribe(function (params) { 533 | _this.dataService.getProblem(+params['id']) 534 | .then(function (problem) { return _this.problem = problem; }); 535 | }); 536 | }; 537 | ProblemDetailComponent = __decorate([ 538 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ 539 | selector: 'app-problem-detail', 540 | template: __webpack_require__("../../../../../src/app/components/problem-detail/problem-detail.component.html"), 541 | styles: [__webpack_require__("../../../../../src/app/components/problem-detail/problem-detail.component.css")] 542 | }), 543 | __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_1__services_data_service__["a" /* DataService */], 544 | __WEBPACK_IMPORTED_MODULE_2__angular_router__["a" /* ActivatedRoute */]]) 545 | ], ProblemDetailComponent); 546 | return ProblemDetailComponent; 547 | }()); 548 | 549 | 550 | 551 | /***/ }), 552 | 553 | /***/ "../../../../../src/app/components/problem-list/problem-list.component.css": 554 | /***/ (function(module, exports, __webpack_require__) { 555 | 556 | exports = module.exports = __webpack_require__("../../../../css-loader/lib/css-base.js")(false); 557 | // imports 558 | 559 | 560 | // module 561 | exports.push([module.i, ".difficulty {\n min-width: 65px;\n margin-right: 10px;\n}\n\n.label.difficulty {\n padding-top: 0.6em;\n color: #fbfdfa;\n font-size: 12px;\n}\n\n.title {\n font-size: 1.2em;\n}\n\n.diff-easy {\n background-color: #42ebf4;\n}\n\n.diff-medium {\n background-color: #92cf5c;\n}\n\n.diff-hard {\n background-color: #dd0d1e;\n}\n\n.diff-super {\n background-color: #8d16e2;\n}", ""]); 562 | 563 | // exports 564 | 565 | 566 | /*** EXPORTS FROM exports-loader ***/ 567 | module.exports = module.exports.toString(); 568 | 569 | /***/ }), 570 | 571 | /***/ "../../../../../src/app/components/problem-list/problem-list.component.html": 572 | /***/ (function(module, exports) { 573 | 574 | module.exports = "\n" 575 | 576 | /***/ }), 577 | 578 | /***/ "../../../../../src/app/components/problem-list/problem-list.component.ts": 579 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 580 | 581 | "use strict"; 582 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ProblemListComponent; }); 583 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 584 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__services_data_service__ = __webpack_require__("../../../../../src/app/services/data.service.ts"); 585 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__services_input_service__ = __webpack_require__("../../../../../src/app/services/input.service.ts"); 586 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 587 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 588 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 589 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 590 | return c > 3 && r && Object.defineProperty(target, key, r), r; 591 | }; 592 | var __metadata = (this && this.__metadata) || function (k, v) { 593 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 594 | }; 595 | 596 | 597 | 598 | var ProblemListComponent = /** @class */ (function () { 599 | function ProblemListComponent(dataService, inputService) { 600 | this.dataService = dataService; 601 | this.inputService = inputService; 602 | // for navbar 603 | this.searchTerm = ''; 604 | } 605 | ProblemListComponent.prototype.ngOnInit = function () { 606 | this.getProblems(); 607 | this.getSearchTerm(); 608 | }; 609 | ProblemListComponent.prototype.ngOnDestroy = function () { 610 | this.subcriptionProblems.unsubscribe(); 611 | }; 612 | ProblemListComponent.prototype.getProblems = function () { 613 | var _this = this; 614 | this.subcriptionProblems = this.dataService.getProblems() 615 | .subscribe(function (problems) { 616 | _this.problems = problems; 617 | }); 618 | }; 619 | ProblemListComponent.prototype.getSearchTerm = function () { 620 | var _this = this; 621 | this.subscriptionInput = this.inputService.getInput() 622 | .subscribe(function (term) { return _this.searchTerm = term; }); 623 | }; 624 | ProblemListComponent = __decorate([ 625 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ 626 | selector: 'app-problem-list', 627 | template: __webpack_require__("../../../../../src/app/components/problem-list/problem-list.component.html"), 628 | styles: [__webpack_require__("../../../../../src/app/components/problem-list/problem-list.component.css")] 629 | }), 630 | __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_1__services_data_service__["a" /* DataService */], 631 | __WEBPACK_IMPORTED_MODULE_2__services_input_service__["a" /* InputService */]]) 632 | ], ProblemListComponent); 633 | return ProblemListComponent; 634 | }()); 635 | 636 | 637 | 638 | /***/ }), 639 | 640 | /***/ "../../../../../src/app/pipes/search.pipe.ts": 641 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 642 | 643 | "use strict"; 644 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SearchPipe; }); 645 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 646 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 647 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 648 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 649 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 650 | return c > 3 && r && Object.defineProperty(target, key, r), r; 651 | }; 652 | 653 | var SearchPipe = /** @class */ (function () { 654 | function SearchPipe() { 655 | } 656 | SearchPipe.prototype.transform = function (problems, term) { 657 | // get filtered problem list 658 | return problems.filter(function (problem) { return problem.name.toLowerCase().includes(term); }); 659 | }; 660 | SearchPipe = __decorate([ 661 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["T" /* Pipe */])({ 662 | name: 'search' 663 | }) 664 | ], SearchPipe); 665 | return SearchPipe; 666 | }()); 667 | 668 | 669 | 670 | /***/ }), 671 | 672 | /***/ "../../../../../src/app/services/collaboration.service.ts": 673 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 674 | 675 | "use strict"; 676 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return CollaborationService; }); 677 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 678 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_rxjs_Subject__ = __webpack_require__("../../../../rxjs/_esm5/Subject.js"); 679 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 680 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 681 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 682 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 683 | return c > 3 && r && Object.defineProperty(target, key, r), r; 684 | }; 685 | var __metadata = (this && this.__metadata) || function (k, v) { 686 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 687 | }; 688 | 689 | 690 | var CollaborationService = /** @class */ (function () { 691 | function CollaborationService() { 692 | this._userSource = new __WEBPACK_IMPORTED_MODULE_1_rxjs_Subject__["a" /* Subject */](); 693 | } 694 | CollaborationService.prototype.init = function (editor, sessionId) { 695 | var _this = this; 696 | // send to server 697 | this.collaborationSocket = io(window.location.origin, { query: 'sessionId=' + sessionId }); 698 | // //wait for 'message' event from server 699 | // this.collaborationSocket.on("message", (message) => { 700 | // console.log('message received from the server: ' + message); 701 | // }) 702 | // handle the changes from server 703 | this.collaborationSocket.on('change', function (delta) { 704 | console.log('collaboration: editor changes by ' + delta); 705 | delta = JSON.parse(delta); 706 | editor.lastAppliedChange = delta; 707 | // apply the changes on editor 708 | editor.getSession().getDocument().applyDeltas([delta]); 709 | }); 710 | // handle user changes 711 | this.collaborationSocket.on('userchange', function (users) { 712 | console.log('user changed: ' + users); 713 | _this._userSource.next(users.toString()); 714 | }); 715 | return this._userSource.asObservable(); 716 | }; 717 | // emit event to make changes and inform server and other collaborators 718 | CollaborationService.prototype.change = function (delta) { 719 | // emit "change" event 720 | this.collaborationSocket.emit('change', delta); 721 | }; 722 | CollaborationService.prototype.restoreBuffer = function () { 723 | // let the server handle the event 724 | this.collaborationSocket.emit('restoreBuffer'); 725 | }; 726 | CollaborationService = __decorate([ 727 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["A" /* Injectable */])(), 728 | __metadata("design:paramtypes", []) 729 | ], CollaborationService); 730 | return CollaborationService; 731 | }()); 732 | 733 | 734 | 735 | /***/ }), 736 | 737 | /***/ "../../../../../src/app/services/data.service.ts": 738 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 739 | 740 | "use strict"; 741 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DataService; }); 742 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 743 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_common_http__ = __webpack_require__("../../../common/esm5/http.js"); 744 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_rxjs_BehaviorSubject__ = __webpack_require__("../../../../rxjs/_esm5/BehaviorSubject.js"); 745 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 746 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 747 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 748 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 749 | return c > 3 && r && Object.defineProperty(target, key, r), r; 750 | }; 751 | var __metadata = (this && this.__metadata) || function (k, v) { 752 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 753 | }; 754 | 755 | 756 | 757 | 758 | var DataService = /** @class */ (function () { 759 | function DataService(httpClient) { 760 | this.httpClient = httpClient; 761 | this._problemSource = new __WEBPACK_IMPORTED_MODULE_2_rxjs_BehaviorSubject__["a" /* BehaviorSubject */]([]); 762 | } 763 | // return a list of problems 764 | DataService.prototype.getProblems = function () { 765 | var _this = this; 766 | this.httpClient.get('api/v1/problems') 767 | .toPromise() 768 | .then(function (res) { 769 | _this._problemSource.next(res); 770 | }) 771 | .catch(this.handleError); 772 | return this._problemSource.asObservable(); 773 | }; 774 | //use subscribe 775 | // getProblems(): Observable { 776 | // this.httpClient.get('api/v1/problems') 777 | // .subscribe((res:any) => this._problemSource.next(res)); 778 | // return this._problemSource.asObservable(); 779 | // } 780 | // return a problem by id 781 | DataService.prototype.getProblem = function (id) { 782 | return this.httpClient.get("api/v1/problems/" + id) 783 | .toPromise() 784 | .then(function (res) { return res; }) 785 | .catch(this.handleError); 786 | }; 787 | // add problem 788 | DataService.prototype.addProblem = function (problem) { 789 | var _this = this; 790 | var options = { headers: new __WEBPACK_IMPORTED_MODULE_1__angular_common_http__["c" /* HttpHeaders */]({ 'Content-Type': 'application/json' }) }; 791 | return this.httpClient.post('api/v1/problems', problem, options) 792 | .toPromise() 793 | .then(function (res) { 794 | _this.getProblems(); 795 | return res; 796 | }) 797 | .catch(this.handleError); 798 | }; 799 | // build and run: POST 800 | DataService.prototype.buildAndRun = function (data) { 801 | var options = { headers: new __WEBPACK_IMPORTED_MODULE_1__angular_common_http__["c" /* HttpHeaders */]({ 'Content-Type': 'application/json' }) }; 802 | return this.httpClient.post('api/v1/build_and_run', data, options) 803 | .toPromise() 804 | .then(function (res) { 805 | console.log(res); 806 | return res; 807 | }) 808 | .catch(this.handleError); 809 | }; 810 | // // modify problem 811 | // editProblem(problem: Problem) { 812 | // const options = {headers: new HttpHeaders({'Content-Type': 'application/json'})}; 813 | // return this.httpClient.post('api/v1/problems', problem, options) 814 | // .toPromise() 815 | // . 816 | // } 817 | // handle errors 818 | DataService.prototype.handleError = function (error) { 819 | console.error('Error reference', error); 820 | return Promise.reject(error.body || error); 821 | }; 822 | DataService = __decorate([ 823 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["A" /* Injectable */])(), 824 | __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_1__angular_common_http__["a" /* HttpClient */]]) 825 | ], DataService); 826 | return DataService; 827 | }()); 828 | 829 | 830 | 831 | /***/ }), 832 | 833 | /***/ "../../../../../src/app/services/input.service.ts": 834 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 835 | 836 | "use strict"; 837 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return InputService; }); 838 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 839 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_rxjs_BehaviorSubject__ = __webpack_require__("../../../../rxjs/_esm5/BehaviorSubject.js"); 840 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 841 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 842 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 843 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 844 | return c > 3 && r && Object.defineProperty(target, key, r), r; 845 | }; 846 | var __metadata = (this && this.__metadata) || function (k, v) { 847 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 848 | }; 849 | 850 | 851 | var InputService = /** @class */ (function () { 852 | function InputService() { 853 | this.inputSubject$ = new __WEBPACK_IMPORTED_MODULE_1_rxjs_BehaviorSubject__["a" /* BehaviorSubject */](''); 854 | } 855 | InputService.prototype.changeInput = function (term) { 856 | this.inputSubject$.next(term); 857 | }; 858 | InputService.prototype.getInput = function () { 859 | return this.inputSubject$.asObservable(); 860 | }; 861 | InputService = __decorate([ 862 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["A" /* Injectable */])(), 863 | __metadata("design:paramtypes", []) 864 | ], InputService); 865 | return InputService; 866 | }()); 867 | 868 | 869 | 870 | /***/ }), 871 | 872 | /***/ "../../../../../src/environments/environment.ts": 873 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 874 | 875 | "use strict"; 876 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return environment; }); 877 | // The file contents for the current environment will overwrite these during build. 878 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 879 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 880 | // The list of which env maps to which file can be found in `.angular-cli.json`. 881 | var environment = { 882 | production: false 883 | }; 884 | 885 | 886 | /***/ }), 887 | 888 | /***/ "../../../../../src/main.ts": 889 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 890 | 891 | "use strict"; 892 | Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); 893 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("../../../core/esm5/core.js"); 894 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__ = __webpack_require__("../../../platform-browser-dynamic/esm5/platform-browser-dynamic.js"); 895 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__app_app_module__ = __webpack_require__("../../../../../src/app/app.module.ts"); 896 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__environments_environment__ = __webpack_require__("../../../../../src/environments/environment.ts"); 897 | 898 | 899 | 900 | 901 | if (__WEBPACK_IMPORTED_MODULE_3__environments_environment__["a" /* environment */].production) { 902 | Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["_13" /* enableProdMode */])(); 903 | } 904 | Object(__WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__["a" /* platformBrowserDynamic */])().bootstrapModule(__WEBPACK_IMPORTED_MODULE_2__app_app_module__["a" /* AppModule */]) 905 | .catch(function (err) { return console.log(err); }); 906 | 907 | 908 | /***/ }), 909 | 910 | /***/ 0: 911 | /***/ (function(module, exports, __webpack_require__) { 912 | 913 | module.exports = __webpack_require__("../../../../../src/main.ts"); 914 | 915 | 916 | /***/ }) 917 | 918 | },[0]); 919 | //# sourceMappingURL=main.bundle.js.map --------------------------------------------------------------------------------