Repository: engineer-man/emkc Branch: develop Commit: 4b7e6c3baba6 Files: 246 Total size: 491.3 KB Directory structure: gitextract_rb6gtnoa/ ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── Dockerfile ├── cdn/ │ └── avatars/ │ └── .gitkeep ├── docker-compose.yml ├── emkc ├── license ├── package.json ├── platform/ │ ├── .babelrc │ ├── api/ │ │ ├── controllers/ │ │ │ ├── AuthController.js │ │ │ ├── ChallengesController.js │ │ │ ├── CommunityController.js │ │ │ ├── ContestsController.js │ │ │ ├── HomeController.js │ │ │ ├── MerchController.js │ │ │ ├── ProfilesController.js │ │ │ ├── ScriptsController.js │ │ │ ├── SnippetsController.js │ │ │ ├── TagsController.js │ │ │ ├── admin/ │ │ │ │ ├── ChallengesController.js │ │ │ │ ├── ContestsController.js │ │ │ │ ├── DashboardController.js │ │ │ │ ├── PistonController.js │ │ │ │ └── UsersController.js │ │ │ └── api/ │ │ │ ├── internal/ │ │ │ │ ├── ChatsController.js │ │ │ │ └── PistonController.js │ │ │ ├── v1/ │ │ │ │ ├── PistonController.js │ │ │ │ ├── UsersController.js │ │ │ │ └── stats/ │ │ │ │ ├── DiscordController.js │ │ │ │ └── PistonController.js │ │ │ └── v2/ │ │ │ └── PistonController.js │ │ ├── policies/ │ │ │ ├── api_internal_auth.js │ │ │ ├── common.js │ │ │ ├── is_admin.js │ │ │ ├── is_prod.js │ │ │ └── logged_in.js │ │ └── services/ │ │ ├── api.js │ │ ├── constant.js │ │ ├── contests.js │ │ ├── discord.js │ │ ├── dispenserd.js │ │ ├── error.js │ │ ├── mailer.js │ │ ├── piston.js │ │ ├── test_cases.js │ │ ├── twig.js │ │ ├── util.js │ │ └── views.js │ ├── config/ │ │ ├── blueprints.js │ │ ├── bootstrap.js │ │ ├── controllers.js │ │ ├── http.js │ │ ├── local.js.sample │ │ ├── paths.js │ │ ├── policies.js │ │ ├── routes.js │ │ ├── session.js │ │ ├── sockets.js │ │ └── views.js │ ├── console/ │ │ ├── common.js │ │ ├── cron.js │ │ └── util.js │ ├── emkc.js │ ├── migrations/ │ │ ├── config.json.sample │ │ └── migrations/ │ │ ├── 20180320123747-initial.sql │ │ ├── 20180901170431-triggers.sql │ │ ├── 20180903004942-display-name.sql │ │ ├── 20180903013450-question-tags.sql │ │ ├── 20180903180404-default-avatar.sql │ │ ├── 20180903222426-views-field.sql │ │ ├── 20180905220531-notification-table.sql │ │ ├── 20180908000333-new-tags.sql │ │ ├── 20180915035412-code-rooms.sql │ │ ├── 20180917013146-snippet-language.sql │ │ ├── 20180930153901-video-requests.sql │ │ ├── 20181005005500-challenges-tables.sql │ │ ├── 20181021204739-chats-table.sql │ │ ├── 20181107035714-new-challenge.sql │ │ ├── 20181111035714-new-challenge.sql │ │ ├── 20181119035714-new-challenge.sql │ │ ├── 20181121035714-discord-rank-field.sql │ │ ├── 20181229135021-new-challenge.sql │ │ ├── 20190104235301-new-challenge.sql │ │ ├── 20190405004828-new-challenge.sql │ │ ├── 20190611224428-new-challenge.sql │ │ ├── 20190622133430-new-challenge.sql │ │ ├── 20190622224428-discord-id-chat-messages.sql │ │ ├── 20190624224428-script-town.sql │ │ ├── 20191023224428-stickers.sql │ │ ├── 20191101133430-new-challenge.sql │ │ ├── 20191201133430-new-challenge.sql │ │ ├── 20200711133430-piston-stats.sql │ │ ├── 20200711133431-piston-stats.sql │ │ ├── 20200802133431-new-challenge.sql │ │ ├── 20200813092823-new-challenge.sql │ │ ├── 20200825133432-new-challenge.sql │ │ ├── 20200830224428-contests-tables.sql │ │ ├── 20200905203703-contest-draft-field.sql │ │ ├── 20200918012206-cleanup-old-tables.sql │ │ ├── 20200918012216-award-table.sql │ │ ├── 20210117125516-add-html-to-challenges.sql │ │ ├── 20210117161957-create-tests-table.sql │ │ ├── 20210220201643-piston-run-changes.sql │ │ ├── 20210314201643-challenge-draft.sql │ │ ├── 20210319145442-add-disallowed-languages.sql │ │ ├── 20210325110214-change-character-set.sql │ │ ├── 20210326154806-add-late-submissions.sql │ │ ├── 20210401114642-add-explanation-field.sql │ │ ├── 20210423100104-add-language-version.sql │ │ ├── 20210714100104-add-best-length.sql │ │ ├── 20210901095201-remove-contest-draft-field.sql │ │ ├── 20220706141314-drop-challenges-folder.sql │ │ └── 20220707092911-drop-official-field.sql │ ├── models/ │ │ ├── awards.js │ │ ├── challenge_tests.js │ │ ├── challenges.js │ │ ├── cli_scripts.js │ │ ├── contest_submissions.js │ │ ├── contests.js │ │ ├── discord_chat_messages.js │ │ ├── index.js │ │ ├── piston_runs.js │ │ ├── snippets.js │ │ ├── sticker_orders.js │ │ ├── tags.js │ │ ├── user_challenges.js │ │ └── users.js │ ├── package.json │ ├── pm2.json │ ├── public/ │ │ ├── css/ │ │ │ └── .gitkeep │ │ ├── js/ │ │ │ └── .gitkeep │ │ ├── lib/ │ │ │ ├── bootbox/ │ │ │ │ └── bootbox.js │ │ │ ├── highlightjs/ │ │ │ │ ├── atom-one-dark.css │ │ │ │ ├── default.css │ │ │ │ ├── highlight-ln.js │ │ │ │ └── highlight.pack.js │ │ │ └── webpack/ │ │ │ └── .gitkeep │ │ └── other/ │ │ └── .gitkeep │ ├── resources/ │ │ ├── challenges/ │ │ │ └── templates/ │ │ │ ├── template.c │ │ │ ├── template.cpp │ │ │ ├── template.cs │ │ │ ├── template.go │ │ │ ├── template.hs │ │ │ ├── template.java │ │ │ ├── template.jl │ │ │ ├── template.js │ │ │ ├── template.kt │ │ │ ├── template.nim │ │ │ ├── template.php │ │ │ ├── template.pl │ │ │ ├── template.py │ │ │ ├── template.rb │ │ │ ├── template.rs │ │ │ ├── template.sh │ │ │ └── template.swift │ │ ├── js/ │ │ │ ├── .gitkeep │ │ │ ├── challenges/ │ │ │ │ └── get_language_version.js │ │ │ ├── common.js │ │ │ ├── snippets/ │ │ │ │ └── delete_snippet.js │ │ │ └── util.js │ │ ├── jsx/ │ │ │ ├── challenges/ │ │ │ │ ├── challenge.jsx │ │ │ │ └── manage_challenge.jsx │ │ │ ├── cli_script.jsx │ │ │ ├── contests/ │ │ │ │ ├── contest.jsx │ │ │ │ ├── description.jsx │ │ │ │ └── manage.jsx │ │ │ ├── login.jsx │ │ │ ├── manage_snippet.jsx │ │ │ ├── mobile_nav.jsx │ │ │ ├── ppman.jsx │ │ │ ├── stickers.jsx │ │ │ └── users.jsx │ │ ├── less/ │ │ │ ├── bootstrap.less │ │ │ ├── colors.less │ │ │ ├── em/ │ │ │ │ ├── challenge.less │ │ │ │ ├── challenge_abstract.less │ │ │ │ ├── challenge_manage.less │ │ │ │ ├── challenges_list.less │ │ │ │ ├── common_content.less │ │ │ │ ├── community_map.less │ │ │ │ ├── container.less │ │ │ │ ├── contests/ │ │ │ │ │ ├── contest.less │ │ │ │ │ ├── home.less │ │ │ │ │ └── manage.less │ │ │ │ ├── footer.less │ │ │ │ ├── language_choice.less │ │ │ │ ├── login.less │ │ │ │ ├── manage_snippet.less │ │ │ │ ├── menu.less │ │ │ │ ├── mobile_nav.less │ │ │ │ ├── power_system.less │ │ │ │ ├── profile.less │ │ │ │ ├── staff_container.less │ │ │ │ ├── stickers.less │ │ │ │ └── top_members.less │ │ │ ├── global.less │ │ │ ├── highlightjs.less │ │ │ └── quill.less │ │ ├── main.js │ │ ├── monaco.js │ │ └── twig/ │ │ └── filters.js │ ├── start │ ├── views/ │ │ ├── _emails/ │ │ │ └── new_user.twig │ │ ├── admin/ │ │ │ ├── challenges/ │ │ │ │ ├── update.twig │ │ │ │ └── view_all.twig │ │ │ ├── contests/ │ │ │ │ ├── update.twig │ │ │ │ └── view_all.twig │ │ │ ├── dashboard/ │ │ │ │ └── dashboard.twig │ │ │ ├── piston/ │ │ │ │ └── view_all.twig │ │ │ └── users/ │ │ │ └── view_all.twig │ │ ├── challenges/ │ │ │ ├── challenge.twig │ │ │ ├── choose_language.twig │ │ │ └── home.twig │ │ ├── community/ │ │ │ ├── about.twig │ │ │ ├── home.twig │ │ │ └── power.twig │ │ ├── contests/ │ │ │ ├── contest.twig │ │ │ └── home.twig │ │ ├── home/ │ │ │ ├── fourohfour.twig │ │ │ ├── home.twig │ │ │ ├── login.twig │ │ │ └── privacy.twig │ │ ├── master.twig │ │ ├── merch/ │ │ │ └── stickers.twig │ │ ├── profiles/ │ │ │ └── view.twig │ │ ├── scripts/ │ │ │ ├── home.twig │ │ │ └── view.twig │ │ └── snippets/ │ │ ├── edit.twig │ │ └── mine.twig │ └── webpack.config.js ├── readme.md └── var/ ├── 502/ │ └── 502.html ├── artwork/ │ └── logicons/ │ └── ignore.afdesign ├── docker/ │ ├── clean │ ├── config/ │ │ └── mysqld.cnf │ ├── init/ │ │ └── db.sql │ ├── logs/ │ │ └── .gitkeep │ ├── mysql/ │ │ └── .gitkeep │ └── redis/ │ └── .gitkeep ├── felix/ │ └── 404felix.psd ├── text/ │ └── a.txt └── tmp/ ├── .gitkeep ├── scripts.sql ├── stats.sql └── vids.sql ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ platform/config/local.js platform/migrations/config.json platform/public/css/*.css platform/public/lib/webpack/* !platform/public/lib/webpack/.gitkeep cdn/avatars/* !cdn/avatars/.gitkeep var/docker/mysql/* !var/docker/mysql/.gitkeep var/docker/redis/* !var/docker/redis/.gitkeep var/docker/logs/* !var/docker/logs/.gitkeep node_modules package-lock.json .env .DS_STORE .vscode ================================================ FILE: .prettierignore ================================================ platform/config/local.js platform/migrations/config.json platform/public/css/*.css platform/public/lib platform/resources/challenges/templates cdn/avatars/* var/ node_modules package-lock.json .env .DS_STORE .vscode ================================================ FILE: .prettierrc.json ================================================ { "tabWidth": 4, "singleQuote": true, "trailingComma": "none" } ================================================ FILE: Dockerfile ================================================ FROM node:14.3.0-stretch RUN apt update && apt install -y inotify-tools libjson-c-dev RUN cd /opt && \ wget https://github.com/realtux/rmig/releases/download/0.0.3/rmig-0.0.3-linux && \ chmod +x rmig-0.0.3-linux && \ ln -s /opt/rmig-0.0.3-linux /usr/bin/rmig WORKDIR /opt/emkc/platform CMD ./start ================================================ FILE: cdn/avatars/.gitkeep ================================================ ================================================ FILE: docker-compose.yml ================================================ version: '3' services: emkc: container_name: emkc build: . ports: - '2005:2727' volumes: - ./:/opt/emkc environment: APPENV: '${APPENV}' restart: always depends_on: - redis - mysql redis: container_name: emkc_redis image: redis:3.2.12 volumes: - ./:/opt/emkc - ./var/docker/redis:/data restart: always mysql: container_name: emkc_mysql image: mysql:8 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: emkc command: --init-file /var/lib/init/db.sql volumes: - ./:/opt/emkc - ./var/docker/mysql:/var/lib/mysql - ./var/docker/init:/var/lib/init - ./var/docker/config:/etc/mysql/conf.d restart: always ================================================ FILE: emkc ================================================ #!/usr/bin/env bash function init_files { chmod 0444 var/docker/config/mysqld.cnf } case $* in init ) cp -n platform/config/local.js.sample platform/config/local.js cp -n platform/migrations/config.json.sample platform/migrations/config.json init_files docker-compose build docker-compose run --rm --no-deps emkc bash -c 'cd /opt/emkc/platform; npm install' ;; deploy ) git pull docker-compose run --rm --no-deps emkc bash -c 'cd /opt/emkc/platform; npm install' docker-compose down docker-compose run --rm emkc bash -c 'cd /opt/emkc/platform/migrations; rmig migrate' init_files docker-compose up -d ;; start ) init_files docker-compose up -d ;; stop ) docker-compose down ;; restart ) docker-compose restart ;; shell ) docker exec -it emkc /bin/bash ;; rebuild ) docker-compose build ;; npm ) docker-compose run --rm --no-deps emkc bash -c 'cd /opt/emkc/platform; npm install' ;; cron* ) docker-compose exec emkc bash -c "/opt/emkc/platform/console/cron.js $2" ;; mysql ) docker exec -it emkc_mysql bash -c 'mysql -hmysql -uroot -proot -Demkc' ;; rmig* ) docker exec -it emkc bash -c "cd /opt/emkc/platform/migrations; $*" ;; tail ) docker-compose logs -f ;; "" ) echo 'emkc control, usage: emkc [command]' echo '' echo 'init initialize env specific config files' echo 'start start the emkc docker container' echo 'stop stop the emkc docker container' echo 'restart restart the docker containers' echo 'shell start a shell in the docker container' echo 'rebuild rebuild emkc from scratch' echo 'npm update node modules' echo 'mysql login to mysql' echo 'rmig status show the status of migrations' echo 'rmig migrate run the pending database migrations' echo 'rmig rollback rollback one database migration' echo 'tail watch app and db logs' exit 1 esac ================================================ FILE: license ================================================ Copyright (c) 2018-2019 Brian Seymour, EMKC Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: package.json ================================================ { "scripts": { "lint": "prettier --write .", "check-lint": "prettier --check ." }, "devDependencies": { "prettier": "2.7.1" } } ================================================ FILE: platform/.babelrc ================================================ { "presets": ["@babel/preset-env", "@babel/preset-react"], "plugins": [ "@babel/plugin-proposal-object-rest-spread", "@babel/plugin-proposal-class-properties", "@babel/plugin-transform-async-to-generator" ] } ================================================ FILE: platform/api/controllers/AuthController.js ================================================ const fs = require('fs'); const request = require('request-promise'); module.exports = { discord(req, res) { // handle the redirect if one was passed with the login operation if (req.query.r) { req.session.redirect = req.query.r; } else { delete req.session.redirect; } return res.redirect( 'https://discord.com/api/v10/oauth2/authorize' + '?client_id=' + sails.config.discord.client_id + '&redirect_uri=' + encode_uri_component(constant.base_url + '/auth/discord_cb') + '&response_type=code' + '&scope=identify%20email' ); }, async discord_cb(req, res) { let code = req.query.code; try { // get an access token from the code returned from the authorization phase let auth_result = await request({ method: 'post', url: 'https://discord.com/api/v10/oauth2/token', headers: { 'content-type': 'application/x-www-form-urlencoded' }, form: { code, client_id: sails.config.discord.client_id, client_secret: sails.config.discord.client_secret, grant_type: 'authorization_code', redirect_uri: constant.base_url + '/auth/discord_cb', scope: 'identify email' }, json: true, simple: true }); // use the returned token to get the data of the user who just logged in let discord_user = await request({ method: 'get', url: 'https://discord.com/api/v10/users/@me', headers: { Authorization: 'Bearer ' + auth_result.access_token }, json: true, simple: true }); // add a new user record if there is not already one matching the given api id let [user, created] = await db.users.find_or_create({ where: { discord_api: discord_user.id }, defaults: { display_name: discord_user.username, email: discord_user.email || null } }); // if this is a new account, sort out what they're username should be // usernames must be letter, numbers, underscores, and dashes only // default username is new_guy and then a number which increases until one isn't used if (created) { let username = discord_user.username; let ext = null; username = username.replace(/[^0-9A-Za-z_\-]+/gi, ''); if (username === '') username = 'new_guy'; // make sure username is unique for (;;) { let dupe = await db.users.find_one({ where: { user_id: { [$ne]: user.user_id }, username: username + (ext === null ? '' : ext) } }); if (!dupe) break; ext = ext === null ? 0 : ++ext; } // save the new username user.username = username + (ext === null ? '' : ext); await user.save(); } if (user.display_name !== discord_user.username) { user.display_name = discord_user.username; await user.save(); } // download discord avatar request({ method: 'get', url: 'https://cdn.discordapp.com/avatars/' + discord_user.id + '/' + discord_user.avatar + '.png', simple: true, encoding: null }) .then((res) => { fs.write_file( root_dir + '/cdn/avatars/' + user.user_id + '.png', res, () => {} ); user.avatar_url = '/avatars/' + user.user_id + '.png'; user.save(); }) .catch((err) => {}); // this logs the user in basically req.session.user_id = user.user_id; // add the emkc member role on discord discord.api( 'put', `/guilds/${constant.server_id}/members/${user.discord_api}/roles/${constant.roles.emkc_member}` ); // according to whether or not the redirect was supplied, either go to that url or to board main if (req.session.redirect) { return res.redirect(req.session.redirect); delete req.session.redirect; } else { return res.redirect('/'); } } catch (e) { return res.redirect('/'); } } }; ================================================ FILE: platform/api/controllers/ChallengesController.js ================================================ const fs = require('fs'); const util = require('util'); module.exports = { async home(req, res) { let options = { where: { draft: 0 }, include: [ { required: false, model: db.user_challenges, as: 'solution', where: { user_id: req.local.user_id } } ], order: [['challenge_id']], group: 'challenge_id' }; options.where.difficulty = constant.challenges.difficulty.easy; let easy = await db.challenges.find_all(options); options.where.difficulty = constant.challenges.difficulty.medium; let medium = await db.challenges.find_all(options); options.where.difficulty = constant.challenges.difficulty.hard; let hard = await db.challenges.find_all(options); return res.view({ easy, medium, hard }); }, async choose_language(req, res) { const { challenge_id } = req.params; let challenge = await db.challenges.find_one({ where: { challenge_id }, include: [ { required: false, user_id: req.local.user_id, model: db.user_challenges, as: 'solutions', where: { user_id: req.local.user_id } } ] }); if (!challenge) { return res.redirect('back'); } return res.view({ challenge, solved: challenge.solutions.map((s) => s.language) }); }, async challenge(req, res) { const { challenge_id, language } = req.params; if (!~constant.challenges.supported_languages.index_of(language)) { return res.redirect('back'); } let challenge = await db.challenges.find_one({ where: { challenge_id }, include: [ { required: false, model: db.user_challenges, as: 'solution', where: { user_id: req.local.user_id, language } }, { required: false, model: db.challenge_tests, as: 'tests' } ] }); if (!challenge || challenge.tests.length === 0) { return res.redirect('back'); } // unpack challenge assets const read_file = util.promisify(fs.read_file); const base_dir = root_dir + '/platform/resources/challenges'; const ext = { js: 'js', python: 'py', go: 'go', c: 'c', ruby: 'rb', cpp: 'cpp', cs: 'cs', php: 'php', swift: 'swift', java: 'java', rust: 'rs', julia: 'jl', bash: 'sh', perl: 'pl', kotlin: 'kt', haskell: 'hs', nim: 'nim' }[language]; const abstract = challenge.html; let base_template = await read_file( base_dir + '/templates/template.' + ext ); let template = ''; base_template = base_template.to_string().split('\n'); for (const line of base_template) { // non processed line, add directly if (!line.match(/^\s*%%/gi)) { template += line + '\n'; continue; } // parse the input according to rules and return the first to determine template types const { inputs } = test_cases.get_inputs_and_outputs( challenge.tests[0] ); let parsed_inputs = inputs.map((test_case) => { return test_case.map((value) => { if (value.match(/^[0-9]+$/)) { return parse_int(value); } if (value.match(/^[0-9]+\.[0-9]+$/)) { return parse_float(value); } return value; }); })[0]; if (line.match(/^\s*%%_IMPORTS_%%/gi)) { let has_string = parsed_inputs.some( (input) => typeof input === 'string' ); let has_int = parsed_inputs.some( (input) => typeof input === 'number' ); switch (language) { case 'go': if (has_int) template += ' "strconv"\n'; break; case 'nim': if (has_int) template += 'import os, parseutils'; else template += 'import os'; template += '\n\n'; break; } continue; } parsed_inputs.for_each((input, i) => { ++i; switch (language) { case 'c': if (typeof input === 'string') template += ` char value${i}[128]; strcpy(value${i}, argv[${i}]);`; if (typeof input === 'number') template += ` int value${i} = atoi(argv[${i}]);`; break; case 'cpp': if (typeof input === 'string') template += ` std::string value${i} = argv[${i}];`; if (typeof input === 'number') template += ` int value${i} = std::atoi(argv[${i}]);`; break; case 'cs': if (typeof input === 'string') template += ` string value${i} = args[${ i - 1 }];`; if (typeof input === 'number') template += ` int value${i} = Convert.ToInt32(args[${ i - 1 }]);`; break; case 'go': if (typeof input === 'string') template += ` var value${i} string = os.Args[${i}]`; if (typeof input === 'number') template += ` value${i}, _ := strconv.Atoi(os.Args[${i}])`; break; case 'java': if (typeof input === 'string') template += ` String value${i} = args[${ i - 1 }];`; if (typeof input === 'number') template += ` int value${i} = Integer.parseInt(args[${ i - 1 }]);`; break; case 'kotlin': if (typeof input === 'string') template += ` val value${i} = args[${i - 1}]`; if (typeof input === 'number') template += ` val value${i} = args[${ i - 1 }].toInt()`; break; case 'haskell': template += ` let value${i} = (args !! ${i - 1})`; break; case 'rust': if (typeof input === 'string') template += ` let value${i}: &String = &args[${i}];`; if (typeof input === 'number') template += ` let value${i}: i32 = args[${i}].parse().unwrap();`; break; case 'js': if (typeof input === 'string') template += `const value${i} = process.argv[${ i + 1 }];`; if (typeof input === 'number') template += `const value${i} = parseInt(process.argv[${ i + 1 }]);`; break; case 'php': template += `$value${i} = $argv[${i}];`; break; case 'python': if (typeof input === 'string') template += `value${i} = sys.argv[${i}]`; if (typeof input === 'number') template += `value${i} = int(sys.argv[${i}])`; break; case 'ruby': template += `value${i} = ARGV[${i - 1}]`; break; case 'swift': template += `var value${i} = CommandLine.arguments[${i}]`; break; case 'julia': if (typeof input === 'string') template += `value${i} = ARGS[${i}]`; if (typeof input === 'number') template += `value${i} = parse(Int, ARGS[${i}])`; break; case 'bash': template += `value${i}=$${i}`; break; case 'perl': template += `my $value${i} = $ARGV[${i - 1}];`; break; case 'nim': if (typeof input === 'number') { template += `var value${i}: int\n`; template += `discard parseInt(paramStr(${i}), value${i})`; } else { template += `var value${i} = paramStr(${i})`; } break; } template += '\n'; }); } template = template.trim() + '\n'; return res.view({ solved: !!challenge.solution, challenge, language, abstract, template, monaco_language: { js: 'javascript', python: 'python', go: 'go', c: 'c', ruby: 'ruby', cpp: 'cpp', cs: 'csharp', php: 'php', swift: 'swift', java: 'java', rust: 'rust', julia: 'julia', bash: 'shell', perl: 'perl', kotlin: 'kotlin', haskell: 'haskell', nim: 'nim' }[language] }); }, async execute(req, res) { const { challenge_id } = req.params; const { language, source } = req.body; let challenge = await db.challenges.find_one({ where: { challenge_id }, include: { required: false, model: db.challenge_tests, as: 'tests' } }); if (challenge.tests.length === 0) { return res.status(400).send(); } const results = []; for (const test of challenge.tests) { const { inputs, outputs } = test_cases.get_inputs_and_outputs(test); let test_idx = Math.floor(Math.random() * inputs.length); let result = await piston.execute( language, source, inputs[test_idx], '', '*' ); const compile_output = result.compile && result.compile.output; const run_error = result.run.stderr; const run_output = result.run.stdout.trim(); results.push({ name: test.name, passed: run_output === outputs[test_idx], input: inputs[test_idx], expected: outputs[test_idx], actual: run_output, compile_output, run_error }); } const passed = results.filter((r) => !r.passed).length === 0; if (passed && req.local.user_id && !challenge.draft) { set_immediate(async () => { let [user_challenge, created] = await db.user_challenges.find_or_create({ where: { user_id: req.local.user_id, challenge_id: challenge.challenge_id, language }, defaults: { solution: source } }); if (created) { return null; } user_challenge.solution = source; user_challenge.save(); }); } return res.status(200).send(results); }, async view_other(req, res) { const { username, challenge_id, language } = req.params; let user = await db.users.find_one({ where: { username } }); if (!user) throw null; let user_solution = await db.user_challenges.find_one({ where: { user_id: req.local.user_id, challenge_id, language } }); if (!user_solution) { return res.redirect('back'); } let challenge = await db.user_challenges.find_one({ where: { user_id: user.user_id, challenge_id, language }, include: [ { model: db.challenges, as: 'challenge' } ], order: [['created_at', 'desc']] }); if (challenge) { return res.view('snippets/edit', { snippet: { language, snip: challenge.solution }, mode: 'view' }); } return res.redirect('/snippets'); } }; ================================================ FILE: platform/api/controllers/CommunityController.js ================================================ module.exports = { home(req, res) { return res.view(); }, about(req, res) { return res.view(); }, power(req, res) { return res.view(); } }; ================================================ FILE: platform/api/controllers/ContestsController.js ================================================ const moment = require('moment'); module.exports = { async home(req, res) { let past_contests = await db.contests.find_all({ where: { end_date: { [$lt]: util.now() } }, order: [['end_date', 'desc']] }); let past_submissions = await db.contest_submissions.find_all({ where: { contest_id: past_contests.map((contest) => contest.contest_id) }, attributes: ['contest_id'], include: [ { model: db.users, as: 'user', attributes: ['avatar_url'] } ] }); let submission_map = {}; for (const submission of past_submissions) { if (!submission_map[submission.contest_id]) { submission_map[submission.contest_id] = []; } submission_map[submission.contest_id].push( submission.user.avatar_url ); } for (const contest of past_contests) { contest.solutions = submission_map[contest.contest_id] ? submission_map[contest.contest_id].length : 0; contest.participants = [ ...new Set(submission_map[contest.contest_id] || []) ]; } let active_contests = await db.contests.find_all({ where: { start_date: { [$lte]: util.now() }, end_date: { [$gte]: util.now() } }, include: [ { model: db.contest_submissions, as: 'submissions', include: [ { model: db.users, as: 'user' } ] } ], order: [ ['end_date', 'desc'], [ { model: db.contest_submissions, as: 'submissions' }, 'created_at' ] ] }); return res.view({ past_contests, active_contests }); }, async contest(req, res) { const { contest_id, slug } = req.params; let contest = await db.contests.find_one({ where: { contest_id }, include: [ { model: db.contest_submissions, as: 'submissions', attributes: [ 'contest_submission_id', 'user_id', 'language', 'language_version', 'solution', 'length', 'explanation', 'created_at', 'late' ], include: [ { model: db.users, as: 'user', attributes: ['username', 'avatar_url'] } ] } ], order: [ [ { model: db.contest_submissions, as: 'submissions' }, 'length' ], [ { model: db.contest_submissions, as: 'submissions' }, 'created_at' ] ] }); if (!contest || slug !== contest.slug) { return res.redirect('/contests'); } let awarded_languages = []; let awarded_users = []; let top = 1; let cases = contests.get_cases(contest, true); contest.submissions.for_each((submission, i) => { // overall awards for top 3 solutions submitted by unique users if ( !submission.late && !awarded_users.includes(submission.user_id) && top <= 3 ) { switch (top) { case 1: submission.dataValues.overall_first = true; break; case 2: submission.dataValues.overall_second = true; break; case 3: submission.dataValues.overall_third = true; break; } awarded_users.push(submission.user_id); ++top; } // per language awards for top solution in each language if ( !submission.late && !awarded_languages.includes(submission.language) ) { submission.dataValues.language_first = true; awarded_languages.push(submission.language); } // hide the solution in the payload to prevent cheating if (contest.active) { delete submission.dataValues.explanation; delete submission.dataValues.solution; } }); let submissions = await db.contest_submissions.find_all({ where: { contest_id, user_id: req.local.user_id } }); return res.view({ contest, cases, submissions }); }, async submit(req, res) { let { contest_id, language, solution, explanation, language_version } = req.body; explanation = explanation || ''; solution = solution.trim(); let contest = await db.contests.find_one({ where: { contest_id } }); let test_cases = contests.get_cases(contest); if (test_cases.length === 0) { return res.status(400).send({ message: 'No test cases exit for this contest, please contact an administrator' }); } let languages = await piston.runtimes(); languages = languages.filter((lang) => lang.language === language); // To prevent submissions by alias if ( constant.contests.disallowed_languages.includes(language) || !languages.length ) { return res.status(400).send({ message: 'An error has occurred while submitting your solution' }); } let is_valid = await contests.validate_submission( test_cases, solution, language, language_version ); if (!is_valid) { return res.status(200).send({ passed: false }); } if (moment().isBefore(contest.start_date)) { // Don't save solution for upcoming contests return res.status(200).send({ passed: true }); } let submission = await db.contest_submissions.find_one({ where: { contest_id, language, user_id: req.local.user_id, late: contest.active ? 0 : 1 } }); let solution_bytes = new TextEncoder().encode(solution).length; if (submission) { submission.language = language; submission.solution = solution; submission.length = solution_bytes; submission.explanation = explanation; submission.language_version = language_version; let prev_length = submission.previous('length'); let prev_length_best = submission.previous('length_best'); if (submission.length < prev_length_best) { submission.length_best = solution_bytes; submission.created_at = util.now(); } if (submission.length < prev_length && contest.active) { discord .api( 'post', `/channels/${constant.channels.emkc}/messages`, { embeds: [ { title: contest.name, description: `Can you do better than this? ` + `[Click here](${constant.base_url}${contest.url}) to give it a try.`, type: 'rich', color: 0x84e47f, timestamp: moment().toISOString(), url: `${constant.base_url}${contest.url}`, author: { name: `${req.local.user.display_name} updated their ${submission.language} ${submission.language_version} solution ` + `with one that is ${submission.length} bytes large ` + `(a ${ prev_length - submission.length } byte improvement)` }, footer: { icon_url: constant.cdn_url + req.local.user.avatar_url, text: `updated by ${req.local.user.display_name}` } } ] } ) .catch((err) => {}); } await submission.save(); } else { submission = await db.contest_submissions.create({ user_id: req.local.user_id, contest_id, language, language_version, solution, length: solution_bytes, length_best: solution_bytes, explanation, late: !contest.active }); if (contest.active) { discord .api( 'post', `/channels/${constant.channels.emkc}/messages`, { embeds: [ { title: contest.name, description: `Can you make a better solution? ` + `[Click here](${constant.base_url}${contest.url}) to give it a try.`, type: 'rich', color: 0x84e47f, timestamp: moment().toISOString(), url: `${constant.base_url}${contest.url}`, author: { name: `${req.local.user.display_name} submitted an initial ${submission.length} ` + `byte solution with ${submission.language} ${submission.language_version}` }, footer: { icon_url: constant.cdn_url + req.local.user.avatar_url, text: `submitted by ${req.local.user.display_name}` } } ] } ) .catch((err) => {}); } } return res.status(200).send({ passed: true }); }, async disallowed_languages(req, res) { let { contest_id } = req.params; let contest = await db.contests.find_one({ where: { contest_id } }); let disallowed_languages = contest.disallowed_languages ? contest.disallowed_languages.split(',') : []; return res.status(200).send(disallowed_languages); } }; ================================================ FILE: platform/api/controllers/HomeController.js ================================================ module.exports = { async home(req, res) { let users = await db.users.find_all({ order: [['score', 'desc'], ['user_id']], limit: 100 }); return res.view({ users }); }, privacy(req, res) { return res.view(); }, login() { return res.view(); }, async logout_as(req, res) { if (!req.session.old_id) { // Logging back from nothing return res.view('home/fourohfour'); } req.session.user_id = req.session.old_id; delete req.session.old_id; return res.redirect('/'); }, logout(req, res) { delete req.session.user_id; return res.redirect('back'); }, fourohfour(req, res) { return res.status(404).view('home/fourohfour'); } }; ================================================ FILE: platform/api/controllers/MerchController.js ================================================ const moment = require('moment'); module.exports = { stickers(req, res) { return res.view({ options: [ { quantity: 2, cost: 'FREE' }, { quantity: 3, cost: '2.40' }, { quantity: 5, cost: '3.50' }, { quantity: 10, cost: '6.00' } ] }); }, async order_stickers(req, res) { const { tx, quantity, name, email, address, coupon } = req.body; if (!coupon && !tx) { return res.status(400).send(); } let order = await db.sticker_orders.create({ tx, coupon, quantity, cost: { 2: null, 3: 2.4, 5: 3.5, 10: 6.0 }[quantity], name, email, address, created_at: moment() }); return res.status(200).send({ order_id: order.sticker_order_id }); }, check_code(req, res) { return res.status(200).send({ valid: req.params.code.to_upper_case() === sails.config.paypal.coupon }); } }; ================================================ FILE: platform/api/controllers/ProfilesController.js ================================================ module.exports = { async view(req, res) { const username = req.params.username; let user = await db.users.find_one({ where: { username } }); if (!user) { return res.redirect('/'); } let stat_challenges = await db.challenges.find_all({ include: [ { model: db.user_challenges, as: 'solutions', where: { user_id: user.user_id } } ] }); let stat_contests = await db.contests.find_all({ include: [ { model: db.contest_submissions, as: 'submissions', where: { user_id: user.user_id } } ] }); let awards = await db.awards.find_all({ where: { user_id: user.user_id }, order: [['type']] }); awards = awards.reduce((a, c) => { let entry = a.find((e) => e.type === c.type); if (entry) { ++entry.count; } else { a.push({ type: c.type, count: 1, tooltip_text: c.tooltip_text }); } return a; }, []); let challenges = await db.user_challenges.find_all({ where: { user_id: user.user_id }, include: [ { model: db.challenges, as: 'challenge' } ], order: [['created_at', 'desc']], limit: 5 }); let user_solved_challenges = await db.user_challenges.find_all({ where: { user_id: req.local.user_id }, include: [ { model: db.challenges, as: 'challenge' } ], order: [['created_at', 'desc']] }); return res.view({ user, stat_challenges: stat_challenges.length, stat_contests: stat_contests.length, awards, challenges, user_solved_challenges: user_solved_challenges.map((challenge) => { return { challenge_id: challenge.challenge_id, language: challenge.language }; }) }); } }; ================================================ FILE: platform/api/controllers/ScriptsController.js ================================================ module.exports = { async home(req, res) { let scripts = await db.cli_scripts.find_all({ where: { is_safe: constant.yes } }); return res.view({ scripts }); }, async view(req, res) { const cli_script_id = req.params.cli_script_id; let script = await db.cli_scripts.find_one({ where: { cli_script_id } }); return res.view({ script }); }, async exec(req, res) { const cli_script_id = req.params.cli_script_id; let script = await db.cli_scripts.find_one({ where: { cli_script_id } }); res.set('content-type', 'text/plain'); return res.status(200).send(script.content); } }; ================================================ FILE: platform/api/controllers/SnippetsController.js ================================================ module.exports = { async view(req, res) { const { hash } = req.params; let snippet = await db.snippets.find_one({ where: { hash } }); try { if (!snippet) { throw null; } if ( req.headers.accept === 'text/plain' || req.path.match(/\/raw$/) ) { res.set('content-type', 'text/plain'); return res.status(200).send(snippet.snip); } if (req.headers.accept === 'application/json') { return res.status(200).send(snippet); } return res.view('snippets/edit', { mode: 'view', snippet }); } catch (e) { return res.redirect('/snippets'); } }, async mine(req, res) { let snippets = await db.snippets.find_all({ where: { user_id: req.local.user_id }, order: [['snippet_id', 'desc']] }); return res.view({ snippets }); }, async create(req, res) { if (req.method === 'POST') { const { language, snip } = req.body; try { if (!snip) { throw new Error('Please supply some code'); } let snippet = await db.snippets.create({ user_id: req.local.user_id, language, snip }); return res.status(200).send({ url: snippet.url }); } catch (e) { return res.status(400).send({ message: e.message }); } } return res.view('snippets/edit', { mode: 'create', snippet: { language: '', snip: '', hash: '' } }); }, async delete(req, res) { const { hash } = req.params; let snippet = await db.snippets.find_one({ where: { hash, user_id: req.local.user_id } }); if (snippet) { await snippet.destroy(); } return res.status(snippet ? 200 : 400).send({ url: '/snippets/mine' }); }, async edit(req, res) { const { hash } = req.params; let snippet = await db.snippets.find_one({ where: { hash, user_id: req.local.user_id } }); if (req.method === 'POST') { const { language, snip } = req.body; try { if (!snippet) { return res.status(400).send({ url: '/snippets' }); } if (!snip) { throw new Error('Please supply some code'); } snippet.language = language; snippet.snip = snip; await snippet.save(); return res.status(200).send({ url: snippet.url }); } catch (e) { return res.status(400).send({ message: e.message }); } } if (!snippet) { return res.redirect('/snippets'); } return res.view({ mode: 'update', snippet }); } }; ================================================ FILE: platform/api/controllers/TagsController.js ================================================ module.exports = { async search(req, res) { const name = req.query.name; let tags = await db.tags.find_all({ where: { name: { [$like]: '%' + name + '%' } }, order: [['name']], limit: 10 }); return res.send({ status: 'ok', payload: { tags: name ? tags : [] } }); } }; ================================================ FILE: platform/api/controllers/admin/ChallengesController.js ================================================ const create_tests = async (tests) => { for (const test of tests) { const { challenge_id, name, input, output } = test; await db.challenge_tests.create({ challenge_id, name, input, output }); } }; const unify_tests_challenge_id = (tests, challenge_id) => { for (const test of tests) { test.challenge_id = challenge_id; } }; const find_invalid_test = (tests) => { for (const test of tests) { if (!test_cases.are_valid(test)) { return test; } } return null; }; const get_tests_errors = (tests) => { if (tests.length === 0) { return 'The challenge tests can not be empty'; } const invalid_test = find_invalid_test(tests); if (invalid_test !== null) { return `Invalid test cases in ${invalid_test.name} test`; } return null; }; module.exports = { async view_all(req, res) { let challenges = await db.challenges.find_all({ order: [['challenge_id', 'desc']] }); return res.view({ challenges }); }, async create(req, res) { if (req.method === 'POST') { try { const { draft, difficulty, points, name, description, html, tests } = req.body; const created_challenge = await db.challenges.create({ draft, difficulty, points, name, description, html }); unify_tests_challenge_id(tests, created_challenge.challenge_id); const error_message = get_tests_errors(tests); if (error_message !== null) { await created_challenge.destroy(); return res.status(400).send({ message: error_message }); } create_tests(tests); return res.status(200).send(); } catch (e) { return res.status(400).send(); } } return res.view('admin/challenges/update', { mode: 'create', challenge: { difficulty: 1, draft: true, points: 10, name: '', description: '', html: '', tests: [] } }); }, async update(req, res) { const { challenge_id } = req.params; let existing_challenge = await db.challenges.find_one({ where: { challenge_id }, include: [ { required: false, model: db.challenge_tests, as: 'tests' } ] }); if (!existing_challenge) { return res.redirect('back'); } if (req.method === 'POST') { const { draft, difficulty, points, name, description, html, tests } = req.body; const challenge = { draft, difficulty, points, name, description, html }; for (const attr in challenge) { existing_challenge[attr] = challenge[attr]; } try { unify_tests_challenge_id( tests, existing_challenge.challenge_id ); const error_message = get_tests_errors(tests); if (error_message !== null) { return res.status(400).send({ message: error_message }); } await existing_challenge.save(); await db.challenge_tests.destroy({ where: { challenge_id: existing_challenge.challenge_id } }); create_tests(tests); return res.status(200).send(); } catch (e) { return res.status(400).send(); } } return res.view({ mode: 'update', challenge: existing_challenge }); } }; ================================================ FILE: platform/api/controllers/admin/ContestsController.js ================================================ const moment = require('moment'); module.exports = { async view_all(req, res) { let all_contests = await db.contests.find_all({ order: [['contest_id', 'desc']] }); return res.view({ contests: all_contests }); }, async create(req, res) { if (req.method === 'POST') { const { name, description, start_date, end_date, input, output, disallowed_languages } = req.body; if (!test_cases.are_valid({ input, output })) { return res.status(400).send({ message: 'Invalid test cases' }); } await db.contests.create({ name, description, start_date, end_date, input, output, disallowed_languages }); return res.status(200).send(); } let disallowed_languages = constant.contests.disallowed_languages.join(','); return res.view('admin/contests/update', { mode: 'create', contest: { name: '', description: '', start_date: moment() .startOf('isoweek') .add(6, 'days') .format('YYYY-MM-DD 17:00:00'), end_date: moment() .startOf('isoweek') .add(9, 'days') .format('YYYY-MM-DD 17:00:00'), input: '', output: '', disallowed_languages } }); }, async update(req, res) { const contest_id = req.params.contest_id; let contest = await db.contests.find_one({ where: { contest_id } }); if (req.method === 'POST') { const { name, description, start_date, end_date, input, output, disallowed_languages } = req.body; if (!test_cases.are_valid({ input, output })) { return res.status(400).send({ message: 'Invalid test cases' }); } contest.name = name; contest.description = description; contest.start_date = start_date; contest.end_date = end_date; contest.input = input; contest.output = output; contest.disallowed_languages = disallowed_languages; await contest.save(); return res.status(200).send(); } return res.view({ contest, mode: 'update' }); }, async delete_submission(req, res) { const { contest_submission_id } = req.body; let submission = await db.contest_submissions.find_one({ where: { contest_submission_id } }); if (!submission) { return res.status(400).send(); } await submission.destroy(); return res.status(200).send(); }, async validate_submissions(req, res) { const { contest_id } = req.params; let contest = await db.contests.find_one({ where: { contest_id }, include: [ { required: false, model: db.contest_submissions, as: 'submissions', include: [ { model: db.users, as: 'user', attributes: ['username'] } ] } ] }); let test_cases = contests.get_cases(contest); let invalids = []; const CHUNK_SIZE = 5; let validation_ops = []; for (let count = 1; count <= contest.submissions.length; ++count) { const submission = contest.submissions[count - 1]; validation_ops.push( contests .validate_submission( test_cases, submission.solution, submission.language, submission.language_version || '*' ) .then((valid) => { if (!valid) invalids.push(submission); }) ); if ( count % CHUNK_SIZE === 0 || count === contest.submissions.length ) { await Promise.all(validation_ops); validation_ops = []; } } return res.status(200).send({ invalids }); } }; ================================================ FILE: platform/api/controllers/admin/DashboardController.js ================================================ module.exports = { async dashboard(req, res) { return res.view(); } }; ================================================ FILE: platform/api/controllers/admin/PistonController.js ================================================ module.exports = { async view_all(req, res) { return res.view({ message: null }); }, async packages(req, res) { let packages = await piston.packages(); return res.status(200).send(packages); }, async install(req, res) { let { language, version } = req.query; let result = await piston.install(language, version); let message = result.language ? 'succeeded' : 'failed: ' + result.message; return res.view('admin/piston/view_all', { message: `Installation of ${language}-${version} ${message}` }); }, async uninstall(req, res) { let { language, version } = req.query; let result = await piston.uninstall(language, version); let message = result.language ? 'succeeded' : 'failed: ' + result.message; return res.view('admin/piston/view_all', { message: `Uninstallation of ${language}-${version} ${message}` }); } }; ================================================ FILE: platform/api/controllers/admin/UsersController.js ================================================ module.exports = { async view_all(req, res) { let users = await db.users.find_all({ attributes: ['user_id', 'username', 'display_name', 'created_at'], where: { [$not]: { user_id: req.session.user_id } }, order: [['user_id', 'desc']] }); return res.view({ users }); }, async login_as(req, res) { let target_id = parse_int(req.query.user_id); let user = await db.users.find_one({ where: { user_id: target_id } }); // The logging in logic if (req.session.user_id === target_id || req.session.old_id || !user) { // On trying to log in as oneself or not using the original user return res.view('home/fourohfour'); } req.session.old_id = req.session.user_id; req.session.user_id = target_id; return res.redirect('/'); } }; ================================================ FILE: platform/api/controllers/api/internal/ChatsController.js ================================================ const crypto = require('crypto'); const moment = require('moment'); module.exports = { async last(req, res) { let message = await db.discord_chat_messages.find_one({ order: [['created_at', 'desc']] }); // this should only be a thing once, send beginning of time if (!message) { return res.send({ last_timestamp: moment('1970-01-01').format() }); } return res.status(200).send({ last_timestamp: message.created_at }); }, async create(req, res) { let messages = req.body; // sometimes only a single message object will be sent, transparently convert to array if (!Array.is_array(messages)) messages = [messages]; let inserted = 0; let duplicate = 0; let failed = 0; // filter out any messages that don't have all the necessary information messages = messages.filter((m) => { let valid = m.channel && m.user && m.discord_id && m.message && m.timestamp && moment(m.timestamp).isValid(); if (!valid) ++failed; return valid; }); let t = await db.sequelize.transaction(); try { for (const message of messages) { let new_message = { channel: message.channel, user: message.user.replace(/[^\x00-\x7F]/g, ''), discord_id: message.discord_id, message: message.message.replace(/[^\x00-\x7F]/g, ''), created_at: moment(message.timestamp).format() }; let hash = crypto .createHash('sha1') .update(JSON.stringify(new_message)) .digest('hex'); new_message.hash = hash; try { await db.discord_chat_messages.create(new_message, { transaction: t }); ++inserted; } catch (e) { if ( err.original.code && err.original.code === 'ER_DUP_ENTRY' ) { ++duplicate; } else { ++failed; } } } await t.commit(); } catch (e) { await t.rollback(); } return res.status(200).send({ inserted, duplicate, failed }); } }; ================================================ FILE: platform/api/controllers/api/internal/PistonController.js ================================================ module.exports = { async log(req, res) { let { server, server_id, user, user_id, language, source } = req.body; if ( !server || !server_id || !user || !user_id || !language || !source ) { return res.status(400).send(); } await db.piston_runs.create({ server, server_id, user, user_id, language, source }); return res.status(200).send(); } }; ================================================ FILE: platform/api/controllers/api/v1/PistonController.js ================================================ const axios = require('axios'); const Redis = require('ioredis'); module.exports = { async versions(req, res) { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Headers', '*'); if (req.method === 'OPTIONS') { return res.status(200).send(); } let result = await piston.runtimes(); result = result.map((lang) => { return { name: lang.language, version: lang.version, aliases: lang.aliases }; }); return res.status(200).send(result); }, async execute(req, res) { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Headers', '*'); if (req.method === 'OPTIONS') { return res.status(200).send(); } const ip = req.headers['x-real-ip']; const authorization = req.headers['authorization']; if (!sails.config.piston.unlimited_keys.includes(authorization)) { const redis = new Redis(6379, 'redis'); let entry = await redis.get(`piston-${ip}`); if (entry) { redis.disconnect(); return res.status(429).send({ message: 'Requests limited to 2 per second' }); } else { await redis.set(`piston-${ip}`, 0, 'px', 500); } redis.disconnect(); } let { language, source, args, stdin, version } = req.body; let log = null; if (req.body.log !== 0) { log = { server: 'Piston API', user: 'Direct Usage' }; } try { let result = await piston.execute( language, source, args, stdin, version || '*', //default to latest version log ); return res.status(200).send({ ran: result.ran, language: result.language, version: result.version, output: result.output ? result.output.replace(/\r/gi, '').slice(0, 65536) : '', stdout: result.stdout ? result.stdout.replace(/\r/gi, '').slice(0, 65536) : '', stderr: result.stderr ? result.stderr.replace(/\r/gi, '').slice(0, 65536) : '' }); } catch (e) { if (e.status_code === 400) { return res.status(400).send({ message: e.message }); } else { return res.status(500).send({ message: 'Execution problem' }); } } } }; ================================================ FILE: platform/api/controllers/api/v1/UsersController.js ================================================ module.exports = { async read_all(req, res) { const { discord_id } = req.query; let query = { where: {}, attributes: [ 'user_id', 'discord_api', 'username', 'display_name', 'score' ] }; if (discord_id) { query.where.discord_api = discord_id; } let users = await db.users.find_all(query); return res.status(200).send(users); }, async read(req, res) { const user_id = req.params.user_id; let user = await db.users.find_one({ where: { user_id }, attributes: ['user_id', 'username', 'display_name', 'score'] }); if (!user) { return res.status(404).send(); } return res.status(200).send(user); } }; ================================================ FILE: platform/api/controllers/api/v1/stats/DiscordController.js ================================================ const moment = require('moment'); module.exports = { async messages(req, res) { let { user, discord_id, term, start, end, limit } = req.query; if (!Array.is_array(user) && typeof user !== 'undefined') { user = [user]; } if (!Array.is_array(discord_id) && typeof discord_id !== 'undefined') { discord_id = [discord_id]; } let query = { where: { [$and]: [] }, attributes: [ 'user', 'discord_id', [db.sequelize.literal('count(*)'), 'messages'] ], order: [[db.sequelize.col('messages'), 'desc']], group: ['discord_id'], limit: 1000 }; let dates = []; if (user) { query.where.user = user; } if (discord_id) { query.where.discord_id = discord_id; } if (term) { query.where.message = { [$like]: '%' + term + '%' }; } if (start) { start = moment(start); if (start.isValid()) { query.where[$and].push({ created_at: { [$gte]: start.format('YYYY-MM-DD HH:mm:ss') } }); } } if (end) { end = moment(end); if (end.isValid()) { query.where[$and].push({ created_at: { [$lte]: end.format('YYYY-MM-DD HH:mm:ss') } }); } } if (limit > 0 && limit <= 1000) { query.limit = +limit; } let stats = await db.discord_chat_messages.find_all(query); return res.send(stats); }, async channels(req, res) { let { user, discord_id, start, end, limit } = req.query; let query = { where: { [$and]: [] }, attributes: [ 'channel', [db.sequelize.literal('count(*)'), 'messages'] ], order: [[db.sequelize.col('messages'), 'desc']], group: ['channel'], limit: 1000 }; let dates = []; if (user) { query.where.user = { [$like]: '%' + user.replace(/[^\x00-\x7F]/g, '') + '%' }; } if (discord_id) { query.where.discord_id = discord_id; } if (start) { start = moment(start); if (start.isValid()) { query.where[$and].push({ created_at: { [$gte]: start.format('YYYY-MM-DD HH:mm:ss') } }); } } if (end) { end = moment(end); if (end.isValid()) { query.where[$and].push({ created_at: { [$lte]: end.format('YYYY-MM-DD HH:mm:ss') } }); } } if (limit > 0 && limit <= 1000) { query.limit = +limit; } let stats = await db.discord_chat_messages.find_all(query); return res.status(200).send(stats); } }; ================================================ FILE: platform/api/controllers/api/v1/stats/PistonController.js ================================================ const moment = require('moment'); module.exports = { async usage(req, res) { let { start, end, category } = req.query; let query = { where: { [$and]: [] } }; let where = query.where[$and]; switch (category) { case 'bot': where.push({ server_id: { [$ne]: null } }); break; case 'emkc': where.push({ server_id: null }); where.push({ server: 'EMKC' }); break; case 'direct': where.push({ server_id: null }); where.push({ server: 'Piston API' }); break; } if (start) { start = moment(start); if (start.isValid()) { where.push({ created_at: { [$gte]: start.format('YYYY-MM-DD HH:mm:ss') } }); } } if (end) { end = moment(end); if (end.isValid()) { where.push({ created_at: { [$lte]: end.format('YYYY-MM-DD HH:mm:ss') } }); } } let count = await db.piston_runs.count(query); return res.status(200).send({ count }); } }; ================================================ FILE: platform/api/controllers/api/v2/PistonController.js ================================================ const axios = require('axios'); const Redis = require('ioredis'); module.exports = { async runtimes(req, res) { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Headers', '*'); if (req.method === 'OPTIONS') { return res.status(200).send(); } let result = await piston.runtimes(); return res.status(200).send(result); }, async execute(req, res) { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Headers', '*'); if (req.method === 'OPTIONS') { return res.status(200).send(); } const ip = req.headers['x-real-ip']; const authorization = req.headers['authorization']; if (!sails.config.piston.unlimited_keys.includes(authorization)) { const redis = new Redis(6379, 'redis'); let entry = await redis.get(`piston-${ip}`); if (entry) { redis.disconnect(); return res.status(429).send({ message: 'Requests limited to 1 per 200ms' }); } else { await redis.set(`piston-${ip}`, 0, 'px', 200); } redis.disconnect(); } let { language, files, args, stdin, version, run_timeout, compile_timeout, run_memory_limit, compile_memory_limit } = req.body; let log = null; if (req.body.log !== 0) { log = { server: 'Piston API', user: 'Direct Usage' }; } try { let result = await piston.execute( language, files, args, stdin, version, log, { run: run_timeout, compile: compile_timeout }, { run: run_memory_limit, compile: compile_memory_limit } ); return res.status(200).send({ language: result.language, version: result.version, run: result.run, compile: result.compile }); } catch (e) { if (e.status_code === 400) { return res.status(400).send({ message: e.message }); } else { return res.status(500).send({ message: 'Execution problem: ' + e.message }); } } } }; ================================================ FILE: platform/api/policies/api_internal_auth.js ================================================ module.exports = (req, res, next) => { let authorization; Object.keys(req.headers).for_each((key) => { if (key.to_lower_case() === 'authorization') authorization = req.headers[key]; }); if (authorization !== sails.config.api.internal_key) { return res.send(401, { message: 'Invalid authorization' }); } return next(); }; ================================================ FILE: platform/api/policies/common.js ================================================ module.exports = async (req, res, next) => { req.local = req.local || { user_id: null }; req.local.constant = constant; // get the logged in user let user = await db.users.find_one({ where: { user_id: req.session.user_id || null } }); if (user) { req.local.user_id = user.user_id; req.local.user = user; } return next(); }; ================================================ FILE: platform/api/policies/is_admin.js ================================================ module.exports = (req, res, next) => { if (!req.local.user || !req.local.user.is_staff) { return res.redirect('/'); } return next(); }; ================================================ FILE: platform/api/policies/is_prod.js ================================================ module.exports = (req, res, next) => { if (!constant.is_prod) { return res.redirect('/'); } return next(); }; ================================================ FILE: platform/api/policies/logged_in.js ================================================ module.exports = (req, res, next) => { if (!req.local.user_id) return res.redirect('/'); return next(); }; ================================================ FILE: platform/api/services/api.js ================================================ module.exports = { handle_err(res, err) { console.log(err, '\n\n'); try { err = JSON.parse(err.message); return res.send({ message: err[0] || 'An error occurred', errors: err[1] }); } catch (e) { return res.send({ message: err.message || 'An error occurred' }); } } }; ================================================ FILE: platform/api/services/constant.js ================================================ let constant = { no: 0, yes: 1, awards: { type: { contest_first_overall: 1, contest_second_overall: 2, contest_third_overall: 3, contest_first_language: 4, general_participation: 5 }, ref_type: { contests: 1 } }, challenges: { supported_languages: [ 'js', 'python', 'go', 'c', 'ruby', 'cpp', 'cs', 'php', 'swift', 'java', 'rust', 'julia', 'bash', 'perl', 'kotlin', 'haskell', 'nim' ], difficulty: { easy: 1, medium: 2, hard: 3 } }, contests: { disallowed_languages: [ 'python2', 'awk', 'dotnet', 'csharp.net', 'basic.net' ], golf_languages: ['jelly', 'osabie'] }, channels: { emkc: '483979558249562112', // emkc-felix-piston python: '483980259239264256', // python js: '483977935225749504', // js-ts-node go: '484027805605298197', // other-languages c: '483978202092535809', // c-cpp-csharp ruby: '484027805605298197', // other-languages cpp: '483978202092535809', // c-cpp-csharp cs: '483978202092535809', // c-cpp-csharp php: '484027805605298197', // other-languages swift: '484027805605298197', // other-languages java: '483979599131312128' // java-kotlin }, roles: { emkc_member: '486562889046556682', emkc_novice: '489975146782785536', emkc_hero: '489975618016903180', emkc_master: '489975728822288384', emkc_legend: '490314890779688963', emkc_winner: '490324386675425281' }, server_id: '473161189120147456', piston: { timeouts: { compile: 10000, run: 3000 }, memory_limits: { compile: -1, run: -1 } }, set_dynamic() { this.base_url = sails.config.base_url; this.cdn_url = this.base_url + '/cdn'; this.is_prod = sails.config.environment === 'production'; this.piston_url = sails.config.environment === 'production' ? 'http://' + sails.config.piston.host + '/api/v2' : 'https://emkc.org/api/v2/piston'; } }; constant.set_dynamic(); module.exports = constant; ================================================ FILE: platform/api/services/contests.js ================================================ module.exports = { get_cases(contest, redact = false) { if (contest.input === '' || contest.output === '') { return []; } const { inputs, outputs } = test_cases.get_inputs_and_outputs(contest); let cases = []; for (let i = 0; i < inputs.length; ++i) { let input = inputs[i]; let this_case = { hide_input: false, hide_output: false, hide_ignore_active: false, args: input, stdin: input.join('\n'), output: outputs[i].replace(/\\n/g, '\n') }; if (input[0].length == 0) { // starts with a pipe //|opt_string|..... this_case.args = input.splice(2); this_case.stdin = this_case.args.join('\n'); let opt_string = input[1]; // e.g. |hide_input,hide_output|hello|world opt_string.split(',').for_each((opt) => { let vals = opt.split('='); this_case[vals[0]] = vals.length == 1 || vals[1]; // true if there is no =, else the value after the = }); } // Hide data from the front-end, but not from the backend if (redact && (contest.active || this_case.hide_ignore_active)) { if (this_case.hide_input) { this_case.args = this_case.args.map((_) => 'hidden'); this_case.stdin = '[hidden]'; } if (this_case.hide_output) { this_case.output = '[hidden]'; } } cases.push(this_case); } return cases; }, async validate_submission(test_cases, solution, language, version) { for (const test_case of test_cases) { let test_result = await piston.execute( language, solution, test_case.args, test_case.stdin, version ); if (test_result.run.stdout.trim() !== test_case.output.trim()) { return false; } } return true; } }; ================================================ FILE: platform/api/services/discord.js ================================================ const request = require('request-promise'); module.exports = { async api(method, url, body = null) { const options = { method, url: 'https://discord.com/api/v10' + url, headers: { Authorization: 'Bot ' + sails.config.felix.key }, json: true, simple: false, resolveWithFullResponse: true }; if (body) { options.body = body; } const response = await request(options); return response; } }; ================================================ FILE: platform/api/services/dispenserd.js ================================================ const request = require('request-promise'); module.exports = { lane_main: 'main', job_test: 'test', /** * dispenserd.schedule(dispenserd.job_test, { * key: 'value' * }); */ schedule(job, options) { options.job = job; request .post({ url: 'http://' + sails.config.dispenserd.host + ':8282/schedule', body: JSON.stringify({ lane: options.lane || dispenserd.lane_main, priority: options.priority || 10000, message: JSON.stringify(options) }), resolveWithFullResponse: true, simple: false }) .catch((err) => { console.log('job failed to schedule'); }); } }; ================================================ FILE: platform/api/services/error.js ================================================ const moment = require('moment'); module.exports = { log(err, msg) { var final_message = '[msg] ' + msg + '\n' + '[date] ' + util.now(); if (err) { final_message += '\n[err] ' + err.toString(); } console.log('\n---\n' + final_message); } }; ================================================ FILE: platform/api/services/mailer.js ================================================ const moment = require('moment'); const q = require('q'); const mailgun = require('mailgun-js')({ apiKey: sails.config.mailgun.key, domain: sails.config.mailgun.domain }); module.exports = { send(to, subject, content, template, variables) { var final_content; var from = variables.context.name + ' '; subject = subject.replace('{{name}}', variables.context.name); var send = () => { mailgun.messages().send( { from, to: constant.email_intercept || to, 'h:Reply-to': variables.reply_to || 'no-reply@emkc.org', subject, html: final_content }, (err, body) => { try { console.log('email to: ' + to); console.log('subject: ' + subject); console.log('err: ' + err); console.log('body: ' + JSON.stringify(body)); } catch (e) { console.log('in catch'); } } ); }; if (template) { views.render(template, variables).then((template_content) => { final_content = template_content; send(); }); } else { final_content = content; send(); } } }; ================================================ FILE: platform/api/services/piston.js ================================================ const axios = require('axios'); const timeout = (ms) => new Promise((res) => set_timeout(res, ms)); const emkc_internal_log_message = { server: 'EMKC', user: 'EMKC Usage' }; class PistonError extends Error { constructor(message, status_code) { super(status_code + ': ' + message); this.message = message; this.error_message = message; this.status_code = status_code; } } module.exports = { languages: { python: 'python', javascript: 'javascript', ruby: 'ruby', go: 'go', c: 'c', cpp: 'cpp', csharp: 'csharp', php: 'php', swift: 'swift', java: 'java' }, async runtimes() { let result = await axios.get(constant.piston_url + '/runtimes'); return result.data; }, async packages() { let result = await axios.get(constant.piston_url + '/packages'); return result.data; }, async install(language, version) { let result = await axios.post( constant.piston_url + `/packages/${language}/${version}` ); return result.data; }, async uninstall(language, version) { let result = await axios.delete( constant.piston_url + `/packages/${language}/${version}` ); return result.data; }, async execute( language, files, args, stdin, version, log_message = emkc_internal_log_message, timeouts = {}, memory_limits = {} ) { if (!Array.is_array(args)) { args = []; } if (typeof files === 'string') { // Assume this is just source, not files files = [ { content: files } ]; } await timeout(constant.is_prod ? 0 : 500); // Delay by 0.5 seconds when using the public api const compile_timeout = constant.piston.timeouts.compile; const run_timeout = constant.piston.timeouts.run; const compile_memory_limit = constant.piston.memory_limits.compile; const run_memory_limit = constant.piston.memory_limits.run; const request_timeouts = { run_timeout, compile_timeout }; const request_memory_limits = { run_memory_limit, compile_memory_limit }; if (timeouts.compile) { request_timeouts.compile_timeout = Math.min( compile_timeout, timeouts.compile ); } if (timeouts.run) { request_timeouts.run_timeout = Math.min(run_timeout, timeouts.run); } if (memory_limits.compile) { request_memory_limits.compile_memory_limit = compile_memory_limit === -1 ? memory_limits.compile : Math.min(compile_memory_limit, memory_limits.compile); } if (memory_limits.run) { request_memory_limits.run_memory_limit = run_memory_limit === -1 ? memory_limits.run : Math.min(run_memory_limit, memory_limits.run); } let result = await axios({ method: 'post', url: constant.piston_url + '/execute', data: { language, version, files, args, stdin, ...request_timeouts, ...request_memory_limits } }); if (result.status !== 200) { throw new PistonError(result.data.message, result.status); } if (log_message) { db.piston_runs.create({ ...log_message, language, source: files[0].content }); } let output = ''; let stdout = ''; let stderr = ''; let ran = true; if (result.data.compile) { output += result.data.compile.output; stdout += result.data.compile.stdout; stderr += result.data.compile.stderr; ran = ran && result.data.compile.code == 0; } if (result.data.run) { output += result.data.run.output; stdout += result.data.run.stdout; stderr += result.data.run.stderr; ran = ran && result.data.run.code == 0; } return { ...result.data, output, stdout, stderr, ran }; } }; ================================================ FILE: platform/api/services/test_cases.js ================================================ module.exports = { get_inputs_and_outputs(test_object) { const inputs = test_object.input .split('\n') .map((input) => input.split('|')); const outputs = test_object.output.split('\n'); return { inputs, outputs }; }, are_valid(test_object) { return ( test_object.input !== '' && test_object.output !== '' && test_object.input.split('\n').length === test_object.output.split('\n').length ); } }; ================================================ FILE: platform/api/services/twig.js ================================================ const moment = require('moment'); const twig = require('twig'); twig.extendFilter('noscript', (value) => { if (!value) { return value; } return value.replace(/\//gi, '\\/'); }); module.exports = { starts_with(string, path) { let pattern = new RegExp('^' + path.replace('/', '\\/')); return pattern.test(string); } }; ================================================ FILE: platform/api/services/util.js ================================================ const fs = require('fs'); const moment = require('moment'); module.exports = { now() { return moment().format('YYYY-MM-DD HH:mm:ss'); }, slugify(string) { return (string + '') .toLowerCase() .trim() .replace(/[^a-z0-9 ]+/g, '') .replace(/ +/g, '-') .replace(/^[\s\-]+/gi, '') .replace(/[\s\-]+$/gi, ''); }, time_diff(start_date, end_date) { var diff = parse_int(end_date.diff(start_date) / 1000); var days = diff / 60 / 60 / 24; var hours = diff / 60 / 60; var minutes = diff / 60; var seconds = diff; var time, unit; for (;;) { if (hours >= 24) { time = Math.round(days); break; } if (minutes >= 60) { time = Math.round(hours); break; } if (seconds >= 60) { time = Math.round(minutes); break; } time = seconds >= 0 ? seconds : 0; break; } for (;;) { if (hours >= 24) { unit = 'days'; break; } if (minutes >= 60) { unit = 'hours'; break; } if (seconds >= 60) { unit = 'minutes'; break; } unit = 'seconds'; break; } if (unit === 'days' && time > 30) { var months = Math.round(time / 30); if (months === 1) { return '1 month'; } else { return months + ' months'; } } if (time === 1) { return time + ' ' + unit.slice(0, -1); } else { return time + ' ' + unit; } }, time_ago(the_time) { var start_date = moment(the_time); var end_date = moment(); return this.time_diff(start_date, end_date); }, bury_upload(file) { if (!file) return null; file.upload({ dirname: '/tmp' }, (err, files) => { files.for_each((file) => { fs.unlink(file.fd); }); }); } }; ================================================ FILE: platform/api/services/views.js ================================================ const twig = require('twig'); module.exports = { async render(template, data) { data.sails = sails; data.constant = constant; return await twig .twig({ allowInlineIncludes: true, base: root_dir + '/platform/views', path: root_dir + '/platform/views/' + template + '.twig', async: false }) .render(data); } }; ================================================ FILE: platform/config/blueprints.js ================================================ module.exports.blueprints = { actions: false, shortcuts: false, rest: false, index: false }; ================================================ FILE: platform/config/bootstrap.js ================================================ process.env.TZ = 'UTC'; require('nocamel'); const path = require('path'); root_dir = path.resolve(__dirname + '/../../'); Promise = require('bluebird'); let axios = require('axios'); axios.defaults.validateStatus = () => true; module.exports.bootstrap = (cb) => { db = require(root_dir + '/platform/models/index.js'); sails.local = { root_dir }; sails.twig = require(root_dir + '/platform/api/services/twig.js'); sails.local.constant = require(root_dir + '/platform/api/services/constant.js'); sails.local.epoch = +new Date(); sails.io.sockets.on('connection', (socket) => { // test for code room socket var hash = /\/r\/([a-zA-Z0-9]+)/gi.exec( socket.handshake.headers.referer ); hash = hash.length > 1 ? hash[1] : null; if (hash) return code_rooms.handle_socket_actions(socket, hash); }); cb(); }; ================================================ FILE: platform/config/controllers.js ================================================ module.exports.controllers = { blueprints: { actions: false, rest: false, shortcuts: false, prefix: '', pluralize: false }, jsonp: false, expectIntegerId: false }; ================================================ FILE: platform/config/http.js ================================================ module.exports.http = { middleware: { xframe: require('lusca').xframe('SAMEORIGIN'), order: [ 'startRequestTimer', 'xframe', 'cookieParser', 'session', 'bodyParser', 'test_json', 'compress', 'methodOverride', '$custom', 'router', 'www', 'favicon', '404', '500' ], test_json(err, req, res, next) { if (err) { return res.send(400, { message: 'Invalid JSON received' }); } return next(); } }, bodyParser() { return require('skipper')({ limit: '4096mb' }); } }; ================================================ FILE: platform/config/local.js.sample ================================================ module.exports = { port: 2727, environment: 'development', base_url: 'http://127.0.0.1:2005', db: { username: 'root', password: 'root', database: 'emkc', host: 'mysql', dialect: 'mysql', logging: false, timezone: '+00:00', define: { underscored: true, timestamps: false } }, api: { internal_key: '' }, discord: { client_id: '496807648289882112', client_secret: 'IqJEUGdYR2UxHKrVmVTha__3aLhIC68l' }, felix: { key: '' }, gcp: { project_id: '' }, mailgun: { key: 'yourkeyhere', domain: '' }, paypal: { id: '', secret: '', coupon: '' }, paypal: { id: '', secret: '', coupon: '' }, piston: { host: '127.0.0.1:2000', unlimited_keys: [] }, dispenserd: { host: '127.0.0.1' }, session: { host: 'redis', secret: '' }, sockets: { host: 'redis' } }; ================================================ FILE: platform/config/paths.js ================================================ module.exports.paths = { public: __dirname + '/../public' }; ================================================ FILE: platform/config/policies.js ================================================ module.exports.policies = { '*': 'common', AuthController: { '*': ['common'] }, ChallengesController: { '*': ['common'] }, CommunityController: { '*': ['common'], add_video_request: ['common', 'logged_in'], delete_video_request: ['common', 'logged_in'], video_request_vote: ['common', 'logged_in'] }, ContestsController: { '*': ['common'], submit: ['common', 'logged_in'] }, HomeController: { '*': ['common'] }, MerchController: { '*': ['common'] }, ProfilesController: { '*': ['common'] }, ScriptsController: { '*': ['common'] }, SnippetsController: { '*': ['common'], mine: ['common', 'logged_in'], delete: ['common', 'logged_in'], edit: ['common', 'logged_in'] }, TagsController: { '*': ['common'] }, 'admin/ContestsController': { '*': ['common', 'logged_in', 'is_admin'] }, 'admin/ChallengesController': { '*': ['common', 'logged_in', 'is_admin'] }, 'admin/DashboardController': { '*': ['common', 'logged_in', 'is_admin'] }, 'admin/UsersController': { '*': ['common', 'logged_in', 'is_admin'] }, 'admin/PistonController': { '*': ['common', 'logged_in', 'is_admin', 'is_prod'] }, 'api/internal/ChatsController': { '*': ['common', 'api_internal_auth'] }, 'api/internal/PistonController': { '*': ['common', 'api_internal_auth'] }, 'api/v1/PistonController': { '*': ['common'] }, 'api/v1/UsersController': { '*': ['common'] }, 'api/v1/stats/DiscordController': { '*': ['common'] }, 'api/v1/stats/PistonController': { '*': ['common'] } }; ================================================ FILE: platform/config/routes.js ================================================ module.exports.routes = { 'GET /': 'HomeController.home', 'GET /logout': 'HomeController.logout', 'GET /logout_as': 'HomeController.logout_as', 'GET /auth/discord': 'AuthController.discord', 'GET /auth/discord_cb': 'AuthController.discord_cb', 'GET /privacy': 'HomeController.privacy', //'GET /stickers': 'MerchController.stickers', //'POST /stickers/order': 'MerchController.order_stickers', //'GET /stickers/check_code/:code': 'MerchController.check_code', 'GET /community': 'CommunityController.home', 'GET /community/about': 'CommunityController.about', 'GET /community/power': 'CommunityController.power', 'GET /challenges': 'ChallengesController.home', 'GET /challenges/choose_language/:challenge_id': 'ChallengesController.choose_language', 'POST /challenges/execute/:challenge_id': 'ChallengesController.execute', 'GET /challenges/:challenge_id/:language': 'ChallengesController.challenge', 'GET /contests': 'ContestsController.home', 'POST /contests/submit': 'ContestsController.submit', 'GET /contests/disallowed_languages/:contest_id': 'ContestsController.disallowed_languages', 'GET /contests/:contest_id/:slug': 'ContestsController.contest', 'GET /snippets': 'SnippetsController.create', 'POST /snippets': 'SnippetsController.create', 'GET /snippets/mine': 'SnippetsController.mine', 'GET /s/:hash': 'SnippetsController.view', 'GET /s/:hash/raw': 'SnippetsController.view', 'POST /snippets/delete/:hash': 'SnippetsController.delete', 'GET /snippets/edit/:hash': 'SnippetsController.edit', 'POST /snippets/edit/:hash': 'SnippetsController.edit', 'GET /scripts': 'ScriptsController.home', 'GET /scripts/:cli_script_id/:slug': 'ScriptsController.view', 'GET /exec/:cli_script_id': 'ScriptsController.exec', 'GET /@:username': 'ProfilesController.view', 'GET /@:username/challenges/:challenge_id/:language': 'ChallengesController.view_other', // admin 'GET /admin': 'admin/DashboardController.dashboard', 'GET /admin/contests': 'admin/ContestsController.view_all', 'GET /admin/challenges': 'admin/ChallengesController.view_all', 'GET /admin/challenges/update/:challenge_id': 'admin/ChallengesController.update', 'POST /admin/challenges/update/:challenge_id': 'admin/ChallengesController.update', 'GET /admin/challenges/create': 'admin/ChallengesController.create', 'POST /admin/challenges/create': 'admin/ChallengesController.create', 'GET /admin/contests/all': 'admin/ContestsController.view_all', 'GET /admin/contests/create': 'admin/ContestsController.create', 'POST /admin/contests/create': 'admin/ContestsController.create', 'GET /admin/contests/update/:contest_id': 'admin/ContestsController.update', 'POST /admin/contests/update/:contest_id': 'admin/ContestsController.update', 'POST /admin/submissions/validate/:contest_id': 'admin/ContestsController.validate_submissions', 'POST /admin/submissions/delete': 'admin/ContestsController.delete_submission', 'GET /admin/users': 'admin/UsersController.view_all', 'GET /admin/users/login_as': 'admin/UsersController.login_as', 'GET /admin/piston': 'admin/PistonController.view_all', 'GET /admin/piston/packages': 'admin/PistonController.packages', 'GET /admin/piston/install': 'admin/PistonController.install', 'GET /admin/piston/uninstall': 'admin/PistonController.uninstall', // service api 'GET /api/internal/chats/last': 'api/internal/ChatsController.last', 'POST /api/internal/chats': 'api/internal/ChatsController.create', 'POST /api/internal/piston/log': 'api/internal/PistonController.log', // public api endpoints 'GET /api/v1/stats/discord/messages': 'api/v1/stats/DiscordController.messages', 'GET /api/v1/stats/discord/channels': 'api/v1/stats/DiscordController.channels', 'GET /api/v1/stats/piston/usage': 'api/v1/stats/PistonController.usage', 'GET /api/v1/users': 'api/v1/UsersController.read_all', 'GET /api/v1/users/:user_id': 'api/v1/UsersController.read', 'GET /api/v1/piston/versions': 'api/v1/PistonController.versions', 'OPTIONS /api/v1/piston/versions': 'api/v1/PistonController.versions', 'POST /api/v1/piston/execute': 'api/v1/PistonController.execute', 'OPTIONS /api/v1/piston/execute': 'api/v1/PistonController.execute', 'GET /api/v2/piston/runtimes': 'api/v2/PistonController.runtimes', 'OPTIONS /api/v2/piston/runtimes': 'api/v2/PistonController.runtimes', 'POST /api/v2/piston/execute': 'api/v2/PistonController.execute', 'OPTIONS /api/v2/piston/execute': 'api/v2/PistonController.execute', // catch all (404) 'ALL r|^/(?!cdn|css|images|js|lib|other|robots.txt|google*)|': 'HomeController.fourohfour' }; ================================================ FILE: platform/config/session.js ================================================ module.exports.session = { adapter: 'redis', key: 'engineerman.sid', cookie: { maxAge: 60 * 60 * 24 * 20 * 1000 } }; ================================================ FILE: platform/config/sockets.js ================================================ module.exports.sockets = { adapter: 'socket.io-redis' // transports: ['websocket'] }; ================================================ FILE: platform/config/views.js ================================================ const twig = require('twig'); for (let filter of require('../resources/twig/filters')) { twig.extendFilter(filter.name, filter.filter); } module.exports.views = { layout: false, engine: { ext: 'twig', fn: twig.__express } }; ================================================ FILE: platform/console/common.js ================================================ process.env.TZ = 'UTC'; process.setMaxListeners(0); require('nocamel'); Promise = require('bluebird'); root_dir = require('path').resolve(__dirname + '/../../'); sails = { config: require('../config/local.js') }; constant = require('../api/services/constant.js'); discord = require('../api/services/discord.js'); dispenserd = require('../api/services/dispenserd.js'); twig = require('../api/services/twig.js'); util = require('../api/services/util.js'); views = require('../api/services/views.js'); db = require('../models/index.js'); ================================================ FILE: platform/console/cron.js ================================================ #!/usr/bin/env node require('./common'); const axios = require('axios'); const moment = require('moment'); const timeout = (ms) => new Promise((res) => set_timeout(res, ms)); const cron = { async calculate_score() { let users = await db.users.find_all(); for (const user of users) { let total_score = 0; // process points from challenges let challenges = await db.user_challenges.find_all({ where: { user_id: user.user_id }, include: [ { model: db.challenges, as: 'challenge' } ] }); let challenges_score = challenges.reduce( (i, c) => i + c.challenge.points, 0 ); total_score += challenges_score; // process points from awards let awards = await db.awards.find_all({ where: { user_id: user.user_id } }); let awards_score = awards.reduce((i, a) => i + a.points, 0); total_score += awards_score; // sync score and apply to discord as appropriate user.score = total_score; if (!user.discord_api) { return await user.save(); } // test for and assign novice role if (user.discord_rank === null && user.score >= 40) { try { await discord.api( 'put', `/guilds/473161189120147456/members/${user.discord_api}` + `/roles/${constant.roles.emkc_novice}` ); user.discord_rank = 1; } catch (e) {} await timeout(1000); } // test for and assign hero role if (user.discord_rank === 1 && user.score >= 300) { try { await discord.api( 'put', `/guilds/473161189120147456/members/${user.discord_api}` + `/roles/${constant.roles.emkc_hero}` ); user.discord_rank = 2; } catch (e) {} await timeout(1000); } // test for and assign master role if (user.discord_rank === 2 && user.score >= 1000) { try { await discord.api( 'put', `/guilds/473161189120147456/members/${user.discord_api}` + `/roles/${constant.roles.emkc_master}` ); user.discord_rank = 3; } catch (e) {} await timeout(1000); } // test for and assign legend role if (user.discord_rank === 3 && user.score >= 5000) { try { await discord.api( 'put', `/guilds/473161189120147456/members/${user.discord_api}` + `/roles/${constant.roles.emkc_legend}` ); user.discord_rank = 4; } catch (e) {} await timeout(1000); } await user.save(); } }, async process_awards() { await db.awards.destroy({ where: {} }); // process contest related awards let contests = await db.contests.find_all({ where: { end_date: { [$lt]: util.now() }, contest_id: { [$not_in]: [30] } }, include: [ { model: db.contest_submissions, as: 'submissions', where: { late: constant.no }, include: [ { model: db.users, as: 'user' } ] } ], order: [ [ { model: db.contest_submissions, as: 'submissions' }, 'length' ], [ { model: db.contest_submissions, as: 'submissions' }, 'created_at' ] ] }); for (const contest of contests) { // handle 1st-3rd place let placed = [ ...new Set(contest.submissions.map((s) => s.user_id)) ].slice(0, 3); let i = 1; for (const user_id of placed) { let type = { 1: constant.awards.type.contest_first_overall, 2: constant.awards.type.contest_second_overall, 3: constant.awards.type.contest_third_overall }[i]; await db.awards.create({ type, user_id, ref_type: constant.awards.ref_type.contests, ref_id: contest.contest_id, points: { [constant.awards.type.contest_first_overall]: 500, [constant.awards.type.contest_second_overall]: 200, [constant.awards.type.contest_third_overall]: 75 }[type] }); ++i; } // handle per language let languages = []; for (const submission of contest.submissions) { if (languages.includes(submission.language)) { continue; } await db.awards.create({ type: constant.awards.type.contest_first_language, user_id: submission.user_id, ref_type: constant.awards.ref_type.contests, ref_id: contest.contest_id, points: 50 }); languages.push(submission.language); } // handle participation let participants = [ ...new Set(contest.submissions.map((s) => s.user_id)) ]; for (const user_id of participants) { await db.awards.create({ type: constant.awards.type.general_participation, user_id, ref_type: constant.awards.ref_type.contests, ref_id: contest.contest_id, points: 50 }); } } }, async update_staff() { await db.users.update( { is_staff: 0 }, { where: {} } ); let users = []; let last_id = null; let base_url = `/guilds/${constant.server_id}/members?limit=1000`; while (true) { let result = await discord.api( 'get', base_url + (last_id ? '&after=' + last_id : '') ); if (result.body.length === 0) { break; } users = users.concat(result.body); last_id = users.slice(-1)[0].user.id; await timeout(1200); } users = users .filter((user) => { return user.roles.includes('473167481624854541'); }) .map((user) => user.user.id); await db.users.update( { is_staff: 1 }, { where: { discord_api: { [$in]: users } } } ); }, async repair_roles() { const update_role = async (user, role) => { console.log('assigning ' + user.username + ' ' + role); let res = await discord.api( 'put', '/guilds/' + constant.server_id + '/members/' + user.discord_api + '/roles/' + role ); if (res.statusCode === 429) { let retry_after = res.body.retry_after; console.log('rate limited, waiting: ' + retry_after); await timeout(retry_after); await update_role(user, role); } }; let users = await db.users.find_all(); for (const user of users) { // member role if (user.discord_api) { await update_role(user, constant.roles.emkc_member); } // novice role if (user.discord_api && user.discord_rank === 1) { await update_role(user, constant.roles.emkc_novice); } // hero role if (user.discord_api && user.discord_rank === 2) { await update_role(user, constant.roles.emkc_hero); } // master role if (user.discord_api && user.discord_rank === 3) { await update_role(user, constant.roles.emkc_master); } // legend role if (user.discord_api && user.discord_rank === 4) { await update_role(user, constant.roles.emkc_legend); } } }, async contest_status() { let contest = await db.contests.find_one({ where: { start_date: { [$lte]: util.now() }, end_date: { [$gte]: util.now() } }, include: [ { model: db.contest_submissions, as: 'submissions', include: [ { model: db.users, as: 'user' } ] } ], order: [ ['contest_id', 'desc'], [ { model: db.contest_submissions, as: 'submissions' }, 'length' ], [ { model: db.contest_submissions, as: 'submissions' }, 'created_at' ] ] }); if (!contest || contest.submissions.length === 0) { return; } let submission = contest.submissions[0]; discord .api('post', `/channels/${constant.channels.emkc}/messages`, { embeds: [ { //title: contest.name, description: 'This contest is active right now. Submit your solution soon and ' + 'try to beat the best solution! ' + `[Click here](${constant.base_url}${contest.url}) to give it a try.`, type: 'rich', color: 0x84e47f, url: `${constant.base_url}${contest.url}`, thumbnail: { url: constant.cdn_url + submission.user.avatar_url }, fields: [ { name: '**leader**', value: submission.user.display_name, inline: true }, { name: '**language used**', value: submission.language, inline: true }, { name: '**length**', value: submission.length, inline: true } ], author: { name: 'Contest Status: ' + contest.name, icon_url: 'https://emkc.org/images/icon_circle_64.png' }, footer: { text: `There's still ${contest.time_left}left to submit a solution` } } ] }) .catch((err) => {}); } }; var method = process.argv[2].replace(/-/gi, '_').replace(/^_+/gi, ''); cron[method](); ================================================ FILE: platform/console/util.js ================================================ #!/usr/bin/env node require('./common'); const moment = require('moment'); const request = require('request-promise'); let cron = { ingest_chats() { let messages = require('fs') .read_file_sync('chats.log') .to_string() .split('\n') .map((msg) => { const pieces = msg.split('|'); const [timestamp, channel, user] = pieces; const message = pieces.slice(3).join(''); return { timestamp, channel, user, message }; }); request({ method: 'post', url: 'http://127.0.0.1:2727/api/internal/chats', headers: { authorization: sails.config.api.internal_key }, body: messages, json: true, simple: true }); } }; let method = process.argv[2].replace(/-/gi, '_').replace(/^_+/gi, ''); cron[method](); ================================================ FILE: platform/emkc.js ================================================ /** * Engineer Man Knowledge Center * Copyright (C) 2021 Brian Seymour and EMKC Contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. **/ require('sails').lift(require('optimist').argv); ================================================ FILE: platform/migrations/config.json.sample ================================================ { "host": "mysql", "port": 3306, "user": "root", "pass": "root", "db": "emkc", "platform": "mysql" } ================================================ FILE: platform/migrations/migrations/20180320123747-initial.sql ================================================ up: create table users ( user_id int unsigned not null auto_increment, is_staff tinyint unsigned not null default 0, username varchar(64) null, email varchar(128) null, password varchar(40) null, discord_api varchar(32) null, avatar_url varchar(128) null, score int not null default 0, created_at datetime not null, primary key (user_id), key is_staff (is_staff), key username (username), key email (email), key discord_api (discord_api), key score (score) )engine=innodb default charset=utf8; create table questions ( question_id int unsigned not null auto_increment, user_id int unsigned not null, title varchar(128) not null, question mediumtext not null, score int not null default 0, comments int unsigned not null default 0, created_at datetime not null, primary key (question_id), key user_id (user_id), key score (score), key comments (comments), key created_at (created_at) )engine=innodb default charset=utf8; create table snippets ( snippet_id int unsigned not null auto_increment, user_id int unsigned null, hash varchar(40) not null, snip mediumtext not null, created_at datetime not null, primary key (snippet_id), key user_id (user_id), key hash (hash), key created_at (created_at) )engine=innodb default charset=utf8; create table comments ( comment_id int unsigned not null auto_increment, question_id int unsigned not null, base_id int unsigned null, parent_id int unsigned null, user_id int unsigned not null, comment mediumtext not null, depth int not null default 0, score int not null default 0, created_at datetime not null, primary key (comment_id), key question_id (question_id), key base_id (base_id), key parent_id (parent_id), key user_id (user_id), key depth (depth), key score (score), key created_at (created_at) )engine=innodb default charset=utf8; create table question_votes ( question_vote_id int unsigned not null auto_increment, question_id int unsigned not null, user_id int unsigned not null, value tinyint not null, primary key (question_vote_id), key question_id (question_id), key user_id (user_id), key value (value) )engine=innodb default charset=utf8; create table comment_votes ( comment_vote_id int unsigned not null auto_increment, comment_id int unsigned not null, user_id int unsigned not null, value tinyint not null, primary key (comment_vote_id), key comment_id (comment_id), key user_id (user_id), key value (value) )engine=innodb default charset=utf8; create table tags ( tag_id int unsigned not null auto_increment, name varchar(128) not null, primary key (tag_id), key name (name) )engine=innodb default charset=utf8; insert into tags values (default, 'abend'); insert into tags values (default, 'absolute-address'); insert into tags values (default, 'absolute-coding'); insert into tags values (default, 'access-violation'); insert into tags values (default, 'acm'); insert into tags values (default, 'action-statement'); insert into tags values (default, 'actionscript'); insert into tags values (default, 'activex'); insert into tags values (default, 'ada'); insert into tags values (default, 'add'); insert into tags values (default, 'ado'); insert into tags values (default, 'advanced-scsi-programming-interface'); insert into tags values (default, 'aggregation'); insert into tags values (default, 'agile-development-methods'); insert into tags values (default, 'agile-manifesto'); insert into tags values (default, 'alert'); insert into tags values (default, 'algol'); insert into tags values (default, 'algorithm'); insert into tags values (default, 'altair-basic'); insert into tags values (default, 'ambient-occlusion'); insert into tags values (default, 'aop'); insert into tags values (default, 'api'); insert into tags values (default, 'applet'); insert into tags values (default, 'argument'); insert into tags values (default, 'arithmetic-operator'); insert into tags values (default, 'array'); insert into tags values (default, 'array-of-pointers'); insert into tags values (default, 'ascii'); insert into tags values (default, 'asp'); insert into tags values (default, 'aspi'); insert into tags values (default, 'assembler'); insert into tags values (default, 'assembly'); insert into tags values (default, 'associative-operation'); insert into tags values (default, 'autohotkey'); insert into tags values (default, 'automata-based-programming'); insert into tags values (default, 'automated-unit-testing'); insert into tags values (default, 'automation'); insert into tags values (default, 'booleanbabel'); insert into tags values (default, 'backend'); insert into tags values (default, 'back-face-culling'); insert into tags values (default, 'background-thread'); insert into tags values (default, 'backpropagation-neural-network'); insert into tags values (default, 'base-address'); insert into tags values (default, 'batch-file'); insert into tags values (default, 'batch-job'); insert into tags values (default, 'bcpl'); insert into tags values (default, 'bean'); insert into tags values (default, 'beanshell'); insert into tags values (default, 'binary-search'); insert into tags values (default, 'bind'); insert into tags values (default, 'bit-shift'); insert into tags values (default, 'bitwise-operators'); insert into tags values (default, 'block'); insert into tags values (default, 'block-level-element'); insert into tags values (default, 'bom'); insert into tags values (default, 'bool'); insert into tags values (default, 'boolean'); insert into tags values (default, 'boolean-data-type'); insert into tags values (default, 'bracket'); insert into tags values (default, 'branch'); insert into tags values (default, 'brooks'); insert into tags values (default, 'bug'); insert into tags values (default, 'bug-tracking'); insert into tags values (default, 'bugfairy'); insert into tags values (default, 'build-computer'); insert into tags values (default, 'bytecode'); insert into tags values (default, 'compiled-programming-languagec'); insert into tags values (default, 'c-sharp'); insert into tags values (default, 'c++'); insert into tags values (default, 'c#'); insert into tags values (default, 'camel-book'); insert into tags values (default, 'camelcase'); insert into tags values (default, 'captured-variable'); insert into tags values (default, 'cc'); insert into tags values (default, 'chaos-model'); insert into tags values (default, 'char'); insert into tags values (default, 'character-code'); insert into tags values (default, 'character-encoding'); insert into tags values (default, 'character-set'); insert into tags values (default, 'chaos-model'); insert into tags values (default, 'circuit-satisfiability-problem'); insert into tags values (default, 'class'); insert into tags values (default, 'class'); insert into tags values (default, 'classpath'); insert into tags values (default, 'clojure'); insert into tags values (default, 'clos'); insert into tags values (default, 'closure'); insert into tags values (default, 'clr'); insert into tags values (default, 'cobol'); insert into tags values (default, 'cocoa'); insert into tags values (default, 'cocoa-touch'); insert into tags values (default, 'code'); insert into tags values (default, 'code-refactoring'); insert into tags values (default, 'codepage'); insert into tags values (default, 'coffeescript'); insert into tags values (default, 'command-language'); insert into tags values (default, 'comment'); insert into tags values (default, 'common-business-oriented-language'); insert into tags values (default, 'common-gateway-interface'); insert into tags values (default, 'compilation'); insert into tags values (default, 'compile'); insert into tags values (default, 'compiler'); insert into tags values (default, 'complementarity'); insert into tags values (default, 'compute'); insert into tags values (default, 'computer-science'); insert into tags values (default, 'commutative-operation'); insert into tags values (default, 'concat'); insert into tags values (default, 'concatenation'); insert into tags values (default, 'concurrency'); insert into tags values (default, 'conditional-expression'); insert into tags values (default, 'conditional-statement'); insert into tags values (default, 'constant'); insert into tags values (default, 'constructor'); insert into tags values (default, 'constructor-chaining'); insert into tags values (default, 'content-migration'); insert into tags values (default, 'control-flow'); insert into tags values (default, 'cpan'); insert into tags values (default, 'cpl'); insert into tags values (default, 'crapplet'); insert into tags values (default, 'cs'); insert into tags values (default, 'csat'); insert into tags values (default, 'css'); insert into tags values (default, 'css-compressor'); insert into tags values (default, 'css-editor'); insert into tags values (default, 'curly-bracket'); insert into tags values (default, 'curry'); insert into tags values (default, 'cvs'); insert into tags values (default, 'cygwin'); insert into tags values (default, 'sparse-matrixd'); insert into tags values (default, 'darkbasic'); insert into tags values (default, 'dart'); insert into tags values (default, 'dataflow-programming'); insert into tags values (default, 'data-flow-analysis'); insert into tags values (default, 'data-flow-diagram'); insert into tags values (default, 'data-source'); insert into tags values (default, 'data-type'); insert into tags values (default, 'datalog'); insert into tags values (default, 'dde'); insert into tags values (default, 'dead-code'); insert into tags values (default, 'debug'); insert into tags values (default, 'debugger'); insert into tags values (default, 'debugging'); insert into tags values (default, 'declaration'); insert into tags values (default, 'declarative-programming'); insert into tags values (default, 'declare'); insert into tags values (default, 'decompiler'); insert into tags values (default, 'decrement'); insert into tags values (default, 'deductive-database'); insert into tags values (default, 'dense-matrix'); insert into tags values (default, 'dereference-operator'); insert into tags values (default, 'dependent-variable'); insert into tags values (default, 'developer'); insert into tags values (default, 'dhtml'); insert into tags values (default, 'die'); insert into tags values (default, 'diff'); insert into tags values (default, 'direct-address'); insert into tags values (default, 'discrete-optimization'); insert into tags values (default, 'dissembler'); insert into tags values (default, 'div'); insert into tags values (default, 'django'); insert into tags values (default, 'dml'); insert into tags values (default, 'do'); insert into tags values (default, 'dom'); insert into tags values (default, 'dragon-book'); insert into tags values (default, 'dribbleware'); insert into tags values (default, 'dump'); insert into tags values (default, 'dword'); insert into tags values (default, 'dylan-programming-language'); insert into tags values (default, 'dynamic-dump'); insert into tags values (default, 'exececlipse'); insert into tags values (default, 'ecmascript'); insert into tags values (default, 'eight-queens-problem'); insert into tags values (default, 'element'); insert into tags values (default, 'ellipsis'); insert into tags values (default, 'else'); insert into tags values (default, 'else-if'); insert into tags values (default, 'elsif'); insert into tags values (default, 'embedded-java'); insert into tags values (default, 'encapsulation'); insert into tags values (default, 'encode'); insert into tags values (default, 'endian'); insert into tags values (default, 'endless-loop'); insert into tags values (default, 'eof'); insert into tags values (default, 'epoch'); insert into tags values (default, 'eq'); insert into tags values (default, 'equal'); insert into tags values (default, 'error'); insert into tags values (default, 'errorlevel'); insert into tags values (default, 'esac'); insert into tags values (default, 'escape'); insert into tags values (default, 'escape-character'); insert into tags values (default, 'escape-sequence'); insert into tags values (default, 'eval'); insert into tags values (default, 'event'); insert into tags values (default, 'event-handler'); insert into tags values (default, 'event-listener'); insert into tags values (default, 'event-driven-programming'); insert into tags values (default, 'exec'); insert into tags values (default, 'exception'); insert into tags values (default, 'exception-handling'); insert into tags values (default, 'exists'); insert into tags values (default, 'exponent'); insert into tags values (default, 'exponential-backoff'); insert into tags values (default, 'expression'); insert into tags values (default, 'foreachf-programming-language'); insert into tags values (default, 'f#'); insert into tags values (default, 'false'); insert into tags values (default, 'fifth-generation-language'); insert into tags values (default, 'first-generation-language'); insert into tags values (default, 'first-class-object'); insert into tags values (default, 'flag'); insert into tags values (default, 'flat-file'); insert into tags values (default, 'floating-point'); insert into tags values (default, 'for'); insert into tags values (default, 'foreach'); insert into tags values (default, 'forth'); insert into tags values (default, 'forth-generation-language'); insert into tags values (default, 'fortran'); insert into tags values (default, 'framework'); insert into tags values (default, 'front-end'); insert into tags values (default, 'full-stack-developer'); insert into tags values (default, 'function'); insert into tags values (default, 'functional-programming'); insert into tags values (default, 'fuzz-testing'); insert into tags values (default, 'game-of-lifegame-of-life'); insert into tags values (default, 'gang-of-four'); insert into tags values (default, 'garbage-collection'); insert into tags values (default, 'gaussian-pyramid'); insert into tags values (default, 'gcc'); insert into tags values (default, 'ge'); insert into tags values (default, 'general-purpose-language'); insert into tags values (default, 'generation-language'); insert into tags values (default, 'genetic-programming'); insert into tags values (default, 'gigo'); insert into tags values (default, 'github'); insert into tags values (default, 'glitch'); insert into tags values (default, 'glob'); insert into tags values (default, 'glue-code'); insert into tags values (default, 'go-language'); insert into tags values (default, 'goto'); insert into tags values (default, 'gpl'); insert into tags values (default, 'grasshopper'); insert into tags values (default, 'gt'); insert into tags values (default, 'gtk'); insert into tags values (default, 'gw-basic'); insert into tags values (default, 'haskell-programming-languagehal'); insert into tags values (default, 'hard-code'); insert into tags values (default, 'hash'); insert into tags values (default, 'haskell'); insert into tags values (default, 'heap'); insert into tags values (default, 'hello-world'); insert into tags values (default, 'heuristic-evaluation'); insert into tags values (default, 'hex-editor'); insert into tags values (default, 'hdml'); insert into tags values (default, 'hiew'); insert into tags values (default, 'high-level-language'); insert into tags values (default, 'html'); insert into tags values (default, 'hungarian-notation'); insert into tags values (default, 'hwclock'); insert into tags values (default, 'hypertext-markup-language'); insert into tags values (default, 'iterationide'); insert into tags values (default, 'if-else'); insert into tags values (default, 'if-statement'); insert into tags values (default, 'immutable-object'); insert into tags values (default, 'imperative-programming'); insert into tags values (default, 'implicit-parallelism'); insert into tags values (default, 'increment'); insert into tags values (default, 'indirection-operator'); insert into tags values (default, 'inherent-error'); insert into tags values (default, 'inheritance'); insert into tags values (default, 'inline'); insert into tags values (default, 'input/output-statement'); insert into tags values (default, 'instance'); insert into tags values (default, 'instantiation'); insert into tags values (default, 'instructions'); insert into tags values (default, 'int'); insert into tags values (default, 'integer'); insert into tags values (default, 'integrated-development-environment'); insert into tags values (default, 'intellij-idea'); insert into tags values (default, 'intermediate-language'); insert into tags values (default, 'interpreted'); insert into tags values (default, 'interpreter'); insert into tags values (default, 'invalid'); insert into tags values (default, 'ioccc'); insert into tags values (default, 'ipc'); insert into tags values (default, 'isapi'); insert into tags values (default, 'iteration'); insert into tags values (default, 'javascript-or-js-logojava'); insert into tags values (default, 'java-champion'); insert into tags values (default, 'java-ee'); insert into tags values (default, 'java-me'); insert into tags values (default, 'java-native-language'); insert into tags values (default, 'java-reserved-words'); insert into tags values (default, 'javabean'); insert into tags values (default, 'javac'); insert into tags values (default, 'javafx'); insert into tags values (default, 'javascript'); insert into tags values (default, 'javascriptcore'); insert into tags values (default, 'javax'); insert into tags values (default, 'jbuilder'); insert into tags values (default, 'jcl'); insert into tags values (default, 'jdbc'); insert into tags values (default, 'jdk'); insert into tags values (default, 'jil'); insert into tags values (default, 'jit'); insert into tags values (default, 'jhtml'); insert into tags values (default, 'jni'); insert into tags values (default, 'jre'); insert into tags values (default, 'jscript'); insert into tags values (default, 'json'); insert into tags values (default, 'jsp'); insert into tags values (default, 'jsr'); insert into tags values (default, 'julia'); insert into tags values (default, 'jvm'); insert into tags values (default, 'karel'); insert into tags values (default, 'kit'); insert into tags values (default, 'kludge'); insert into tags values (default, 'kluge'); insert into tags values (default, 'looplabel'); insert into tags values (default, 'lambda-calculus'); insert into tags values (default, 'language'); insert into tags values (default, 'language-processor'); insert into tags values (default, 'lexical-analysis'); insert into tags values (default, 'lexicon'); insert into tags values (default, 'linker'); insert into tags values (default, 'lisp'); insert into tags values (default, 'live-script'); insert into tags values (default, 'literal'); insert into tags values (default, 'llvm'); insert into tags values (default, 'local-optimum'); insert into tags values (default, 'logic-programming'); insert into tags values (default, 'logical-operation'); insert into tags values (default, 'logo'); insert into tags values (default, 'lookup-table'); insert into tags values (default, 'loony-bin'); insert into tags values (default, 'loop'); insert into tags values (default, 'loophole'); insert into tags values (default, 'loosely-typed-language'); insert into tags values (default, 'low-level-language'); insert into tags values (default, 'library'); insert into tags values (default, 'lt'); insert into tags values (default, 'lua'); insert into tags values (default, 'lut'); insert into tags values (default, 'matlab-logomachine-language'); insert into tags values (default, 'magic-quotes'); insert into tags values (default, 'map'); insert into tags values (default, 'markup-language'); insert into tags values (default, 'math'); insert into tags values (default, 'matlab'); insert into tags values (default, 'mbean'); insert into tags values (default, 'memoization'); insert into tags values (default, 'mercurial'); insert into tags values (default, 'meta-character'); insert into tags values (default, 'metaclass'); insert into tags values (default, 'metalanguage'); insert into tags values (default, 'method'); insert into tags values (default, 'method-overloading'); insert into tags values (default, 'metro'); insert into tags values (default, 'middleware'); insert into tags values (default, 'mod'); insert into tags values (default, 'module'); insert into tags values (default, 'modulo'); insert into tags values (default, 'monkey-testing'); insert into tags values (default, 'monte-carlo-method'); insert into tags values (default, 'msdn'); insert into tags values (default, 'msvc'); insert into tags values (default, 'multi-pass-compiler'); insert into tags values (default, 'mumps'); insert into tags values (default, 'mutex'); insert into tags values (default, 'microsoft-dotnet'); insert into tags values (default, 'ne'); insert into tags values (default, 'dotnet'); insert into tags values (default, 'native-compiler'); insert into tags values (default, 'native-language'); insert into tags values (default, 'natural-language'); insert into tags values (default, 'nbsp'); insert into tags values (default, 'nda'); insert into tags values (default, 'nested-function'); insert into tags values (default, 'nested-loop-join'); insert into tags values (default, 'newline'); insert into tags values (default, 'nil-pointer'); insert into tags values (default, 'nim'); insert into tags values (default, 'node-js'); insert into tags values (default, 'nodelist'); insert into tags values (default, 'noncontiguous-data-structure'); insert into tags values (default, 'non-disclosure-agreement'); insert into tags values (default, 'nonexecutable-statement'); insert into tags values (default, 'no-operation-instructions'); insert into tags values (default, 'null'); insert into tags values (default, 'null-character'); insert into tags values (default, 'null-pointer'); insert into tags values (default, 'operatorobject-code'); insert into tags values (default, 'object-file'); insert into tags values (default, 'object-module'); insert into tags values (default, 'object-oriented-programming'); insert into tags values (default, 'objective-c'); insert into tags values (default, 'obfuscated-code'); insert into tags values (default, 'ocaml'); insert into tags values (default, 'octave'); insert into tags values (default, 'odbc'); insert into tags values (default, 'oop'); insert into tags values (default, 'one-pass-compiler'); insert into tags values (default, 'opcode'); insert into tags values (default, 'open-database-connectivity'); insert into tags values (default, 'opengl-polygon'); insert into tags values (default, 'operand'); insert into tags values (default, 'operator'); insert into tags values (default, 'operator-associatively'); insert into tags values (default, 'operator-precedence'); insert into tags values (default, 'or-operator'); insert into tags values (default, 'overflow-error'); insert into tags values (default, 'overload'); insert into tags values (default, 'practical-extraction-reporting-languagep-code'); insert into tags values (default, 'package'); insert into tags values (default, 'parenthesis'); insert into tags values (default, 'parse'); insert into tags values (default, 'pascal'); insert into tags values (default, 'pascal-case'); insert into tags values (default, 'pastebin'); insert into tags values (default, 'pdl'); insert into tags values (default, 'pear'); insert into tags values (default, 'perl'); insert into tags values (default, 'persistent-memory'); insert into tags values (default, 'personaljava'); insert into tags values (default, 'php'); insert into tags values (default, 'phrase-tag'); insert into tags values (default, 'pick'); insert into tags values (default, 'pickling'); insert into tags values (default, 'picojava'); insert into tags values (default, 'pipe'); insert into tags values (default, 'pixel-shader'); insert into tags values (default, 'pod'); insert into tags values (default, 'pointer'); insert into tags values (default, 'polymorphism'); insert into tags values (default, 'pop'); insert into tags values (default, 'positional-parameter'); insert into tags values (default, 'private'); insert into tags values (default, 'procedural-language'); insert into tags values (default, 'procedure'); insert into tags values (default, 'process'); insert into tags values (default, 'program'); insert into tags values (default, 'program-generator'); insert into tags values (default, 'program-listing'); insert into tags values (default, 'programmable'); insert into tags values (default, 'programmer'); insert into tags values (default, 'programming'); insert into tags values (default, 'programming-in-logic'); insert into tags values (default, 'programming-language'); insert into tags values (default, 'programming-tools'); insert into tags values (default, 'prolog'); insert into tags values (default, 'pseudocode'); insert into tags values (default, 'pseudolanguage'); insert into tags values (default, 'pseudo-operation'); insert into tags values (default, 'pseudo-random'); insert into tags values (default, 'public'); insert into tags values (default, 'purebasic'); insert into tags values (default, 'push'); insert into tags values (default, 'python'); insert into tags values (default, 'python-pickling'); insert into tags values (default, 'pythonic'); insert into tags values (default, 'qi'); insert into tags values (default, 'qt'); insert into tags values (default, 'quick-and-dirty'); insert into tags values (default, 'return-statementr-programming-language'); insert into tags values (default, 'race-condition'); insert into tags values (default, 'racket'); insert into tags values (default, 'rad'); insert into tags values (default, 'random'); insert into tags values (default, 'random-seed'); insert into tags values (default, 'rcs'); insert into tags values (default, 'rdf'); insert into tags values (default, 'react'); insert into tags values (default, 'react-native'); insert into tags values (default, 'real-number'); insert into tags values (default, 'recursion'); insert into tags values (default, 'recursive'); insert into tags values (default, 'regex'); insert into tags values (default, 'regular-expression'); insert into tags values (default, 'reia'); insert into tags values (default, 'relational-algebra'); insert into tags values (default, 'religion-of-chi'); insert into tags values (default, 'rem'); insert into tags values (default, 'remark'); insert into tags values (default, 'repeat-counter'); insert into tags values (default, 'repl'); insert into tags values (default, 'reserved-character'); insert into tags values (default, 'reserved-word'); insert into tags values (default, 'resource-description-framework'); insert into tags values (default, 'return-address'); insert into tags values (default, 'return-statement'); insert into tags values (default, 'reverse-engineering'); insert into tags values (default, 'revision-control'); insert into tags values (default, 'rom-basic'); insert into tags values (default, 'routine'); insert into tags values (default, 'routing-algorithm'); insert into tags values (default, 'rpg'); insert into tags values (default, 'ruby'); insert into tags values (default, 'run-time'); insert into tags values (default, 'rust'); insert into tags values (default, 'spaghetti-codes-expression'); insert into tags values (default, 'safe-font'); insert into tags values (default, 'sandbox'); insert into tags values (default, 'scala'); insert into tags values (default, 'scanf'); insert into tags values (default, 'schema-matching'); insert into tags values (default, 'scheme-programming-language'); insert into tags values (default, 'scratch'); insert into tags values (default, 'sdk'); insert into tags values (default, 'second-generation-language'); insert into tags values (default, 'section'); insert into tags values (default, 'security-descriptor-definition-language'); insert into tags values (default, 'seed'); insert into tags values (default, 'segfault'); insert into tags values (default, 'separator'); insert into tags values (default, 'sequence'); insert into tags values (default, 'server-side'); insert into tags values (default, 'server-side-scripting'); insert into tags values (default, 'servlet'); insert into tags values (default, 'sgml'); insert into tags values (default, 'shebang'); insert into tags values (default, 'shell-scripts'); insert into tags values (default, 'shift'); insert into tags values (default, 'short-circuit-operator'); insert into tags values (default, 'signedness'); insert into tags values (default, 'simulated-annealing'); insert into tags values (default, 'single-step'); insert into tags values (default, 'smalltalk'); insert into tags values (default, 'smil'); insert into tags values (default, 'snippet'); insert into tags values (default, 'soap'); insert into tags values (default, 'socket'); insert into tags values (default, 'soft'); insert into tags values (default, 'software-development-phases'); insert into tags values (default, 'software-development-process'); insert into tags values (default, 'software-engineering'); insert into tags values (default, 'software-library'); insert into tags values (default, 'software-life-cycle'); insert into tags values (default, 'source'); insert into tags values (default, 'source-code'); insert into tags values (default, 'source-computer'); insert into tags values (default, 'source-data'); insert into tags values (default, 'sourceforge'); insert into tags values (default, 'spaghetti-code'); insert into tags values (default, 'sparse-matrix'); insert into tags values (default, 'sparsity'); insert into tags values (default, 'special-purpose-language'); insert into tags values (default, 'spl'); insert into tags values (default, 'spooling'); insert into tags values (default, 'sql'); insert into tags values (default, 'stack'); insert into tags values (default, 'stack-pointer'); insert into tags values (default, 'standard-attribute'); insert into tags values (default, 'statement'); insert into tags values (default, 'stdin'); insert into tags values (default, 'strong-typed-language'); insert into tags values (default, 'stubroutine'); insert into tags values (default, 'stylesheet'); insert into tags values (default, 'subprogram'); insert into tags values (default, 'subroutine'); insert into tags values (default, 'subscript'); insert into tags values (default, 'substring'); insert into tags values (default, 'subversion'); insert into tags values (default, 'superclass'); insert into tags values (default, 'switch-statement'); insert into tags values (default, 'syntactic-sugar'); insert into tags values (default, 'syntax-error'); insert into tags values (default, 'system-development'); insert into tags values (default, 'systems-engineer'); insert into tags values (default, 'systems-programming-language'); insert into tags values (default, 'tupletail-recursion'); insert into tags values (default, 'tcl'); insert into tags values (default, 'tcl/tk'); insert into tags values (default, 'ternary-operator'); insert into tags values (default, 'theoretical-computer-science-'); insert into tags values (default, 'third-generation-language'); insert into tags values (default, 'thread'); insert into tags values (default, 'thunk'); insert into tags values (default, 'tk'); insert into tags values (default, 'token'); insert into tags values (default, 'transcompiler'); insert into tags values (default, 'true'); insert into tags values (default, 'true-basic'); insert into tags values (default, 'trunk'); insert into tags values (default, 'tuple'); insert into tags values (default, 'turbo-pascal'); insert into tags values (default, 'turing-completeness'); insert into tags values (default, 'unary-operator'); insert into tags values (default, 'undefined'); insert into tags values (default, 'undefined-variable'); insert into tags values (default, 'underflow'); insert into tags values (default, 'unescape'); insert into tags values (default, 'unit-test'); insert into tags values (default, 'unshift'); insert into tags values (default, 'value'); insert into tags values (default, 'var'); insert into tags values (default, 'variable'); insert into tags values (default, 'vb'); insert into tags values (default, 'vector'); insert into tags values (default, 'vhdl'); insert into tags values (default, 'vim'); insert into tags values (default, 'visual-basic'); insert into tags values (default, 'visual-studio'); insert into tags values (default, 'void'); insert into tags values (default, 'waterfall-model'); insert into tags values (default, 'web-development'); insert into tags values (default, 'webgl'); insert into tags values (default, 'while'); insert into tags values (default, 'whole-number'); insert into tags values (default, 'wml'); insert into tags values (default, 'workspace'); insert into tags values (default, 'xml'); insert into tags values (default, 'xna'); insert into tags values (default, 'xor-operator'); insert into tags values (default, 'xoxo'); insert into tags values (default, 'xsl'); insert into tags values (default, 'xslt'); insert into tags values (default, 'y-combinator'); insert into tags values (default, 'yaml'); insert into tags values (default, 'z-buffering'); insert into tags values (default, 'zombie'); down: drop table users; drop table questions; drop table comments; drop table tags; drop table question_votes; drop table comment_votes; drop table snippets; ================================================ FILE: platform/migrations/migrations/20180901170431-triggers.sql ================================================ up: drop trigger if exists question_vote_insert_trigger; delimiter $ create trigger question_vote_insert_trigger after insert on question_votes for each row begin update questions set score = score + NEW.value where question_id = NEW.question_id; end$ delimiter ; drop trigger if exists question_vote_delete_trigger; delimiter $ create trigger question_vote_delete_trigger after delete on question_votes for each row begin update questions set score = score - OLD.value where question_id = OLD.question_id; end$ delimiter ; drop trigger if exists comment_vote_insert_trigger; delimiter $ create trigger comment_vote_insert_trigger after insert on comment_votes for each row begin update comments set score = score + NEW.value where comment_id = NEW.comment_id; end$ delimiter ; drop trigger if exists comment_vote_delete_trigger; delimiter $ create trigger comment_vote_delete_trigger after delete on comment_votes for each row begin update comments set score = score - OLD.value where comment_id = OLD.comment_id; end$ delimiter ; drop trigger if exists comment_insert_trigger; delimiter $ create trigger comment_insert_trigger after insert on comments for each row begin update questions set comments = comments + 1 where question_id = NEW.question_id; end$ delimiter ; drop trigger if exists comment_delete_trigger; delimiter $ create trigger comment_delete_trigger after delete on comments for each row begin update questions set comments = comments - 1 where question_id = OLD.question_id; end$ delimiter ; down: ================================================ FILE: platform/migrations/migrations/20180903004942-display-name.sql ================================================ up: alter table users add display_name varchar(64) not null after is_staff; update users set display_name = username; down: alter table users drop column display_name; ================================================ FILE: platform/migrations/migrations/20180903013450-question-tags.sql ================================================ up: create table question_tags ( question_tag_id int unsigned not null auto_increment, question_id int not null default 0, tag_id int not null default 0, primary key (question_tag_id), key question_id (question_id), key tag_id (tag_id) )engine=innodb default charset=utf8; down: drop table question_tags; ================================================ FILE: platform/migrations/migrations/20180903180404-default-avatar.sql ================================================ up: alter table users modify avatar_url varchar(128) not null default '/avatars/default.png' after discord_api; down: alter table users modify avatar_url varchar(128) null after discord_api; ================================================ FILE: platform/migrations/migrations/20180903222426-views-field.sql ================================================ up: alter table questions add views int unsigned not null default 0 after score; down: alter table questions drop column views; ================================================ FILE: platform/migrations/migrations/20180905220531-notification-table.sql ================================================ up: create table notifications ( notification_id int unsigned not null auto_increment, user_id int unsigned not null, type tinyint unsigned not null, entity_type tinyint unsigned not null, entity_id int unsigned not null, message varchar(512) not null, created_at datetime not null, primary key (notification_id), key user_id (user_id), key type (type), key entity_type (entity_type), key entity_id (entity_id) )engine=innodb default charset=utf8; down: drop table notifications; ================================================ FILE: platform/migrations/migrations/20180908000333-new-tags.sql ================================================ up: truncate tags; insert into tags values (default, 'java'); insert into tags values (default, 'c'); insert into tags values (default, 'python'); insert into tags values (default, 'c++'); insert into tags values (default, 'visual-basic-dot-net'); insert into tags values (default, 'c#'); insert into tags values (default, 'php'); insert into tags values (default, 'javascript'); insert into tags values (default, 'sql'); insert into tags values (default, 'objective-c'); insert into tags values (default, 'delphi-object-pascal'); insert into tags values (default, 'ruby'); insert into tags values (default, 'matlab'); insert into tags values (default, 'assembly-language'); insert into tags values (default, 'swift'); insert into tags values (default, 'go'); insert into tags values (default, 'perl'); insert into tags values (default, 'r'); insert into tags values (default, 'pl-sql'); insert into tags values (default, 'visual-basic'); insert into tags values (default, 'sas'); insert into tags values (default, 'dart'); insert into tags values (default, 'd'); insert into tags values (default, 'scratch'); insert into tags values (default, 'f#'); insert into tags values (default, 'cobol'); insert into tags values (default, 'scala'); insert into tags values (default, 'abap'); insert into tags values (default, 'fortran'); insert into tags values (default, 'lua'); insert into tags values (default, 'rust'); insert into tags values (default, 'transact-sql'); insert into tags values (default, 'lisp'); insert into tags values (default, 'groovy'); insert into tags values (default, 'labview'); insert into tags values (default, 'prolog'); insert into tags values (default, 'ada'); insert into tags values (default, 'logo'); insert into tags values (default, 'julia'); insert into tags values (default, 'haskell'); insert into tags values (default, 'apex'); insert into tags values (default, 'kotlin'); insert into tags values (default, 'bash'); insert into tags values (default, 'ladder-logic'); insert into tags values (default, 'alice'); insert into tags values (default, 'tcl'); insert into tags values (default, 'clojure'); insert into tags values (default, 'postscript'); insert into tags values (default, 'scheme'); insert into tags values (default, 'awk'); insert into tags values (default, 'actionscript'); insert into tags values (default, 'bc'); insert into tags values (default, 'bourne-shell'); insert into tags values (default, 'c-shell'); insert into tags values (default, 'cfml'); insert into tags values (default, 'coffeescript'); insert into tags values (default, 'common-lisp'); insert into tags values (default, 'crystal'); insert into tags values (default, 'ct'); insert into tags values (default, 'elixir'); insert into tags values (default, 'elm'); insert into tags values (default, 'emacs-lisp'); insert into tags values (default, 'erlang'); insert into tags values (default, 'forth'); insert into tags values (default, 'hack'); insert into tags values (default, 'icon'); insert into tags values (default, 'inform'); insert into tags values (default, 'io'); insert into tags values (default, 'j'); insert into tags values (default, 'korn-shell'); insert into tags values (default, 'livecode'); insert into tags values (default, 'maple'); insert into tags values (default, 'mercury'); insert into tags values (default, 'ml'); insert into tags values (default, 'monkey'); insert into tags values (default, 'ocaml'); insert into tags values (default, 'opencl'); insert into tags values (default, 'openedge-abl'); insert into tags values (default, 'oz'); insert into tags values (default, 'powershell'); insert into tags values (default, 'q'); insert into tags values (default, 'racket'); insert into tags values (default, 'ring'); insert into tags values (default, 'rpg'); insert into tags values (default, 's'); insert into tags values (default, 'snap!'); insert into tags values (default, 'spark'); insert into tags values (default, 'spss'); insert into tags values (default, 'tex'); insert into tags values (default, 'typescript'); insert into tags values (default, 'vhdl'); insert into tags values (default, 'emkc'); insert into tags values (default, 'linux'); insert into tags values (default, 'ubuntu'); down: truncate tags; ================================================ FILE: platform/migrations/migrations/20180915035412-code-rooms.sql ================================================ up: create table code_rooms ( code_room_id int unsigned not null auto_increment, user_id int unsigned null, hash varchar(40) not null, code mediumtext not null, created_at datetime not null, primary key (code_room_id), key user_id (user_id), key hash (hash), key created_at (created_at) )engine=innodb default charset=utf8; down: drop table code_rooms; ================================================ FILE: platform/migrations/migrations/20180917013146-snippet-language.sql ================================================ up: alter table snippets add language varchar(32) not null after hash; update snippets set language = 'javascript'; down: alter table snippets drop column language; ================================================ FILE: platform/migrations/migrations/20180930153901-video-requests.sql ================================================ up: create table video_requests ( video_request_id int unsigned not null auto_increment, user_id int not null, name varchar(255) not null, created_at datetime not null, primary key (video_request_id), key user_id (user_id) )engine=innodb default charset=utf8; create table video_request_votes ( video_request_vote_id int unsigned not null auto_increment, video_request_id int unsigned not null, user_id int unsigned not null, primary key (video_request_vote_id), key video_request_id (video_request_id), key user_id (user_id) )engine=innodb default charset=utf8; down: drop table video_requests; drop table video_request_votes; ================================================ FILE: platform/migrations/migrations/20181005005500-challenges-tables.sql ================================================ up: create table challenges ( challenge_id int unsigned not null auto_increment, difficulty tinyint unsigned not null, points int unsigned not null, folder varchar(64) not null, name varchar(128) not null, description varchar(512) not null, primary key (challenge_id), key difficulty (difficulty), key points (points) )engine=innodb default charset=utf8; insert into challenges values (1, 1, 10, '1_reverse_string', 'Reverse a string', 'Just take any given string and output it in reverse, pretty easy, right?'); create table user_challenges ( user_challenge_id int unsigned not null auto_increment, user_id int unsigned not null, challenge_id int unsigned not null, language varchar(8) not null, solution mediumtext not null, created_at datetime not null, primary key (user_challenge_id), key user_id (user_id), key challenge_id (challenge_id), key language (language), key created_at (created_at) )engine=innodb default charset=utf8; down: drop table challenges; drop table user_challenges; ================================================ FILE: platform/migrations/migrations/20181021204739-chats-table.sql ================================================ up: create table discord_chat_messages ( discord_chat_message_id int unsigned not null auto_increment, hash varchar(40) not null, channel varchar(32) not null, user varchar(32) not null, message varchar(8192) not null, created_at datetime not null, primary key (discord_chat_message_id), unique hash (hash), key channel (channel), key user (user), key created_at (created_at) )engine=innodb default charset=utf8; down: drop table discord_chat_messages; ================================================ FILE: platform/migrations/migrations/20181107035714-new-challenge.sql ================================================ up: insert into challenges values (2, 1, 10, '2_number_frequency', 'Count number frequency', 'Take a string of numbers and output the one which appears the most.'); down: delete from challenges where challenge_id = 2; ================================================ FILE: platform/migrations/migrations/20181111035714-new-challenge.sql ================================================ up: insert into challenges values (3, 1, 10, '3_list_sum', 'Sum a list of numbers', 'Take a string of comma separated numbers and print out the sum.'); down: delete from challenges where challenge_id = 3; ================================================ FILE: platform/migrations/migrations/20181119035714-new-challenge.sql ================================================ up: insert into challenges values (4, 3, 50, '4_invalid_json', 'Detect and fix invalid JSON', 'Take an invalid JSON string and figure out where the errors are and make it valid.'); insert into challenges values (5, 2, 30, '5_binary_convert', 'Convert string to binary', 'Take three lowercase letters and print out binary.'); down: delete from challenges where challenge_id = 4; delete from challenges where challenge_id = 5; ================================================ FILE: platform/migrations/migrations/20181121035714-discord-rank-field.sql ================================================ up: alter table users add discord_rank tinyint unsigned default null after discord_api; down: alter table users drop column discord_rank; ================================================ FILE: platform/migrations/migrations/20181229135021-new-challenge.sql ================================================ up: insert into challenges values (6, 2, 30, '6_fibonacci_sequence', 'Fibonacci Numbers', 'Start with one Fibonacci sequence number, then calculate more from there.'); insert into challenges values (7, 2, 30, '7_check_permutation', 'Check scrambled string', 'Given two strings of equal length, figure out if one is a scramble of the other.'); down: delete from challenges where challenge_id = 6; delete from challenges where challenge_id = 7; ================================================ FILE: platform/migrations/migrations/20190104235301-new-challenge.sql ================================================ up: insert into challenges values (8, 1, 10, '8_sort_integers', 'Integer list sorting', 'Take a list of integers and print it after sorting it in descending order.'); insert into challenges values (9, 3, 50, '9_roman_numerals', 'Roman Numeral conversion', 'Take a roman numeral(<1000 in value) and print its corresponding value in the decimal system of numbers.'); down: delete from challenges where challenge_id = 8; delete from challenges where challenge_id = 9; ================================================ FILE: platform/migrations/migrations/20190405004828-new-challenge.sql ================================================ up: insert into challenges values (10, 3, 50, '10_pig_latin', 'Pig latin translator', 'Take a sentence/phrase in pig latin, translate it to English.'); down: delete from challenges where challenge_id = 10; ================================================ FILE: platform/migrations/migrations/20190611224428-new-challenge.sql ================================================ up: insert into challenges values (11, 2, 30, '11_array_neighbor', 'Zipper merge', 'Merge two arrays in a zipper-like fashion.'); update challenges set difficulty = 3, points = 50 where challenge_id = 10; down: update challenges set difficulty = 1, points = 10 where challenge_id = 10; delete from challenges where challenge_id = 11; ================================================ FILE: platform/migrations/migrations/20190622133430-new-challenge.sql ================================================ up: insert into challenges values (12, 1, 10, '12_longest_word', 'Find Longest Word', 'Given a string with multiple words, return the longest word.'); down: delete from challenges where challenge_id = 12; ================================================ FILE: platform/migrations/migrations/20190622224428-discord-id-chat-messages.sql ================================================ up: alter table discord_chat_messages add discord_id varchar(32) not null after user; alter table discord_chat_messages add index discord_id (discord_id); down: alter table discord_chat_messages drop column discord_id; ================================================ FILE: platform/migrations/migrations/20190624224428-script-town.sql ================================================ up: create table cli_scripts ( cli_script_id int unsigned not null auto_increment, user_id int unsigned not null, is_public tinyint unsigned not null default 0, is_safe tinyint unsigned not null default 0, title varchar(256) not null, content mediumtext not null, created_at datetime not null, primary key (cli_script_id), key user_id (user_id), key is_public (is_public), key is_safe (is_safe), key title (title), key created_at (created_at) )engine=innodb default charset=utf8; down: drop table cli_scripts; ================================================ FILE: platform/migrations/migrations/20191023224428-stickers.sql ================================================ up: create table sticker_orders ( sticker_order_id int unsigned not null auto_increment, is_fulfilled tinyint unsigned not null default 0, tx varchar(128) null, coupon varchar(128) null, quantity int unsigned not null, cost decimal(5,2) null, name varchar(256) not null, email varchar(256) not null, address varchar(256) not null, created_at datetime not null, primary key (sticker_order_id), key is_fulfilled (is_fulfilled), key created_at (created_at) )engine=innodb default charset=utf8; down: drop table sticker_orders; ================================================ FILE: platform/migrations/migrations/20191101133430-new-challenge.sql ================================================ up: insert into challenges values (13, 2, 30, '13_most_common_character', 'Find Most Common Characters', 'Given a string with multiple words, find the most common character.'); down: delete from challenges where challenge_id = 13; ================================================ FILE: platform/migrations/migrations/20191201133430-new-challenge.sql ================================================ up: insert into challenges values (14, 2, 30, '14_number_digit_sum', 'Digit Sum Even or Odd', 'Given a number, find out if the sum of the digits is even or odd.'); down: delete from challenges where challenge_id = 14; ================================================ FILE: platform/migrations/migrations/20200711133430-piston-stats.sql ================================================ up: create table piston_runs ( piston_run_id int unsigned not null auto_increment, server varchar(64) not null, user varchar(32) not null, discord_id varchar(32) not null, language varchar(32) not null, source text, created_at datetime not null, primary key (piston_run_id), key server (server), key user (user), key discord_id (discord_id), key language (language), key created_at (created_at) )engine=innodb default charset=utf8; down: drop table piston_runs; ================================================ FILE: platform/migrations/migrations/20200711133431-piston-stats.sql ================================================ up: alter table piston_runs change discord_id user_id varchar(32) not null; alter table piston_runs add server_id varchar(32) not null after server; down: alter table piston_runs change user_id discord_id varchar(32) not null; alter table piston_runs drop column server_id; ================================================ FILE: platform/migrations/migrations/20200802133431-new-challenge.sql ================================================ up: insert into challenges values (15, 1, 10, '15_binary_cookie', 'Find The Cookie', 'Given a binary string, a cookie, find its place in the binary cookie jar.'); down: delete from challenges where challenge_id = 15; ================================================ FILE: platform/migrations/migrations/20200813092823-new-challenge.sql ================================================ up: insert into challenges values (16, 1, 10, '16_spiral_corner', 'Spiral Sum', 'Given the size of a spiral, calculate the sum of the four corners.'); down: delete from challenges where challenge_id = 16; ================================================ FILE: platform/migrations/migrations/20200825133432-new-challenge.sql ================================================ up: insert into challenges values (17, 2, 30, '17_quadratic_calculator', 'Answer The Quadratic', 'Given a quadratic find the decimal values of x'); down: delete from challenges where challenge_id = 17; ================================================ FILE: platform/migrations/migrations/20200830224428-contests-tables.sql ================================================ up: create table contests ( contest_id int unsigned not null auto_increment, name varchar(128) not null, description mediumtext not null, start_date datetime not null, end_date datetime not null, input text not null, output text not null, created_at datetime not null, primary key (contest_id), key start_date (start_date), key end_date (end_date), key created_at (created_at) )engine=innodb default charset=utf8; insert into contests values (1, 'First Contest', 'Test Description', '2020-08-29 00:00:00', '2020-09-20 23:59:59', '5', '5', now()); create table contest_submissions ( contest_submission_id int unsigned not null auto_increment, user_id int unsigned not null, contest_id int unsigned not null, language varchar(32) not null, solution mediumtext not null, length int unsigned not null, award_place int unsigned null, award_points int unsigned null, created_at datetime not null, primary key (contest_submission_id), key user_id (user_id), key contest_id (contest_id), key language (language), key award_place (award_place), key award_points (award_points), key created_at (created_at) )engine=innodb default charset=utf8; insert into contest_submissions values (default, 1, 1, 'javascript', 'console.log(1)', 14, null, null, now()); down: drop table contests; drop table contest_submissions; ================================================ FILE: platform/migrations/migrations/20200905203703-contest-draft-field.sql ================================================ up: alter table contests add draft tinyint unsigned not null default 1 after contest_id; down: alter table contests drop column draft; ================================================ FILE: platform/migrations/migrations/20200918012206-cleanup-old-tables.sql ================================================ up: drop table code_rooms; drop table comment_votes; drop table comments; drop table notifications; drop table question_tags; drop table question_votes; drop table questions; drop table video_request_votes; drop table video_requests; down: CREATE TABLE `code_rooms` ( `code_room_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned DEFAULT NULL, `hash` varchar(40) NOT NULL, `code` mediumtext NOT NULL, `created_at` datetime NOT NULL, PRIMARY KEY (`code_room_id`), KEY `user_id` (`user_id`), KEY `hash` (`hash`), KEY `created_at` (`created_at`) ) ENGINE=InnoDB AUTO_INCREMENT=274 DEFAULT CHARSET=utf8; CREATE TABLE `comment_votes` ( `comment_vote_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `comment_id` int(10) unsigned NOT NULL, `user_id` int(10) unsigned NOT NULL, `value` tinyint(4) NOT NULL, PRIMARY KEY (`comment_vote_id`), KEY `comment_id` (`comment_id`), KEY `user_id` (`user_id`), KEY `value` (`value`) ) ENGINE=InnoDB AUTO_INCREMENT=372 DEFAULT CHARSET=utf8; CREATE TABLE `comments` ( `comment_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `question_id` int(10) unsigned NOT NULL, `base_id` int(10) unsigned DEFAULT NULL, `parent_id` int(10) unsigned DEFAULT NULL, `user_id` int(10) unsigned NOT NULL, `comment` mediumtext NOT NULL, `depth` int(11) NOT NULL DEFAULT '0', `score` int(11) NOT NULL DEFAULT '0', `created_at` datetime NOT NULL, PRIMARY KEY (`comment_id`), KEY `question_id` (`question_id`), KEY `base_id` (`base_id`), KEY `parent_id` (`parent_id`), KEY `user_id` (`user_id`), KEY `depth` (`depth`), KEY `score` (`score`), KEY `created_at` (`created_at`) ) ENGINE=InnoDB AUTO_INCREMENT=316 DEFAULT CHARSET=utf8; CREATE TABLE `notifications` ( `notification_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL, `type` tinyint(3) unsigned NOT NULL, `entity_type` tinyint(3) unsigned NOT NULL, `entity_id` int(10) unsigned NOT NULL, `message` varchar(512) NOT NULL, `created_at` datetime NOT NULL, PRIMARY KEY (`notification_id`), KEY `user_id` (`user_id`), KEY `type` (`type`), KEY `entity_type` (`entity_type`), KEY `entity_id` (`entity_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `question_tags` ( `question_tag_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `question_id` int(11) NOT NULL DEFAULT '0', `tag_id` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`question_tag_id`), KEY `question_id` (`question_id`), KEY `tag_id` (`tag_id`) ) ENGINE=InnoDB AUTO_INCREMENT=84 DEFAULT CHARSET=utf8; CREATE TABLE `question_votes` ( `question_vote_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `question_id` int(10) unsigned NOT NULL, `user_id` int(10) unsigned NOT NULL, `value` tinyint(4) NOT NULL, PRIMARY KEY (`question_vote_id`), KEY `question_id` (`question_id`), KEY `user_id` (`user_id`), KEY `value` (`value`) ) ENGINE=InnoDB AUTO_INCREMENT=157 DEFAULT CHARSET=utf8; CREATE TABLE `questions` ( `question_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL, `title` varchar(128) NOT NULL, `question` mediumtext NOT NULL, `score` int(11) NOT NULL DEFAULT '0', `views` int(10) unsigned NOT NULL DEFAULT '0', `comments` int(10) unsigned NOT NULL DEFAULT '0', `created_at` datetime NOT NULL, PRIMARY KEY (`question_id`), KEY `user_id` (`user_id`), KEY `score` (`score`), KEY `comments` (`comments`), KEY `created_at` (`created_at`) ) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8; CREATE TABLE `video_request_votes` ( `video_request_vote_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `video_request_id` int(10) unsigned NOT NULL, `user_id` int(10) unsigned NOT NULL, PRIMARY KEY (`video_request_vote_id`), KEY `video_request_id` (`video_request_id`), KEY `user_id` (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=374 DEFAULT CHARSET=utf8; CREATE TABLE `video_requests` ( `video_request_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `name` varchar(255) NOT NULL, `created_at` datetime NOT NULL, PRIMARY KEY (`video_request_id`), KEY `user_id` (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8; ================================================ FILE: platform/migrations/migrations/20200918012216-award-table.sql ================================================ up: create table awards ( award_id int unsigned not null auto_increment, type int unsigned not null, points int unsigned not null, user_id int unsigned not null, ref_type int unsigned null, ref_id int unsigned null, created_at datetime not null, primary key (award_id), key type (type), key points (points), key user_id (user_id), key ref_type (ref_type), key ref_id (ref_id), key created_at (created_at) )engine=innodb default charset=utf8; down: drop table awards; ================================================ FILE: platform/migrations/migrations/20210117125516-add-html-to-challenges.sql ================================================ up: alter table challenges add html mediumtext default null after description; update challenges set html = '

Instructions

Your input variable could contain a variety of string values. Regardless of value, you''ll need to reverse the string and print it out.

Inputs

value1
The string to reverse

Sample Test Cases

Simple string
value1 cat
output tac
Complex string
value1 sd#$)(&*09&M0
output 0M&90*&()$#ds
' where folder = '1_reverse_string'; update challenges set html = '

Instructions

Your input variable will be a string of many numbers. You''ll need to print out the number which appears the most times in that string.

Inputs

value1
String of numbers

Sample Test Cases

String of numbers
value1 08989082882348823838
output 8
' where folder = '2_number_frequency'; update challenges set html = '

Instructions

Your input variable could contain a list of integer values. Regardless of value, you''ll need to print out the sum of the list.

Inputs

value1
The list to add

Sample Test Cases

Short list
value1 2,5,1
output 8
Long list
value1 3,9,10,5,2,7,9,2
output 47
' where folder = '3_list_sum'; update challenges set html = '

Instructions

Your input variable will contain a string of invalid JSON. However, each invalid JSON string received can be fixed by making one or more single character changes. Only three possible things may be wrong with the JSON string: 1) missing leading or trailing brace, 2) unquoted JSON string value, 3) missing comma between properties.

Inputs

value1
A string of invalid JSON

Sample Test Cases

Single Problem
value1 {"name":"em"
output {"name":"em"}
Multiple Problems
value1 "name":"em
output {"name":"em"}
' where folder = '4_invalid_json'; update challenges set html = '

Instructions

Your input variable will contain a string of three lowercase letters. From this, you''ll need to convert it to binary and print out the 24 number representation of those letters in binary.

Inputs

value1
Three lowercase letters

Sample Test Case

Letter
value1 abc
output 011000010110001001100011
' where folder = '5_binary_convert'; update challenges set html = '

Instructions

Your input variable will contain a fibonacci sequence number. Your job is to calculate the next n digits.

Inputs

value1
The starting number

value2
n number to calculate after value1

Sample Test Cases

Small Number
value1 5
value2 2
output 8,13
Large Numbers
value1 34
value2 7
output 55,89,144,233,377,610,987
' where folder = '6_fibonacci_sequence'; update challenges set html = '

Instructions

Your input variable will contain two strings of equal length, separated by a comma. You have to check whether the second string is a permutation of the first string. Print "Yes" if it is, "No" if not.

Inputs

value1
Two strings separated by a comma

Sample Test Case

Permutation
value1 brian,airbn
output Yes
' where folder = '7_check_permutation'; update challenges set html = '

Instructions

Your input variable will contain a list of integers, you have to sort the list in descending order and print it.

Inputs

value1
The list to sort

Sample Test Cases

Short list
value1 3,4,-9
output 4,3,-9
Long list
value1 3,9,10,5,2,7,9,2
output 10,9,9,7,5,3,2,2
' where folder = '8_sort_integers'; update challenges set html = '

Instructions

Your input variable will contain a roman numeral less than 1000 in value. Print the corresponding value of the roman numeral in the decimal system of numbers.

Inputs

value1
The roman numeral

Sample Test Cases

Small Roman Numeral
value1 VI
output 6
Large Roman Numeral
value1 CDVII
output 407
' where folder = '9_roman_numerals'; update challenges set html = '

Instructions

Your input variable will contain a sentence/phrase in pig latin. Your job is to translate it to english. You add "yay" if the word starts with a vowel. Otherwise move the starting consonant sequence (w, wr, sch, ...) to the end of the word and add "ay" plus a dash.

Inputs

value1
Sentence/phrase in pig latin.

Sample Test Cases

Short phrase
value1 ayay imple-say est-tay ase-cay
output a simple test case
Long phrase
value1 ig-pay atin-lay isyay usedyay inyay ools-schay o-tay each-tay anguage-lay onstructs-cay
output pig latin is used in schools to teach language constructs
' where folder = '10_pig_latin'; update challenges set html = '

Instructions

You''ll get two inputs, each will be a comma separated list of numbers. Each input will contain the same amount of numbers. You''ll need to merge the two lists by inserting numbers from value2 into value1. Each number from value2 should be inserted every other number starting after the first number in value 1.

Inputs

value1
First comma separated list of numbers

value2
Second comma separated list of numbers

Sample Test Cases

Short List
value1 9,5
value2 7,10
output 9,7,5,10
Large List
value1 34,18,4,102
value2 15,19,120,64
output 34,15,18,19,4,120,102,64
' where folder = '11_array_neighbor'; update challenges set html = '

Instructions

You''ll get one input, a string with multiple words. Return the longest word in the string. If the input contains multiple words that are the largest length, return a string that contains all of the words in the same order they are provided. All returned strings should be lowercase and trimmed of whitespace.

Inputs

value1
Single string with multiple words.

Sample Test Cases

Regular
value1 run,barn,yellow,barracuda,shark,fish,swim
output barracuda
Same Size
value1 fishes,sam,gollum,sauron,frodo,balrog
output fishes,gollum,sauron,balrog
' where folder = '12_longest_word'; update challenges set html = '

Instructions

You will be given a string and your job is to find the most common character in that string. If there are two characters which appear the same amount of times and are the largest amount, you should output both separated by a comma in the order they first appeared.

Inputs

value1
A long or short string

Sample Test Cases

Short phrase
value1 A test case
output t,e,s
Long phrase
value1 The way this mode works is by looking for the mode of the characters of any given string
output o
' where folder = '13_most_common_character'; update challenges set html = '

Instructions

You will be given an integer and your job is to determine the sum made up by each individual digit. Once you have the sum, determine if the sum is even or odd and then print out either "even" or "odd".

Inputs

value1
An integer

Sample Test Cases

Short number
value1 31
output even
Long number
value1 662638
output odd
' where folder = '14_number_digit_sum'; update challenges set html = '

Instructions

You''ll get one input string formatted as ''[cookie],[cookie jar]''. Return the sum of the starting index number of the cookie in the cookie jar and the ending index number of the cookie in the cookie jar.

Inputs

value1
Single string formatted as ''[cookie],[cookie jar]''.

Sample Test Cases

Regular Cookie
value1 10000101,100001111000010110100001
output 23
Big Cookie
value1 1010100100110110,1111010000011111111000111010100100110110
output 63
' where folder = '15_binary_cookie'; update challenges set html = '

Instructions

Given a size for a number spiral, you count clockwise with numbers. A 3x3 is 3 columns by 3 rows.
        2x2  3x3    4x4
        1 2  7 8 9   7  8  9 10
        4 3  6 1 2   6  1  2 11
             5 4 3   5  4  3 12
                    16 15 14 13
The input gives you the size of the spiral that you need to create. The goal is to sum the corners. If you look at the 3x3 grid, the numbers at the corners are 7, 9, 3, and 5. If you sum these, you get 24, which is the answer. Write a program that will provide the sum of the corners for any sized spiral up to 100x100.

Inputs

value1
Single string formatted as ''numberxnumber''.

Sample Test Cases

Sample Input 1
value1 3x3
output 24
Sample Input 2
value1 4x4
output 46
' where folder = '16_spiral_corner'; update challenges set html = '

Instructions

You''ll get one input string formatted like ''ax^2+bx+c=0''. Return the two decimal values of x like ''x_value1,x_value2''.

Inputs

value1
Single string formatted like ''ax^2+bx+c=0''.

Sample Test Cases

Real
value1 -9x^2-9x+7=0
output -1.51379,-1.51379
Imaginary
value1 8x^2-9x+9=0
output imaginary,imaginary
' where folder = '17_quadratic_calculator'; down: alter table challenges drop column html; ================================================ FILE: platform/migrations/migrations/20210117161957-create-tests-table.sql ================================================ up: create table challenge_tests ( challenge_test_id int unsigned not null auto_increment, challenge_id int unsigned not null, official boolean, name varchar(128) not null, input text not null, output text not null, primary key (challenge_test_id), key challenge_id (challenge_id) )engine=innodb default charset=utf8; insert into challenge_tests (challenge_id, official, name, input, output) values (1, false, 'Testing simple string', 'engineer man cat reverse me :) 1234567890a', 'nam reenigne tac ): em esrever a0987654321'); insert into challenge_tests (challenge_id, official, name, input, output) values (1, false, 'Testing complex string', 'a,masd#$)(&*09&M0d7fn0s8$*&4876%*&7dnosydhf) ===================****#$#$ sd9f6 9s8d6f9 8 s 78^*&^((((((((((((((()))))))))))))))', ')fhdysond7&*%6784&*$8s0nf7d0M&90*&()$#dsam,a $#$#****=================== s 8 9f6d8s9 6f9ds )))))))))))))))(((((((((((((((^&*^87'); insert into challenge_tests (challenge_id, official, name, input, output) values (2, false, 'String of numbers', '738923a 897494889999a 0004953945000a 7575847577777a', '3 9 0 7'); insert into challenge_tests (challenge_id, official, name, input, output) values (3, false, 'Testing short lists', '2,5,1 1,4,5 -2,4,-9', '8 10 -7'); insert into challenge_tests (challenge_id, official, name, input, output) values (3, false, 'Testing long lists', '3,9,10,5,2,7,9,2 3,32,10,5,2,2,9,12,19,49,6,145 -3,9,-10,19,-5,-21,9,-4', '47 294 -6'); insert into challenge_tests (challenge_id, official, name, input, output) values (4, false, 'Single Problem', '{"name":"em" "name":"somebody"} {"doggo":"chase} {"name":"em" "doggo":"chase"}', '{"name":"em"} {"name":"somebody"} {"doggo":"chase"} {"name":"em","doggo":"chase"}'); insert into challenge_tests (challenge_id, official, name, input, output) values (4, false, 'Multiple Problems', '"name":"em "doggo":chase""name":"em', '{"name":"em"} {"doggo":"chase","name":"em"}'); insert into challenge_tests (challenge_id, official, name, input, output) values (5, false, 'Single Problem', 'abc nwv pdu xns jfj nnd', '011000010110001001100011 011011100111011101110110 011100000110010001110101 011110000110111001110011 011010100110011001101010 011011100110111001100100'); insert into challenge_tests (challenge_id, official, name, input, output) values (6, false, 'Testing small numbers', '3|2 8|4 5|3', '5,8 13,21,34,55 8,13,21'); insert into challenge_tests (challenge_id, official, name, input, output) values (6, false, 'Testing large numbers', '34|9 233|14 377|6', '55,89,144,233,377,610,987,1597,2584 377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418 610,987,1597,2584,4181,6765'); insert into challenge_tests (challenge_id, official, name, input, output) values (7, false, 'Testing permutations', 'engineer,gireneen cat,act e1m2k3c4,e2k3m14c', 'Yes Yes Yes'); insert into challenge_tests (challenge_id, official, name, input, output) values (7, false, 'Testing non-permutations', '14467,42641 qwerty,qeerty', 'No No'); insert into challenge_tests (challenge_id, official, name, input, output) values (8, false, 'Testing short lists', '2,5,1 -2,22,-3 3,4,-9', '5,2,1 22,-2,-3 4,3,-9'); insert into challenge_tests (challenge_id, official, name, input, output) values (8, false, 'Testing long lists', '3,9,10,5,2,7,9,2 3,32,10,5,2,2,9,-5,12,19,49,6,145,-2,-1 -3,9,-10,19,-5,-21,9,-4', '10,9,9,7,5,3,2,2 145,49,32,19,12,10,9,6,5,3,2,2,-1,-2,-5 19,9,9,-3,-4,-5,-10,-21'); insert into challenge_tests (challenge_id, official, name, input, output) values (9, false, 'Testing small Roman Numerals', 'VI XII III I', '6 12 3 1'); insert into challenge_tests (challenge_id, official, name, input, output) values (9, false, 'Testing large Roman Numerals', 'CDVII CMXCVII DCXLIII DCCCLXXVI', '407 997 643 876'); insert into challenge_tests (challenge_id, official, name, input, output) values (10, false, 'Testing small phrases', 'ig-pay atin-lay engineeryay an-may ave-hay un-fay idden-hay essage-may illy-say anguage-lay', 'pig latin engineer man have fun hidden message silly language'); insert into challenge_tests (challenge_id, official, name, input, output) values (10, false, 'Testing large phrases', 'isyay ift-sway ayay ood-gay anguage-lay ucks-day areyay etty-pray ool-cay is-thay isyay o-say andom-ray at-whay amyay iyay oing-day ig-pay atin-lay isyay usedyay inyay ools-schay o-tay each-tay anguage-lay onstructs-cay ityay isyay illy-say ut-bay ort-say ofyay un-fay or-fay ildren-chay', 'is swift a good language ducks are pretty cool this is so random what am i doing pig latin is used in schools to teach language constructs it is silly but sort of fun for children'); insert into challenge_tests (challenge_id, official, name, input, output) values (11, false, 'Testing short list', '1,7,4|6,3,8 9,2|10,5 5,3,9|4,8,10 2,4,6|3,8,10', '1,6,7,3,4,8 9,10,2,5 5,4,3,8,9,10 2,3,4,8,6,10'); insert into challenge_tests (challenge_id, official, name, input, output) values (11, false, 'Testing long list', '1,119,37,17,64,120,24,55,500,255|5,40,21,135,32,110,121,68,300,1000 279,378,150,800,5,1337,5,8,12,56|6,7,312,10,15,80,385,231,986,1338', '1,5,119,40,37,21,17,135,64,32,120,110,24,121,55,68,500,300,255,1000 279,6,378,7,150,312,800,10,5,15,1337,80,5,385,8,231,12,986,56,1338'); insert into challenge_tests (challenge_id, official, name, input, output) values (12, false, 'Regular', 'run,barn,yellow,barracuda,shark,fish,swim america,united,kingdom,mexico,canada,AUSTRalia Meatballs,Noodles,Pizza,Porter,Reuben,Toast,Wine,walnuts,lamb,kale,jerky', 'barracuda australia meatballs'); insert into challenge_tests (challenge_id, official, name, input, output) values (12, false, 'Same Size', 'fishes,sam,gollum,sauron,frodo,balrog rUnNiNg ,swimming, eating,biking, climbing', 'fishes,gollum,sauron,balrog swimming,climbing'); insert into challenge_tests (challenge_id, official, name, input, output) values (13, false, 'Testing short strings', 'Engineer man Chocolate bar Weetabix', 'n o,a e'); insert into challenge_tests (challenge_id, official, name, input, output) values (13, false, 'Testing long strings', 'tttt::::::tt::t::t:::t:t: lllasllsllslsllsllslslslal llllttttnabcefghigklmnop', ': l l'); insert into challenge_tests (challenge_id, official, name, input, output) values (14, false, 'Testing short numbers', '3 17 57', 'odd even even'); insert into challenge_tests (challenge_id, official, name, input, output) values (14, false, 'Testing long numbers', '74739 337394 3739203', 'even odd odd'); insert into challenge_tests (challenge_id, official, name, input, output) values (15, false, 'Regular Cookie', '10101111,10011101111001011010111111110011 00010100,1011111100010100100000001111100101111111 10100011,101000111010011100111100', '39 23 7'); insert into challenge_tests (challenge_id, official, name, input, output) values (15, false, 'Big Cookie', '011011000110111101101100,101110001111001010100001011110010110110001101111011011000010011000000101 0110100001101001,1111010000000011011010000110100101101001010100100101110001100001', '87 47'); insert into challenge_tests (challenge_id, official, name, input, output) values (16, false, 'Spiral Corner Sum', '2x2 3x3 4x4 5x5', '10 24 46 76'); insert into challenge_tests (challenge_id, official, name, input, output) values (16, false, 'Spiral Corner Sum', '24x24 25x25', '2166 2356'); insert into challenge_tests (challenge_id, official, name, input, output) values (17, false, 'Real', '1x^2-1x-6=0 x^2-6x+9=0 2x^2-6x-7=0 9x^2-6x-7=0 9x^2+6x-7=0 -3x^2+1x+7=0', '3,-2 3,3 3.89791,-0.89791 1.27614,-0.60947 0.60947,-1.27614 -1.36992,1.70325'); insert into challenge_tests (challenge_id, official, name, input, output) values (17, false, 'Imaginary', '2x^2-6x+7=0 3x^2+1x+7=0 9x^2+9x+7=0 -9x^2-9x-7=0', 'imaginary,imaginary imaginary,imaginary imaginary,imaginary imaginary,imaginary'); down: drop table challenge_tests; ================================================ FILE: platform/migrations/migrations/20210220201643-piston-run-changes.sql ================================================ up: alter table piston_runs modify server_id varchar(32) null; alter table piston_runs modify user_id varchar(32) null; down: alter table piston_runs modify server_id varchar(32) not null; alter table piston_runs modify user_id varchar(32) not null; ================================================ FILE: platform/migrations/migrations/20210314201643-challenge-draft.sql ================================================ up: alter table challenges add draft tinyint unsigned not null default 1 after challenge_id; update challenges set draft = 0; down: alter table challenges drop column draft; ================================================ FILE: platform/migrations/migrations/20210319145442-add-disallowed-languages.sql ================================================ up: alter table contests add disallowed_languages varchar(2048) after output; update contests set disallowed_languages = 'python2,awk'; down: alter table contests drop column disallowed_languages; ================================================ FILE: platform/migrations/migrations/20210325110214-change-character-set.sql ================================================ up: alter table awards convert to character set utf8mb4; alter table challenge_tests convert to character set utf8mb4; alter table challenges convert to character set utf8mb4; alter table cli_scripts convert to character set utf8mb4; alter table contest_submissions convert to character set utf8mb4; alter table contests convert to character set utf8mb4; alter table discord_chat_messages convert to character set utf8mb4; alter table piston_runs convert to character set utf8mb4; alter table rmig convert to character set utf8mb4; alter table snippets convert to character set utf8mb4; alter table sticker_orders convert to character set utf8mb4; alter table tags convert to character set utf8mb4; alter table user_challenges convert to character set utf8mb4; alter table users convert to character set utf8mb4; down: alter table awards convert to character set utf8; alter table challenge_tests convert to character set utf8; alter table challenges convert to character set utf8; alter table cli_scripts convert to character set utf8; alter table contest_submissions convert to character set utf8; alter table contests convert to character set utf8; alter table discord_chat_messages convert to character set utf8; alter table piston_runs convert to character set utf8; alter table rmig convert to character set utf8; alter table snippets convert to character set utf8; alter table sticker_orders convert to character set utf8; alter table tags convert to character set utf8; alter table user_challenges convert to character set utf8; alter table users convert to character set utf8; ================================================ FILE: platform/migrations/migrations/20210326154806-add-late-submissions.sql ================================================ up: alter table contest_submissions add late tinyint unsigned default 0; down: alter table contest_submissions drop column late; ================================================ FILE: platform/migrations/migrations/20210401114642-add-explanation-field.sql ================================================ up: alter table contest_submissions add explanation mediumtext not null after length; down: alter table contest_submissions drop column explanation; ================================================ FILE: platform/migrations/migrations/20210423100104-add-language-version.sql ================================================ up: alter table contest_submissions add language_version varchar(32) not null after length; down: alter table contest_submissions drop column language_version; ================================================ FILE: platform/migrations/migrations/20210714100104-add-best-length.sql ================================================ up: alter table contest_submissions add length_best int unsigned not null after length; down: alter table contest_submissions drop column length_best; ================================================ FILE: platform/migrations/migrations/20210901095201-remove-contest-draft-field.sql ================================================ up: alter table contests drop column draft; down: alter table contests add draft tinyint unsigned not null default 1 after contest_id; ================================================ FILE: platform/migrations/migrations/20220706141314-drop-challenges-folder.sql ================================================ up: alter table challenges drop column folder; down: alter table challenges add column folder varchar(64) not null ================================================ FILE: platform/migrations/migrations/20220707092911-drop-official-field.sql ================================================ up: alter table challenge_tests drop column official; down: alter table challenge_tests add column official tinyint(1) default null; ================================================ FILE: platform/models/awards.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class awards extends Sequelize.Model {} awards.init( { award_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, type: DataTypes.INTEGER, points: DataTypes.INTEGER, user_id: DataTypes.INTEGER, ref_type: DataTypes.INTEGER, ref_id: DataTypes.INTEGER, created_at: DataTypes.DATE, // getters tooltip_text: { type: DataTypes.VIRTUAL, get() { return ( { [constant.awards.type.contest_first_overall]: 'Placed 1st overall in a contest', [constant.awards.type.contest_second_overall]: 'Placed 2nd overall in a contest', [constant.awards.type.contest_third_overall]: 'Placed 3rd overall in a contest', [constant.awards.type.contest_first_language]: 'Placed 1st for a specific language in a contest', [constant.awards.type.general_participation]: 'Participation' }[this.type] || '' ); } } }, { sequelize, modelName: 'awards', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return awards; }; ================================================ FILE: platform/models/challenge_tests.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class challenge_tests extends Sequelize.Model {} challenge_tests.init( { challenge_test_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, challenge_id: DataTypes.INTEGER, name: DataTypes.STRING, input: DataTypes.TEXT, output: DataTypes.TEXT }, { sequelize, modelName: 'challenge_tests', freezeTableName: true } ); return challenge_tests; }; ================================================ FILE: platform/models/challenges.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class challenges extends Sequelize.Model {} challenges.init( { challenge_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, draft: DataTypes.INTEGER, difficulty: DataTypes.INTEGER, points: DataTypes.INTEGER, name: DataTypes.STRING, description: DataTypes.STRING, html: DataTypes.TEXT('medium'), // getters difficulty_name: { type: DataTypes.VIRTUAL, get() { return ( { [constant.challenges.difficulty.easy]: 'easy', [constant.challenges.difficulty.medium]: 'medium', [constant.challenges.difficulty.hard]: 'hard' }[this.difficulty] || null ); } }, difficulty_name_upper: { type: DataTypes.VIRTUAL, get() { return ( { [constant.challenges.difficulty.easy]: 'Easy', [constant.challenges.difficulty.medium]: 'Medium', [constant.challenges.difficulty.hard]: 'Hard' }[this.difficulty] || null ); } } }, { sequelize, modelName: 'challenges', freezeTableName: true, hooks: {} } ); return challenges; }; ================================================ FILE: platform/models/cli_scripts.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class cli_scripts extends Sequelize.Model {} cli_scripts.init( { cli_script_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, user_id: DataTypes.INTEGER, is_public: DataTypes.INTEGER, is_safe: DataTypes.INTEGER, title: DataTypes.STRING, content: DataTypes.TEXT('medium'), created_at: DataTypes.DATE, // getters view_url: { type: DataTypes.VIRTUAL, get() { return ( '/scripts/' + this.cli_script_id + '/' + util.slugify(this.title) ); } }, exec_url: { type: DataTypes.VIRTUAL, get() { return '/exec/' + this.cli_script_id; } } }, { sequelize, modelName: 'cli_scripts', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return cli_scripts; }; ================================================ FILE: platform/models/contest_submissions.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class contest_submissions extends Sequelize.Model {} contest_submissions.init( { contest_submission_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, user_id: DataTypes.INTEGER, contest_id: DataTypes.INTEGER, language: DataTypes.STRING, language_version: DataTypes.STRING, solution: DataTypes.TEXT('medium'), length: DataTypes.INTEGER, length_best: DataTypes.INTEGER, explanation: DataTypes.TEXT('medium'), award_place: DataTypes.INTEGER, award_points: DataTypes.INTEGER, created_at: DataTypes.DATE, late: DataTypes.INTEGER }, { sequelize, modelName: 'contest_submissions', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return contest_submissions; }; ================================================ FILE: platform/models/contests.js ================================================ const Sequelize = require('sequelize'); const moment = require('moment'); module.exports = (sequelize, DataTypes) => { class contests extends Sequelize.Model {} contests.init( { contest_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, name: DataTypes.STRING, description: DataTypes.TEXT('medium'), start_date: DataTypes.DATE, end_date: DataTypes.DATE, input: DataTypes.TEXT, output: DataTypes.TEXT, disallowed_languages: DataTypes.STRING, created_at: DataTypes.DATE, // getters active: { type: DataTypes.VIRTUAL, get() { return ( moment().isAfter(moment(this.start_date)) && moment().isBefore(moment(this.end_date)) ); } }, url: { type: DataTypes.VIRTUAL, get() { return ( '/contests/' + this.contest_id + '/' + util.slugify(this.name) ); } }, slug: { type: DataTypes.VIRTUAL, get() { return util.slugify(this.name); } }, time_left: { type: DataTypes.VIRTUAL, get() { const start = moment().unix(); const end = moment(this.end_date).unix(); const diff = end - start; const duration = moment.duration( diff * 1000, 'milliseconds' ); if (duration.weeks() > 0) { return ( duration.weeks() + ' week' + (duration.weeks() == 1 ? '' : 's') + ' ' + duration.days() + ' day' + (duration.days() == 1 ? '' : 's') + ' ' + duration.hours() + ' hour' + (duration.hours() == 1 ? '' : 's') + ' ' + duration.minutes() + ' minute' + (duration.minutes() == 1 ? '' : 's') + ' ' ); } if (duration.days() > 0) { return ( duration.days() + ' day' + (duration.days() == 1 ? '' : 's') + ' ' + duration.hours() + ' hour' + (duration.hours() == 1 ? '' : 's') + ' ' + duration.minutes() + ' minute' + (duration.minutes() == 1 ? '' : 's') + ' ' ); } if (duration.hours() > 0) { return ( duration.hours() + ' hour' + (duration.hours() == 1 ? '' : 's') + ' ' + duration.minutes() + ' minute' + (duration.minutes() == 1 ? '' : 's') + ' ' ); } return ( duration.minutes() + ' minute' + (duration.minutes() == 1 ? '' : 's') + ' ' ); } } }, { sequelize, modelName: 'contests', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return contests; }; ================================================ FILE: platform/models/discord_chat_messages.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class discord_chat_messages extends Sequelize.Model {} discord_chat_messages.init( { discord_chat_message_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, hash: DataTypes.STRING, channel: DataTypes.STRING, user: DataTypes.STRING, discord_id: DataTypes.STRING, message: DataTypes.STRING, created_at: DataTypes.DATE }, { sequelize, modelName: 'discord_chat_messages', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return discord_chat_messages; }; ================================================ FILE: platform/models/index.js ================================================ const path = require('path'); const basename = path.basename(module.filename); const config = sails.config.db; const db = {}; const { Sequelize, DataTypes } = require('sequelize'); const sequelize = new Sequelize( config.database, config.username, config.password, config ); require('fs') .readdir_sync(__dirname) .filter((file) => { return ( file.indexOf('.') !== 0 && file !== basename && file.match(/\.js$/) ); }) .for_each((file) => { //let model = sequelize.import(path.join(__dirname, file)); let model = require(path.join(__dirname, file))(sequelize, DataTypes); db[model.name] = model; }); for (const model_name in db) { db[model_name].bulk_create = db[model_name].bulkCreate; db[model_name].find_one = db[model_name].findOne; db[model_name].find_all = db[model_name].findAll; db[model_name].find_or_create = db[model_name].findOrCreate; db[model_name].find_and_count_all = db[model_name].findAndCountAll; db[model_name].belongs_to = db[model_name].belongsTo; db[model_name].has_one = db[model_name].hasOne; db[model_name].has_many = db[model_name].hasMany; db[model_name].belongs_to_many = db[model_name].belongsToMany; } db.sequelize = sequelize; db.Sequelize = Sequelize; $or = Sequelize.Op.or; $and = Sequelize.Op.and; $like = Sequelize.Op.like; $ne = Sequelize.Op.ne; $not = Sequelize.Op.not; $gt = Sequelize.Op.gt; $gte = Sequelize.Op.gte; $lt = Sequelize.Op.lt; $lte = Sequelize.Op.lte; $in = Sequelize.Op.in; $not_in = Sequelize.Op.notIn; db.challenges.has_one(db.user_challenges, { as: 'solution', foreignKey: 'challenge_id' }); db.challenges.has_many(db.user_challenges, { as: 'solutions', foreignKey: 'challenge_id' }); db.challenges.has_many(db.challenge_tests, { as: 'tests', foreignKey: 'challenge_id' }); db.contests.has_many(db.contest_submissions, { as: 'submissions', foreignKey: 'contest_id' }); db.users.has_many(db.contest_submissions, { as: 'submissions', foreignKey: 'user_id' }); db.user_challenges.belongs_to(db.challenges, { as: 'challenge', foreignKey: 'challenge_id' }); db.user_challenges.belongs_to(db.users, { as: 'user', foreignKey: 'user_id' }); db.challenge_tests.belongs_to(db.challenges, { as: 'challenge', foreignKey: 'challenge_id' }); db.contest_submissions.belongs_to(db.contests, { as: 'contest', foreignKey: 'contest_id' }); db.contest_submissions.belongs_to(db.users, { as: 'user', foreignKey: 'user_id' }); module.exports = db; ================================================ FILE: platform/models/piston_runs.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class piston_runs extends Sequelize.Model {} piston_runs.init( { piston_run_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, server: DataTypes.STRING, server_id: DataTypes.STRING, user: DataTypes.STRING, user_id: DataTypes.STRING, language: DataTypes.STRING, source: DataTypes.TEXT, created_at: DataTypes.DATE }, { sequelize, modelName: 'piston_runs', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return piston_runs; }; ================================================ FILE: platform/models/snippets.js ================================================ const Sequelize = require('sequelize'); const crypto = require('crypto'); module.exports = (sequelize, DataTypes) => { class snippets extends Sequelize.Model {} snippets.init( { snippet_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, user_id: DataTypes.INTEGER, hash: DataTypes.STRING, language: DataTypes.STRING, snip: DataTypes.TEXT('medium'), created_at: DataTypes.DATE, // getters url: { type: DataTypes.VIRTUAL, get() { return '/s/' + this.hash; } }, time_ago: { type: DataTypes.VIRTUAL, get() { return util.time_ago(this.created_at); } } }, { sequelize, modelName: 'snippets', freezeTableName: true, hooks: { async beforeCreate(instance) { instance.created_at = util.now(); var letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; for (;;) { instance.hash = ''; for (var i = 0; i < 6; ++i) { instance.hash += letters[ Math.floor(Math.random() * letters.length) ]; } var dupe = await db.snippets.find_one({ where: { hash: instance.hash } }); if (!dupe) break; } } } } ); return snippets; }; ================================================ FILE: platform/models/sticker_orders.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class sticker_orders extends Sequelize.Model {} sticker_orders.init( { sticker_order_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, is_fulfilled: DataTypes.INTEGER, tx: DataTypes.STRING, coupon: DataTypes.STRING, quantity: DataTypes.INTEGER, cost: DataTypes.DECIMAL(5, 2), name: DataTypes.STRING, email: DataTypes.STRING, address: DataTypes.TEXT, created_at: DataTypes.DATE }, { sequelize, modelName: 'sticker_orders', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return sticker_orders; }; ================================================ FILE: platform/models/tags.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class tags extends Sequelize.Model {} tags.init( { tag_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, name: DataTypes.STRING }, { sequelize, modelName: 'tags', freezeTableName: true, hooks: {} } ); return tags; }; ================================================ FILE: platform/models/user_challenges.js ================================================ const Sequelize = require('sequelize'); module.exports = (sequelize, DataTypes) => { class user_challenges extends Sequelize.Model {} user_challenges.init( { user_challenge_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, user_id: DataTypes.INTEGER, challenge_id: DataTypes.INTEGER, language: DataTypes.STRING, solution: DataTypes.TEXT('medium'), created_at: DataTypes.DATE }, { sequelize, modelName: 'user_challenges', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); } } } ); return user_challenges; }; ================================================ FILE: platform/models/users.js ================================================ const Sequelize = require('sequelize'); const crypto = require('crypto'); module.exports = (sequelize, DataTypes) => { class users extends Sequelize.Model {} users.init( { user_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, is_staff: DataTypes.INTEGER, display_name: DataTypes.STRING, username: DataTypes.STRING, email: DataTypes.STRING, password: DataTypes.STRING, discord_api: DataTypes.STRING, discord_rank: DataTypes.INTEGER, avatar_url: DataTypes.STRING, score: DataTypes.INTEGER, created_at: DataTypes.DATE }, { sequelize, modelName: 'users', freezeTableName: true, hooks: { beforeCreate(instance) { instance.created_at = util.now(); if (instance.password) instance.password = crypto .createHash('sha1') .update(instance.password) .digest('hex'); }, beforeUpdate(instance) { if (instance.changed('password')) instance.password = crypto .createHash('sha1') .update(instance.password) .digest('hex'); } } } ); return users; }; ================================================ FILE: platform/package.json ================================================ { "scripts": { "prod": "run-s prod:webpack prod:app", "prod:webpack": "webpack --mode production --colors --progress", "prod:app": "node emkc.js", "dev": "run-p dev:webpack dev:app", "dev:webpack": "webpack --mode development --colors --watch --progress", "dev:app": "nodemon --ignore resources/ --ignore public/ -e js,twig emkc.js" }, "dependencies": { "@babel/core": "7.7.4", "@babel/plugin-proposal-object-rest-spread": "7.7.4", "@babel/plugin-proposal-class-properties": "7.7.4", "@babel/plugin-transform-async-to-generator": "7.7.4", "@babel/preset-env": "7.7.4", "@babel/preset-react": "7.7.4", "@google-cloud/storage": "2.0.0", "axios": "0.19.0", "babel-loader": "8.0.6", "bluebird": "3.5.1", "connect-redis": "3.3.0", "core-js": "3.6.5", "css-loader": "3.2.1", "file-loader": "6.0.0", "grunt": "0.4.1", "ioredis": "4.17.3", "less": "3.10.3", "less-loader": "5.0.0", "lusca": "1.3.0", "mailgun-js": "0.20.0", "mini-css-extract-plugin": "0.8.0", "moment": "2.22.2", "moment-timezone": "0.5.21", "monaco-editor": "0.20.0", "monaco-editor-webpack-plugin": "1.9.0", "mysql2": "2.1.0", "nocamel": "*", "nodemon": "2.0.4", "npm-run-all": "4.1.5", "optimist": "0.6.1", "pm2": "4.4.0", "q": "1.5.0", "quill": "1.3.7", "react": "16.12.0", "react-dom": "16.12.0", "react-router": "5.1.2", "react-router-dom": "5.1.2", "redis": "2.8.0", "regenerator-runtime": "0.13.3", "request-promise": "4.2.2", "sails": "0.12.14", "sequelize": "6.3.5", "socket.io-redis": "1.0.0", "style-loader": "1.0.1", "twig": "0.8.2", "uuid": "3.2.1", "webpack": "^4.41.2", "webpack-cli": "3.3.10" } } ================================================ FILE: platform/pm2.json ================================================ { "name": "emkc", "args": ["-i 0"], "script": "emkc.js", "node_args": ["--max_old_space_size=4096"], "error_file": "/var/log/emkc.log", "out_file": "/var/log/emkc.log", "instances": 0, "merge_logs": true, "log_date_format": "YYYY-MM-DD HH:mm Z", "exec_mode": "cluster" } ================================================ FILE: platform/public/css/.gitkeep ================================================ ================================================ FILE: platform/public/js/.gitkeep ================================================ ================================================ FILE: platform/public/lib/bootbox/bootbox.js ================================================ /** * bootbox.js v4.4.0 * * http://bootboxjs.com/license.txt */ !function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d.call(c,a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback.call(this):!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback.call(this,c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!b.isArray(k))throw new Error("Please pass an array of input options");if(!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),a.maxlength&&h.attr("maxlength",a.maxlength),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var d=b(n.dialog),f=d.find(".modal-dialog"),i=d.find(".modal-body"),j=a.buttons,k="",l={onEscape:a.onEscape};if(b.fn.modal===c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(g(j,function(a,b){k+="",l[a]=b.callback}),i.find(".bootbox-body").html(a.message),a.animate===!0&&d.addClass("fade"),a.className&&d.addClass(a.className),"large"===a.size?f.addClass("modal-lg"):"small"===a.size&&f.addClass("modal-sm"),a.title&&i.before(n.header),a.closeButton){var m=b(n.closeButton);a.title?d.find(".modal-header").prepend(m):m.css("margin-top","-10px").prependTo(i)}return a.title&&d.find(".modal-title").html(a.title),k.length&&(i.after(n.footer),d.find(".modal-footer").html(k)),d.on("hidden.bs.modal",function(a){a.target===this&&d.remove()}),d.on("shown.bs.modal",function(){d.find(".btn-primary:first").focus()}),"static"!==a.backdrop&&d.on("click.dismiss.bs.modal",function(a){d.children(".modal-backdrop").length&&(a.currentTarget=d.children(".modal-backdrop").get(0)),a.target===a.currentTarget&&d.trigger("escape.close.bb")}),d.on("escape.close.bb",function(a){l.onEscape&&e(a,d,l.onEscape)}),d.on("click",".modal-footer button",function(a){var c=b(this).data("bb-handler");e(a,d,l[c])}),d.on("click",".bootbox-close-button",function(a){e(a,d,l.onEscape)}),d.on("keyup",function(a){27===a.which&&d.trigger("escape.close.bb")}),b(a.container).append(d),d.modal({backdrop:a.backdrop?"static":!1,keyboard:!1,show:!1}),a.show&&d.modal("show"),d},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={bg_BG:{OK:"Ок",CANCEL:"Отказ",CONFIRM:"Потвърждавам"},br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fa:{OK:"قبول",CANCEL:"لغو",CONFIRM:"تایید"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},hu:{OK:"OK",CANCEL:"Mégsem",CONFIRM:"Megerősít"},hr:{OK:"OK",CANCEL:"Odustani",CONFIRM:"Potvrdi"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sq:{OK:"OK",CANCEL:"Anulo",CONFIRM:"Prano"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},th:{OK:"ตกลง",CANCEL:"ยกเลิก",CONFIRM:"ยืนยัน"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.addLocale=function(a,c){return b.each(["OK","CANCEL","CONFIRM"],function(a,b){if(!c[b])throw new Error("Please supply a translation for '"+b+"'")}),q[a]={OK:c.OK,CANCEL:c.CANCEL,CONFIRM:c.CONFIRM},p},p.removeLocale=function(a){return delete q[a],p},p.setLocale=function(a){return p.setDefaults("locale",a)},p.init=function(c){return a(c||b)},p}); ================================================ FILE: platform/public/lib/highlightjs/atom-one-dark.css ================================================ /* Atom One Dark by Daniel Gamage Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax base: #282c34 mono-1: #abb2bf mono-2: #818896 mono-3: #5c6370 hue-1: #56b6c2 hue-2: #61aeee hue-3: #c678dd hue-4: #98c379 hue-5: #e06c75 hue-5-2: #be5046 hue-6: #d19a66 hue-6-2: #e6c07b */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #abb2bf; background: #24282F !important; } .hljs-comment, .hljs-quote { color: #5c6370; font-style: italic; } .hljs-doctag, .hljs-keyword, .hljs-formula { color: #c678dd; } .hljs-section, .hljs-name, .hljs-selector-tag, .hljs-deletion, .hljs-subst { color: #e06c75; } .hljs-literal { color: #56b6c2; } .hljs-string, .hljs-regexp, .hljs-addition, .hljs-attribute, .hljs-meta-string { color: #98c379; } .hljs-built_in, .hljs-class .hljs-title { color: #e6c07b; } .hljs-attr, .hljs-variable, .hljs-template-variable, .hljs-type, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-number { color: #d19a66; } .hljs-symbol, .hljs-bullet, .hljs-link, .hljs-meta, .hljs-selector-id, .hljs-title { color: #61aeee; } .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: bold; } .hljs-link { text-decoration: underline; } ================================================ FILE: platform/public/lib/highlightjs/default.css ================================================ /* Original highlight.js style (c) Ivan Sagalaev */ .hljs { display: block; overflow-x: auto; padding: 0.5em; background: #F0F0F0; } /* Base color: saturation 0; */ .hljs, .hljs-subst { color: #444; } .hljs-comment { color: #888888; } .hljs-keyword, .hljs-attribute, .hljs-selector-tag, .hljs-meta-keyword, .hljs-doctag, .hljs-name { font-weight: bold; } /* User color: hue: 0 */ .hljs-type, .hljs-string, .hljs-number, .hljs-selector-id, .hljs-selector-class, .hljs-quote, .hljs-template-tag, .hljs-deletion { color: #880000; } .hljs-title, .hljs-section { color: #880000; font-weight: bold; } .hljs-regexp, .hljs-symbol, .hljs-variable, .hljs-template-variable, .hljs-link, .hljs-selector-attr, .hljs-selector-pseudo { color: #BC6060; } /* Language color: hue: 90; */ .hljs-literal { color: #78A960; } .hljs-built_in, .hljs-bullet, .hljs-code, .hljs-addition { color: #397300; } /* Meta color: hue: 200 */ .hljs-meta { color: #1f7199; } .hljs-meta-string { color: #4d99bf; } /* Misc effects */ .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: bold; } ================================================ FILE: platform/public/lib/highlightjs/highlight-ln.js ================================================ !function(n,e){"use strict";function t(){var n=e.createElement("style");n.type="text/css",n.innerHTML=h(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[f,m,j]),e.getElementsByTagName("head")[0].appendChild(n)}function r(t){"complete"===e.readyState?l(t):n.addEventListener("DOMContentLoaded",function(){l(t)})}function l(t){try{var r=e.querySelectorAll("code.hljs");for(var l in r)r.hasOwnProperty(l)&&i(r[l],t)}catch(o){n.console.error("LineNumbers error: ",o)}}function i(n,e){if("object"==typeof n){e=e||{singleLine:!1};var t=e.singleLine?0:1;u(function(){s(n),n.innerHTML=o(n.innerHTML,t)})}}function o(n,e){var t=c(n);if(""===t[t.length-1].trim()&&t.pop(),t.length>e){for(var r="",l=0,i=t.length;l
{6}
',[v,g,m,j,p,l+1,t[l].length>0?t[l]:" "]);return h('{1}
',[f,r])}return n}function s(n){var e=n.childNodes;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];d(r.textContent)>0&&(r.childNodes.length>0?s(r):a(r.parentNode))}}function a(n){var e=n.className;if(/hljs-/.test(e)){for(var t=c(n.innerHTML),r=0,l="";r{1}\n',[e,t[r]]);n.innerHTML=l.trim()}}function c(n){return 0===n.length?[]:n.split(L)}function d(n){return(n.trim().match(L)||[]).length}function u(e){n.setTimeout(e,0)}function h(n,e){return n.replace(/\{(\d+)\}/g,function(n,t){return e[t]?e[t]:n})}var f="hljs-ln",g="hljs-ln-line",p="hljs-ln-code",v="hljs-ln-numbers",m="hljs-ln-n",j="data-line-number",L=/\r\n|\r|\n/g;n.hljs?(n.hljs.initLineNumbersOnLoad=r,n.hljs.lineNumbersBlock=i,t()):n.console.error("highlight.js not detected!")}(window,document); ================================================ FILE: platform/public/lib/highlightjs/highlight.pack.js ================================================ /*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){s+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("java",function(e){var a="[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",t=a+"(<"+a+"(\\s*,\\s*"+a+")*>)?",r="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",s="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",c={cN:"number",b:s,r:0};return{aliases:["jsp"],k:r,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},c,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={v:[{b:/\$\d/},{b:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{b:/[\$%@][^\s\w{]/,r:0}]},i=[e.BE,r,n],o=[n,e.HCM,e.C("^\\=\\w","\\=cut",{eW:!0}),s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"function",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",eE:!0,r:5,c:[e.TM]},{b:"-\\w\\b",r:0},{b:"^__DATA__$",e:"^__END__$",sL:"mojolicious",c:[{b:"^@@.*",e:"$",cN:"comment"}]}];return r.c=o,s.c=o,{aliases:["pl","pm"],l:/[\w\.]+/,k:t,c:o}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super yield import export from as default await then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",r={cN:"subst",b:/#\{/,e:/}/,k:c},i=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,r]},{b:/"/,e:/"/,c:[e.BE,r]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[r,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+n},{sL:"javascript",eB:!0,eE:!0,v:[{b:"```",e:"```"},{b:"`",e:"`"}]}];r.c=i;var s=e.inherit(e.TM,{b:n}),t="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(i)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:i.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+t,e:"[-=]>",rB:!0,c:[s,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:t,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[s]},s]},{b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:b}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+"|unless)\\s*",k:"unless",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",u="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",w=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+u+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:s.concat(w).concat(d)}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U)?L?"',e:'"',i:"\\n",c:[t.BE]},{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e]},t.CLCM,t.CBCM,i]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b://,c:["self"]},t.TM]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("shell",function(s){return{aliases:["console"],c:[{cN:"meta",b:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{e:"$",sL:"bash"}}]}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},_={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},i=/[a-zA-Z@][a-zA-Z0-9_]*/,n="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:_,l:i,i:""}]}]},{cN:"class",b:"("+n.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:n,l:i,c:[e.UTM]},{b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("ini",function(e){var b={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},b,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}});hljs.registerLanguage("makefile",function(e){var i={cN:"variable",v:[{b:"\\$\\("+e.UIR+"\\)",c:[e.BE]},{b:/\$[@%>>|\.\.\.) /},c={cN:"subst",b:/\{/,e:/\}/,k:r,i:/#/},a={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[b],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[b],r:10},{b:/(fr|rf|f)'''/,e:/'''/,c:[b,c]},{b:/(fr|rf|f)"""/,e:/"""/,c:[b,c]},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},{b:/(fr|rf|f)'/,e:/'/,c:[c]},{b:/(fr|rf|f)"/,e:/"/,c:[c]},e.ASM,e.QSM]},s={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},i={cN:"params",b:/\(/,e:/\)/,c:["self",b,s,a]};return c.c=[a,s,b],{aliases:["py","gyp"],k:r,i:/(<\/|->|\?)|=>/,c:[b,s,a,e.HCM,{v:[{cN:"function",bK:"def"},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,i,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:""},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("cs",function(e){var i={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long nameof object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let on orderby partial remove select set value var where yield",literal:"null false true"},t={cN:"string",b:'@"',e:'"',c:[{b:'""'}]},r=e.inherit(t,{i:/\n/}),a={cN:"subst",b:"{",e:"}",k:i},c=e.inherit(a,{i:/\n/}),n={cN:"string",b:/\$"/,e:'"',i:/\n/,c:[{b:"{{"},{b:"}}"},e.BE,c]},s={cN:"string",b:/\$@"/,e:'"',c:[{b:"{{"},{b:"}}"},{b:'""'},a]},o=e.inherit(s,{i:/\n/,c:[{b:"{{"},{b:"}}"},{b:'""'},c]});a.c=[s,n,t,e.ASM,e.QSM,e.CNM,e.CBCM],c.c=[o,n,r,e.ASM,e.QSM,e.CNM,e.inherit(e.CBCM,{i:/\n/})];var l={v:[s,n,t,e.ASM,e.QSM]},b=e.IR+"(<"+e.IR+"(\\s*,\\s*"+e.IR+")*>)?(\\[\\])?";return{aliases:["csharp"],k:i,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:""},{b:""}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},l,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{cN:"meta",b:"^\\s*\\[",eB:!0,e:"\\]",eE:!0,c:[{cN:"meta-string",b:/"/,e:/"/}]},{bK:"new return throw await else",r:0},{cN:"function",b:"("+b+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:i,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:i,r:0,c:[l,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"meta",b:/<\?(php)?|\?>/},t={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},a={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[i]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},i,{cN:"keyword",b:/\$this\b/},c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,t,a]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},t,a]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}}); ================================================ FILE: platform/public/lib/webpack/.gitkeep ================================================ ================================================ FILE: platform/public/other/.gitkeep ================================================ ================================================ FILE: platform/resources/challenges/templates/template.c ================================================ #include #include #include int main(int argc, char **argv) { %%_INSERTVALUES_%% // write your solution here } ================================================ FILE: platform/resources/challenges/templates/template.cpp ================================================ #include #include int main(int argc, char **argv) { %%_INSERTVALUES_%% // write your solution here } ================================================ FILE: platform/resources/challenges/templates/template.cs ================================================ using System; class MainClass { static void Main(string[] args) { %%_INSERTVALUES_%% // write your solution here } } ================================================ FILE: platform/resources/challenges/templates/template.go ================================================ package main import ( "os" "fmt" %%_IMPORTS_%% ) func main() { %%_INSERTVALUES_%% // write your solution here } ================================================ FILE: platform/resources/challenges/templates/template.hs ================================================ import System.Environment main = do args <- getArgs %%_INSERTVALUES_%% -- write your solution here ================================================ FILE: platform/resources/challenges/templates/template.java ================================================ public class Main { public static void main(String[] args) { %%_INSERTVALUES_%% // write your solution here } } ================================================ FILE: platform/resources/challenges/templates/template.jl ================================================ %%_INSERTVALUES_%% # write your solution here ================================================ FILE: platform/resources/challenges/templates/template.js ================================================ %%_INSERTVALUES_%% // write your solution here ================================================ FILE: platform/resources/challenges/templates/template.kt ================================================ fun main(args: Array) { %%_INSERTVALUES_%% // write your solution here } ================================================ FILE: platform/resources/challenges/templates/template.nim ================================================ %%_INSERTVALUES_%% # write your solution here ================================================ FILE: platform/resources/challenges/templates/template.php ================================================ = env::args().collect(); %%_INSERTVALUES_%% // write your solution here } ================================================ FILE: platform/resources/challenges/templates/template.sh ================================================ %%_INSERTVALUES_%% # write your solution here ================================================ FILE: platform/resources/challenges/templates/template.swift ================================================ %%_INSERTVALUES_%% // write your solution here ================================================ FILE: platform/resources/js/.gitkeep ================================================ ================================================ FILE: platform/resources/js/challenges/get_language_version.js ================================================ import axios from 'axios'; $(document).ready(async function () { if ($('.get-versions').length > 0) { var languages = await axios.get('/api/v1/piston/versions'); $('.version').each(function () { let language = languages.data.filter( (lang) => $(this).data('langname') === lang.name )[0]; $(this).append(language.version); }); } }); ================================================ FILE: platform/resources/js/common.js ================================================ const Constants = { exp_mo: [ '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12' ], exp_yr: new Array(10).fill(new Date().getFullYear()).map((n, i) => n + i) }; export default Constants; ================================================ FILE: platform/resources/js/snippets/delete_snippet.js ================================================ import axios from 'axios'; $(document).on('click', '.confirm-delete', function (e) { var hash = $(this).data('hash'); bootbox.confirm({ message: 'Are you sure you want to delete this snippet?', buttons: { confirm: { label: 'Delete', className: 'btn-danger' }, cancel: { label: 'Cancel', className: 'btn-secondary' } }, callback: async function (result) { if (result) { let res = await axios.post('/snippets/delete/' + hash); location = res.data.url; } } }); }); ================================================ FILE: platform/resources/js/util.js ================================================ import React from 'react'; import ReactDOM from 'react-dom'; class Util { static unpack_props(props) { for (const key in props) { try { props[key] = JSON.parse(props[key]); } catch (e) {} } } static try_render(id, comp) { if (document.getElementById(id)) { let ele = document.getElementById(id); const final = {}; for (const key in ele.dataset) { try { final[key] = JSON.parse(ele.dataset[key]); } catch (e) {} } return ReactDOM.render( React.createElement(comp, final), document.getElementById(id) ); } } static are_test_cases_valid(test_object) { return ( test_object.input !== '' && test_object.output !== '' && test_object.input.split('\n').length === test_object.output.split('\n').length ); } } export default Util; ================================================ FILE: platform/resources/jsx/challenges/challenge.jsx ================================================ import React from 'react'; import axios from 'axios'; import Util from 'js/util'; class Challenge extends React.Component { constructor(props) { super(props); this.state = { solved: props.solved, challenge: props.challenge, language: props.language, template: (props.challenge.solution && props.challenge.solution.solution) || props.template, abstract: props.abstract, monaco_language: props.monaco_language, executing: false, test_results: [], changed: false }; this.execute = this.execute.bind(this); this.editor_change = this.editor_change.bind(this); this.before_unload = this.before_unload.bind(this); // Add event listener for when the user leaves with unsaved work window.addEventListener('beforeunload', this.before_unload, false); } componentDidMount() { this.editor = monaco.editor.create(document.getElementById('editor'), { theme: 'em', language: this.state.monaco_language, value: this.state.template, automaticLayout: true, fontSize: 16 }); // Bind event listener for when the editor changes; unsaved work this.editor.onDidChangeModelContent(this.editor_change); } componentWillUnmount() { // Remove event listener on unmount window.removeEventListener('beforeunload', this.before_unload, false); } async execute() { this.setState({ executing: true, test_results: [] }); let res = await axios.post( '/challenges/execute/' + this.state.challenge.challenge_id, { language: this.state.language, source: this.editor.getValue() } ); if (res.status >= 400) { return bootbox.alert( 'An error has occured, please try again later.' ); } let solved = res.data.filter((r) => !r.passed).length === 0; if (solved) { this.setState((prev) => { if (!prev.solved) { let alert_message = !!prev.challenge.draft ? 'Thank you for testing EMKC challenges!
\ Your answer will not be saved since this challenge is still under construction.' : 'Congratulations, you solved this challenge!'; bootbox.alert(alert_message); } return { solved: true, // The challenge's code saves on solve // Therefore, we can disable the "close protection" changed: false }; }); } return this.setState({ executing: false, test_results: res.data }); } editor_change(_) { // Only change state when necessary if (!this.state.changed) { // The editor's contents have changed this.setState({ changed: true }); } } before_unload(e) { if (this.state.changed) { // Unsaved work, prompt user! e.preventDefault(); e.returnValue = true; } } render() { let text_color; switch (this.state.challenge.difficulty) { case 1: text_color = 'easy'; break; case 2: text_color = 'medium'; break; case 3: text_color = 'hard'; break; } return (

{this.state.challenge.name}

{this.state.challenge.description}

{this.state.solved ? 'Solved' : 'Unsolved'}

Test Results

{this.state.test_results.map((result) => { return (
{result.name}{' '} {result.passed ? 'passed' : 'failed'}
{result.input.map((input, i) => { return ( value{i + 1} {' '} {input}
); })} expected output {' '} {result.expected}
actual output {' '}
{result.actual}
{!!result.compile_output && ( <>
compile output {' '}
{result.compile_output}
)} {!!result.run_error && ( <>
run error {' '}
{result.run_error}
)}
); })}
); } } Util.try_render('react_challenge', Challenge); export default Challenge; ================================================ FILE: platform/resources/jsx/challenges/manage_challenge.jsx ================================================ import React from 'react'; import axios from 'axios'; import Quill from 'quill'; import Util from 'js/util'; class ManageChallenge extends React.Component { constructor(props) { super(props); this.state = { ...props.challenge, challenge_id: this.props.mode === 'create' ? -1 : this.props.challenge.challenge_id, editing_test: {} // The test being edited (to show edit section) }; this.handle_change = this.handle_change.bind(this); this.manage_test = this.manage_test.bind(this); this.save_test = this.save_test.bind(this); this.delete_test = this.delete_test.bind(this); this.save = this.save.bind(this); } componentDidMount() { let Inline = Quill.import('blots/inline'); class Badge extends Inline {} Badge.blotName = 'badge'; Badge.tagName = 'span'; Badge.className = 'value-badge'; Badge.formats = () => true; Quill.register(Badge); let quill = new Quill('#html', { theme: 'snow', modules: { syntax: false, toolbar: [ ['bold', 'italic', 'underline', 'strike'], [ { header: 1 }, { header: 2 }, { header: 3 }, { header: 4 } ], ['blockquote', 'code-block', 'link'], [{ list: 'ordered' }, { list: 'bullet' }], //['badge'], ['clean'] ] } }); quill.on('text-change', () => { this.setState({ html: quill.root.innerHTML }); }); if (this.props.mode === 'update') { quill.clipboard.dangerouslyPasteHTML(this.state.html); } } handle_change(e) { let id = e.target.id; let value = e.target.value; // Handles changes in challenge data if (id.indexOf('test-') === -1) { if (id === 'draft') { value = this.state.draft ? 0 : 1; } return this.setState({ [id]: value }); } // Handles changes in tests data const editing_test = this.state.editing_test; editing_test[id.replace('test-', '')] = value; return this.setState({ editing_test }); } async save() { if (this.state.tests.length === 0) { return bootbox.alert('Please add at least one test.'); } let url = this.props.mode === 'create' ? '/admin/challenges/create' : '/admin/challenges/update/' + this.state.challenge_id; let res = await axios.post(url, { draft: this.state.draft, difficulty: this.state.difficulty, points: this.state.points, name: this.state.name, description: this.state.description, html: this.state.html, tests: this.state.tests }); if (res.status >= 400) { return bootbox.alert('An error has occurred'); } location = '/admin/challenges'; } manage_test(editing_test) { this.setState({ editing_test }); } async delete_test(index_to_delete) { let current_tests = this.state.tests; current_tests.splice(index_to_delete, 1); this.setState({ tests: current_tests, editing_test: {} }); } async save_test() { let current_tests = this.state.tests; let editing_test = this.state.editing_test; if (!editing_test.name || !editing_test.input || !editing_test.output) { return bootbox.alert('Please provide all data.'); } if (!Util.are_test_cases_valid(editing_test)) { return bootbox.alert('Invalid test cases'); } if (editing_test.index === -1) { current_tests.push(editing_test); return this.setState({ tests: current_tests, editing_test: {} }); } let test_to_edit = current_tests[editing_test.index]; current_tests.splice( current_tests.indexOf(test_to_edit), 1, editing_test ); return this.setState({ tests: current_tests, editing_test: {} }); } render() { return (

Manage Challenge

{this.state.html.indexOf('em_challenge_abstract"') !== -1 && (
Editing is not supported for this challenge unless reformatted.
)}
{' '} Draft

Test Cases this.manage_test({ challenge_id: this.state.challenge_id, name: '', input: '', output: '', index: -1 }) } > {' '}

{Object.keys(this.state.editing_test).length > 0 && (
)} {!!this.state.tests.length && this.state.tests.map((test, index) => { test.index = index; return ( ); })}
Name
this.manage_test(test) } > {' '} this.delete_test(index) } > {test.name}
); } } Util.try_render('react_manage_challenge', ManageChallenge); export default ManageChallenge; ================================================ FILE: platform/resources/jsx/cli_script.jsx ================================================ import React from 'react'; import Util from 'js/util'; class CliScript extends React.Component { componentDidMount() { let editor = monaco.editor.create(document.getElementById('editor'), { theme: 'em', value: this.props.content, language: 'shell', automaticLayout: true, fontSize: 16, readOnly: true, wordWrap: 'off', scrollBeyondLastLine: false, scrollbar: { vertical: 'hidden' }, minimap: { enabled: false } }); document.getElementById('editor').style.height = editor.getModel().getLineCount() * 22 + 'px'; } render() { return
; } } Util.try_render('react_cli_script', CliScript); export default CliScript; ================================================ FILE: platform/resources/jsx/contests/contest.jsx ================================================ import React from 'react'; import axios from 'axios'; import moment from 'moment'; import Util from 'js/util'; import Description from './description'; class Contest extends React.Component { constructor(props) { super(props); this.state = { contest: props.contest, language: '', language_version: '', solution: '', explanation: '', languages: [], passed: true, validating: false, submitting: false, shown_submissions: [], showing_late: false, filtered_language: 'all', filtered_language_version: '' }; this.encoder = new TextEncoder(); this.on_time_submissions = []; this.late_submissions = []; // choose the right initial on time solution by length let submission = props.submissions .filter((submission) => !submission.late) .sort((a, b) => (a.length > b.length ? 1 : -1))[0]; if (submission) { this.state.language = submission.language; this.state.language_version = submission.language_version; this.state.solution = submission.solution; this.state.explanation = submission.explanation; } if (this.state.contest.submissions.length > 0) { this.on_time_submissions = this.state.contest.submissions.filter( (submission) => !submission.late ); this.late_submissions = this.state.contest.submissions.filter( (submission) => submission.late ); } this.filter_languages = this.filter_languages.bind(this); } highlight_blocks() { $('.ql-syntax').each(function (i, block) { hljs.highlightBlock(block); }); } async componentDidMount() { this.highlight_blocks(); let languages = await axios.get('/api/v2/piston/runtimes'); let disallowed_languages = await axios.get( '/contests/disallowed_languages/' + this.state.contest.contest_id ); disallowed_languages = disallowed_languages.data; languages = languages.data .sort((a, b) => (a.language < b.language ? -1 : 1)) .reduce((a, c) => { if (a.find((l) => l.language === c.language)) { return a; } let tmp = languages.data .filter((language) => language.language === c.language) .sort((a, b) => (a.version > b.version ? -1 : 1)); a.push(tmp[0]); return a; }, []) .filter((lang) => !disallowed_languages.includes(lang.language)); this.setState({ languages, language: this.state.language || languages[0].language, language_version: this.state.language_version || languages[0].version, shown_submissions: this.on_time_submissions }); } handle_change = (e) => { let id = e.target.id; let value = e.target.value; if (id === 'language') { let [language, language_version] = value.split('-'); let submission = this.props.submissions.find((submission) => { return ( submission.language === language && submission.language_version === language_version && !!submission.late === !this.state.contest.active ); }); this.setState({ solution: submission ? submission.solution : '', explanation: submission ? submission.explanation : '', language, language_version }); } else { this.setState({ [id]: value }); } }; filter_languages = (e) => { let [filtered_language, filtered_language_version] = e.target.value.split('-'); if (filtered_language === 'all') { filtered_language_version = ''; } let shown_submissions = this.state.showing_late ? this.late_submissions : this.on_time_submissions; if (filtered_language != 'all') { shown_submissions = shown_submissions.filter( (submission) => submission.language === filtered_language && submission.language_version === filtered_language_version ); } this.setState({ filtered_language, filtered_language_version, shown_submissions }); }; toggle_explanation = (submission) => { submission.explanation_open = !submission.explanation_open; this.setState((prev) => { return { shown_submissions: prev.shown_submissions }; }); }; set_late = (showing_late) => { // update the main list of submissions let shown_submissions = showing_late ? this.late_submissions : this.on_time_submissions; // update the user specific submission let submission = this.props.submissions .filter((submission) => showing_late ? submission.late : !submission.late ) .sort((a, b) => (a.length > b.length ? 1 : -1))[0]; this.setState((prev) => { return { showing_late, shown_submissions, language: submission ? submission.language : prev.language, language_version: submission ? submission.language_version : prev.language_version, solution: submission ? submission.solution : '', explanation: submission ? submission.explanation : '', filtered_language: 'all', filtered_language_version: '' }; }); }; submit = async () => { this.setState({ passed: true }); const { language, solution, explanation, language_version } = this.state; this.setState({ submitting: true }); let result = await axios.post('/contests/submit', { contest_id: this.state.contest.contest_id, language, solution, explanation, language_version }); this.setState({ submitting: false }); if (result.status >= 400) { return bootbox.alert('An error has occurred'); } if (result.data.passed) { return bootbox.alert( 'Your solution succeeded and has been recorded/updated.', () => { location = location; } ); } this.setState({ passed: false }); }; async delete(contest_submission_id) { bootbox.confirm({ message: 'Are you sure you want to delete this submission?', buttons: { confirm: { label: 'Delete', className: 'btn-danger' }, cancel: { label: 'Cancel', className: 'btn-secondary' } }, callback: async (result) => { if (!result) { return; } let res = await axios.post('/admin/submissions/delete', { contest_submission_id }); location = location; } }); } validate = async () => { this.setState({ validating: true }); let res = await axios.post( '/admin/submissions/validate/' + this.state.contest.contest_id ); let { invalids } = res.data; this.setState({ validating: false }); if (!invalids.length) { return bootbox.alert('No invalid submissions were found'); } let invalids_str = ''; for (let invalid of invalids) { invalids_str += `(#${invalid.contest_submission_id}) ${invalid.user.username}'s ${invalid.language}\ submission of length ${invalid.length}
`; } return bootbox.alert( 'The following invalid submissions were found:
' + invalids_str ); }; render() { const active = this.state.contest.active; return (

{this.state.contest.name}

Test Cases
{this.props.cases.map((c, i) => { return (
Test Case {i + 1}
                                    {c.hide_input &&
                                    (active || c.hide_ignore_active) ? (
                                        
                                            {c.args.length} hidden argument(s)
                                        
                                    ) : (
                                        c.args.map((input, i) => {
                                            return (
                                                
Argument {i + 1} {'\n'} {input} {'\n'}
); }) )} {'\n'} {c.hide_output && (active || c.hide_ignore_active) ? ( Hidden Output ) : ( <> Expected Output {'\n'} {c.output.replace(/\\n/g, '\n')} )}
); })}
Your Submission
{(ctx.user_id && (
{((active || this.state.showing_late) && ( <>

It's recommended that you compose your solution separately and just paste here once you're ready. After clicking "Submit Solution" your solution will be tested with the given inputs. If successful, your solution will be saved. Be sure to choose the correct language.

{this.props.submissions && this.props.submissions.length > 0 && (
You have solutions in:{' '} {this.props.submissions .filter((s) => this.state .showing_late ? s.late : !s.late ) .map( (submission, i) => { return ( { submission.language }{' '} ( { submission.length } ) {i + 1 < this .props .submissions .length && ', '} ); } )}
)}
{ this.encoder.encode( this.state.solution.trim() ).length }{' '} bytes

{' '} {!this.state.passed && ( Sorry, your solution does not satisfy the requirements )}
)) || (

This contest is no longer active but you can still submit a late solution. Click on the "Late" tab below and then submit as usual. Note that late submissions will not receive any points.

)}
)) || (
You are not logged in. To submit a solution, click the Login button at the top right.
)}
Submissions
{!!ctx.is_staff && (
{' '}
)}
{!active && ( )} {this.state.shown_submissions.map((submission) => { return (
{submission.length} bytes with{' '} {submission.language}{' '} {submission.overall_first && ( )}{' '} {submission.overall_second && ( )}{' '} {submission.overall_third && ( )}{' '} {submission.language_first && ( )}
Submitted:{' '} {moment(submission.created_at).format( 'MMMM D, YYYY @ h:mm:ss a' )}{' '} (#{submission.contest_submission_id}){' '} {!!ctx.is_staff && ( this.delete( submission.contest_submission_id ) } class="fas fa-trash text-danger pointer" > )}
{!active && !!submission.explanation && (
this.toggle_explanation( submission ) } > {submission.explanation_open ? 'Hide' : 'Show'}{' '} Explanation
)}
{' '} {submission.user.username}
{!active && (
                                    {submission.solution}
                                
)} {!active && !!submission.explanation_open && (
The following explanation was provided:
                                        {submission.explanation}
                                    
)}
); })}
); } } Util.try_render('react_contest_contest', Contest); export default Contest; ================================================ FILE: platform/resources/jsx/contests/description.jsx ================================================ import React from 'react'; import Quill from 'quill'; class Description extends React.PureComponent { ops_to_html(ops) { try { ops = JSON.parse(ops).ops; var tmp = document.createElement('div'); new Quill(tmp, { modules: { syntax: true } }).setContents(ops); return tmp.getElementsByClassName('ql-editor')[0].innerHTML; } catch (e) { return ''; } } render() { return (
); } } export default Description; ================================================ FILE: platform/resources/jsx/contests/manage.jsx ================================================ import React from 'react'; import axios from 'axios'; import Quill from 'quill'; import Util from 'js/util'; class Manage extends React.Component { constructor(props) { super(props); this.state = { ...props.contest, languages: [] }; } async componentDidMount() { this.quill = new Quill('#description', { theme: 'snow', modules: { syntax: true, toolbar: [ ['bold', 'italic', 'underline', 'strike'], ['blockquote', 'code-block', 'link'], [{ header: 1 }, { header: 2 }], [{ list: 'ordered' }, { list: 'bullet' }], ['clean'] ] } }); if (this.props.mode === 'update') { this.quill.setContents(JSON.parse(this.state.description)); } let disallowed_languages = this.state.disallowed_languages ? this.state.disallowed_languages.split(',') : []; let { data: languages } = await axios.get('/api/v2/piston/runtimes'); languages = languages .sort((a, b) => (a.language < b.language ? -1 : 1)) .reduce((a, c) => { c.enabled = !disallowed_languages.includes(c.language); if (a.find((l) => l.language === c.language)) { return a; } let tmp = languages .filter((language) => language.language === c.language) .sort((a, b) => (a.version > b.version ? -1 : 1)); a.push(tmp[0]); return a; }, []); this.setState({ disallowed_languages, languages }); } handle_change = (e) => { let id = e.target.id; let value = e.target.value; this.setState({ [id]: value }); }; handle_language_change = (e) => { e.persist(); let name = e.target.id; this.setState((prev) => { const languages = prev.languages.map((language) => { if (language.language === name) { language.enabled = e.target.checked; } return language; }); return { languages }; }); }; select = (all) => { this.setState((prev) => { const languages = prev.languages.map((language) => { language.enabled = all ? true : !language.enabled; return language; }); return { languages }; }); }; save = async () => { let { name, start_date, end_date, input, output, disallowed_languages } = this.state; const description = JSON.stringify(this.quill.getContents()); if (!Util.are_test_cases_valid({ input, output })) { return bootbox.alert('Invalid test cases'); } const url = this.props.mode === 'update' ? '/admin/contests/update/' + this.props.contest_id : '/admin/contests/create'; disallowed_languages = this.state.languages .filter((language) => !language.enabled) .map((language) => language.language) .concat(this.props.languages.disallowed_languages) .join(','); const res = await axios.post(url, { name, description, start_date, end_date, input, output, disallowed_languages }); if (res.status === 400) { return bootbox.alert(res.data.message); } if (res.status >= 400) { return bootbox.alert('An error has occurred'); } location = '/admin/contests'; }; render() { return (
{' '}
{this.state.languages.map((lang) => { return (
{' '} {lang.language} ( {lang.runtime ? `via ${lang.runtime} ` : ''} {lang.version})
); })}
); } } Util.try_render('react_contest_manage', Manage); export default Manage; ================================================ FILE: platform/resources/jsx/login.jsx ================================================ import React from 'react'; import Util from 'js/util'; class Login extends React.Component { constructor(props) { super(props); this.state = { open: false }; this.open = this.open.bind(this); this.close = this.close.bind(this); } open(redirect) { this.setState({ open: true, redirect: redirect || location.pathname }); } close() { this.setState({ open: false }); } render() { return ( ); } } window.login = Util.try_render('react_login', Login); export default Login; ================================================ FILE: platform/resources/jsx/manage_snippet.jsx ================================================ import React from 'react'; import axios from 'axios'; import Util from 'js/util'; class ManageSnippet extends React.Component { constructor(props) { super(props); this.state = { snip: this.props.mode === 'create' ? '' : this.props.snip, language: this.props.mode === 'create' ? 'javascript' : this.props.language, word_wrap: 'off', runnable_language: false, executing: false, stdin: '', argv: '', compile_output: '', stdout: '', stderr: '' }; this.monaco_piston_map = { abap: 'none', aes: 'none', apex: 'none', awk: 'awk', azcli: 'none', bat: 'none', bicep: 'none', c: 'c', cameligo: 'none', cjam: 'cjam', clojure: 'clojure', cobol: 'cobol', coffeescript: 'coffeescript', cow: 'cow', cpp: 'cpp', crystal: 'crystal', csharp: 'csharp', csp: 'none', css: 'none', d: 'd', dart: 'dart', dash: 'dash', dockerfile: 'none', dragon: 'dragon', ecl: 'none', elixir: 'elixir', emacs: 'emacs', erlang: 'erlang', fortran: 'fortran', fsharp: 'fsharp.net', go: 'go', golfscript: 'golfscript', graphql: 'none', groovy: 'groovy', handlebars: 'none', haskell: 'haskell', hcl: 'none', html: 'none', ini: 'none', java: 'java', javascript: 'javascript', jelly: 'jelly', json: 'none', julia: 'julia', kotlin: 'kotlin', less: 'none', lexon: 'none', liquid: 'none', lisp: 'lisp', lua: 'lua', lolcode: 'lolcode', m3: 'none', markdown: 'none', mips: 'none', msdax: 'none', mysql: 'none', sql: 'sqlite', 'objective-c': 'none', nasm: 'nasm', nasm64: 'nasm64', nim: 'nim', ocaml: 'ocaml', octave: 'octave', osabie: 'osabie', paradoc: 'paradoc', pascal: 'pascal', pascaligo: 'none', perl: 'perl', pgsql: 'none', php: 'php', plaintext: 'none', ponylang: 'ponylang', postiats: 'none', powerquery: 'none', powershell: 'powershell', prolog: 'prolog', pure: 'pure', pug: 'none', pyth: 'pyth', python: 'python', python2: 'python2', qsharp: 'none', r: 'r', raku: 'raku', razor: 'none', redis: 'none', redshift: 'none', restructuredtext: 'none', rockstar: 'rockstar', ruby: 'ruby', rust: 'rust', sb: 'none', scala: 'scala', scheme: 'none', scss: 'none', shell: 'bash', sol: 'none', sparql: 'none', st: 'none', swift: 'swift', systemverilog: 'none', tcl: 'none', twig: 'none', typescript: 'typescript', vb: 'vb', verilog: 'none', vlang: 'vlang', xml: 'none', yaml: 'none', yeethon: 'yeethon', zig: 'zig' }; this.change_language = this.change_language.bind(this); this.handle_change = this.handle_change.bind(this); this.execute = this.execute.bind(this); this.toggle_word_wrap = this.toggle_word_wrap.bind(this); this.save = this.save.bind(this); } componentDidMount() { this.state.editor = monaco.editor.create( document.getElementById('editor'), { theme: 'em', language: this.state.language, automaticLayout: true, value: this.state.snip, readOnly: this.props.mode === 'view', fontSize: 16 } ); this.props.mode !== 'view' && this.state.editor.addCommand( monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, this.save ); this.state.editor.addCommand(monaco.KeyCode.F9, this.execute); this.check_runnable_language(); } check_runnable_language() { this.setState({ runnable_language: this.state.language in this.monaco_piston_map && this.monaco_piston_map[this.state.language] !== 'none' }); } async execute() { if (!this.state.runnable_language) { return; } this.setState({ executing: true }); const result = await axios.post('/api/v2/piston/execute', { language: this.state.language, version: '*', files: [{ content: this.state.editor.getValue() }], args: this.state.argv === '' ? [] : this.state.argv.split('\n'), stdin: this.state.stdin }); this.setState({ executing: false }); if (result.status === 429) { return bootbox.alert( 'You are executing the snippet too many times.' ); } if (result.status >= 400) { return bootbox.alert('An internal error has occurred.'); } // Check if it is a compiled language const compile_output = 'compile' in result.data ? result.data.compile.output : ''; const { stdout, stderr } = result.data.run; this.setState({ compile_output, stdout, stderr }); } handle_change(e) { this.setState({ [e.target.id]: e.target.value }); } change_language(event) { this.setState( { language: event.target.value }, this.check_runnable_language ); monaco.editor.setModelLanguage( this.state.editor.getModel(), event.target.value ); } toggle_word_wrap() { const word_wrap = this.state.word_wrap === 'off' ? 'bounded' : 'off'; this.state.editor.updateOptions({ wordWrap: word_wrap }); this.setState({ word_wrap }); } async save() { const url = this.props.mode === 'update' ? '/snippets/edit/' + this.props.hash : '/snippets'; const res = await axios.post(url, { language: this.state.language, snip: this.state.editor.getValue() }); if (res.status >= 300) { return bootbox.alert('Please provide some code'); } location = res.data.url; } render() { return (
{this.state.runnable_language && (
{this.state.compile_output}
{this.state.stdout}
{this.state.stderr}
)}
); } } Util.try_render('react_manage_snippet', ManageSnippet); export default ManageSnippet; ================================================ FILE: platform/resources/jsx/mobile_nav.jsx ================================================ import React from 'react'; import Util from 'js/util'; class MobileNav extends React.Component { constructor(props) { super(props); this.state = { open: false }; this.open = this.open.bind(this); this.close = this.close.bind(this); } open(redirect) { this.setState({ open: true }); } close() { this.setState({ open: false }); } render() { return (
); } } window.mobile_nav = Util.try_render('react_mobile_nav', MobileNav); export default MobileNav; ================================================ FILE: platform/resources/jsx/ppman.jsx ================================================ import React from 'react'; import axios from 'axios'; import Util from 'js/util'; class PistonPackageManager extends React.Component { constructor(props) { super(props); this.state = { packages: [], message: props.message }; } async componentDidMount() { let { data: packages } = await axios.get('/admin/piston/packages'); this.setState({ packages }); } render() { return (

{this.state.message}

{this.state.packages.map((pkg) => { return ( ); })}
Name Version Installed
{(pkg.installed && ( Uninstall )) || ( Install )} {pkg.language} {pkg.language_version} {pkg.installed ? 'Yes' : 'No'}
); } } Util.try_render('react_ppman', PistonPackageManager); export default PistonPackageManager; ================================================ FILE: platform/resources/jsx/stickers.jsx ================================================ import React from 'react'; import ReactDOM from 'react-dom'; import axios from 'axios'; import Util from 'js/util'; class Stickers extends React.Component { constructor(props) { super(props); this.state = { done: false, valid: false, discounted: false, env: props.env || 'sandbox', quantity: props.options[1].quantity, name: '', email: '', address: '', coupon: '' }; this.handle_update = this.handle_update.bind(this); this.check_coupon = this.check_coupon.bind(this); this.submit = this.submit.bind(this); this.check_coupon_timer = null; } componentDidMount() { paypal.Button.render( { env: this.props.env, client: { sandbox: this.props.paypal_id, production: this.props.paypal_id }, locale: 'en_US', style: { size: 'medium', color: 'blue', shape: 'rect', tagline: false }, commit: true, payment: (data, actions) => { return actions.payment.create({ transactions: [ { amount: { total: this.props.options.find( (option) => option.quantity === this.state.quantity ).cost, currency: 'USD' }, description: this.state.quantity + ' 2" x 2" Engineer Man Stickers' } ] }); }, onAuthorize: async (data, actions) => { return actions.payment.execute().then(async (details) => { let res = await axios.post('/stickers/order', { tx: details.transactions[0].related_resources[0] .sale.id, quantity: this.state.quantity, name: this.state.name, email: this.state.email, address: this.state.address, coupon: null }); return bootbox.alert( 'Your order was placed successfully, thanks. Please ' + 'reference Order ID #' + res.data.order_id + ' if necessary.', () => { location = location; } ); }); } }, '#paypal-button' ); } handle_update(e) { e.persist(); this.setState( { [e.target.id]: e.target.value }, () => { if (e.target.id === 'coupon') { this.check_coupon(); } this.setState({ valid: this.state.name && this.state.email && this.state.address }); } ); } check_coupon() { clearInterval(this.check_coupon_timer); this.check_coupon_timer = setTimeout(async () => { let res = await axios.get( '/stickers/check_code/' + this.state.coupon ); let valid = res.data.valid; if (valid) { this.setState({ discounted: valid, quantity: 2 }); } }, 300); } submit(e) { return axios .post('/stickers/order', { tx: null, quantity: this.state.quantity, name: this.state.name, email: this.state.email, address: this.state.address, coupon: this.state.valid ? this.state.coupon : null }) .then((res) => { if (res.status >= 300) { return bootbox.alert( 'There was a problem submitting your order' ); } return bootbox.alert( 'Your order was placed successfully, thanks. Please ' + 'reference Order ID #' + res.data.order_id + ' if necessary.', () => { location = location; } ); }); } render() { return ( <>

Engineer Man Stickers 2" x 2"

Stickers are made with vinyl making them weatherproof and resistant to scratching and fading. Stickers cannot be removed and reapplied.


{(this.state.discounted && (
2 for FREE
)) || this.props.options .filter((option) => option.cost !== 'FREE') .map((option) => { return ( <>
this.setState({ quantity: option.quantity }) } > {option.quantity} for $ {option.cost}
{' '} ); })}
{this.state.coupon && this.state.discounted && ( Coupon valid )}
{(this.state.discounted && ( )) || (
)} ); } } Util.try_render('react_stickers', Stickers); export default Stickers; ================================================ FILE: platform/resources/jsx/users.jsx ================================================ import React from 'react'; import axios from 'axios'; import moment from 'moment'; import Util from 'js/util'; class Users extends React.Component { constructor(props) { super(props); this.state = { users: props.users }; } search = (e) => { let users = this.props.users.filter((user) => user.display_name .toLowerCase() .includes(e.target.value.toLowerCase()) ); this.setState({ users }); }; render() { return (
{this.state.users.map((user) => { return ( ); })}
User ID Username Display Name Registered
); } } Util.try_render('react_users', Users); export default Users; ================================================ FILE: platform/resources/less/bootstrap.less ================================================ .btn-success { background-color: #37b86e; &:hover { background-color: #289254; } } .badge-success { background-color: #37b86e; } .dropdown-menu { a:visited, a:link, a:hover { color: #333 !important; } a:active { color: #fff !important; } .dropdown-item { &:active { background-color: #36b96e; } } } .bootbox-body { text-align: left; color: #000; } .highlightjs * { font-size: 14px !important; font-family: monospace !important; } select { background: none !important; outline: none !important; border: #999 1px solid !important; background: #282c34 !important; color: #fff !important; } input.form-control, textarea.form-control { background: none !important; border: 0 !important; border-bottom: #666 1px solid !important; padding-left: 0 !important; outline: 0 !important; color: #fff !important; &:focus { box-shadow: none !important; outline: 0 !important; } } .form-box { padding: 15px; background: #21252b; margin: 30px 0; } hr { border-top: #000 1px solid; } .btn { &:focus { box-shadow: none; } } table { th { border-top: 0 !important; } } .text-warning { color: #ffdd78 !important; } ================================================ FILE: platform/resources/less/colors.less ================================================ @challenge_easy: #84e47f; @challenge_medium: #e4e37f; @challenge_hard: #e47f8d; .green { color: #8aecb4; } ================================================ FILE: platform/resources/less/em/challenge.less ================================================ @import '../colors.less'; .em_challenge { position: absolute; top: 56px; left: 0; right: 0; bottom: 0; display: flex; pre { font: inherit; color: inherit; display: inline; } .instructions { width: 360px; overflow-y: auto; padding: 15px; } .editor { flex: 1; position: relative; } #editor { position: absolute; top: 0; left: 0; right: 0; bottom: 0; } .easy { color: @challenge_easy; } .medium { color: @challenge_medium; } .hard { color: @challenge_hard; } .results { position: fixed; top: 70%; bottom: 0; left: 454px; right: 30px; background: rgba(0, 0, 0, 0.3); padding: 25px; overflow: auto; .result { background: rgba(0, 0, 0, 0.2); padding: 10px 15px; margin-bottom: 10px; color: #fff; font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; } } } ================================================ FILE: platform/resources/less/em/challenge_abstract.less ================================================ .em_challenge .abstract, #react_manage_challenge .ql-editor { .input { p:last-child { margin-bottom: 0; } } .wrap { word-break: break-all; } .test_case { background: rgba(0, 0, 0, 0.2); padding: 10px 15px; margin-bottom: 10px; color: #fff; font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; > * { margin-bottom: 5px; } } p { margin: 0; padding: 0; } h4 { font-weight: 300; } .value-badge { color: #fff; background-color: #007bff; display: inline-block; padding: 0.25em 0.4em; font-size: 75%; font-weight: 700; line-height: 1; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } pre { display: block; font-size: 87.5%; color: #212529; } .section { margin-bottom: 30px; } .input { background: rgba(0, 0, 0, 0.2); padding: 10px 15px; margin-bottom: 10px; color: #fff; } .ql-syntax { background: rgba(0, 0, 0, 0.2); padding: 10px 15px; margin-bottom: 20px; margin-top: -5px; color: #fff; } } ================================================ FILE: platform/resources/less/em/challenge_manage.less ================================================ .em_challenge_manage { .case_box { padding: 15px; background: #1b1f27; } } ================================================ FILE: platform/resources/less/em/challenges_list.less ================================================ @import '../colors.less'; .em_challenges_list { .challenge_list { margin-bottom: 20px; .challenge { display: block; background: #21252b; padding: 10px; margin-bottom: 8px; color: #fff; .title { font-size: 18px; } .description { font-weight: 300; } &:hover { background: #2f353e; } } } .easy { .title { .badge { float: right; } .text { color: @challenge_easy; } } } .medium { .title { .badge { float: right; } .text { color: @challenge_medium; } } } .hard { .title { .badge { float: right; } .text { color: @challenge_hard; } } } } ================================================ FILE: platform/resources/less/em/common_content.less ================================================ .em_common_content { max-width: 1140px; width: 100%; margin-left: auto; margin-right: auto; padding: 40px 15px; h4 { margin-bottom: 10px; } .version { margin-top: -5px; } .col-4 { margin-top: 5px; } } .em_wide_content { padding: 20px 15px; h4 { margin-bottom: 10px; } } ================================================ FILE: platform/resources/less/em/community_map.less ================================================ .em_community_map { max-width: 1100px; width: 100%; margin: auto; padding: 30px 15px; .link_list { background: #000; background: #21252b; padding: 10px; margin-bottom: 20px; a { display: block; margin-bottom: 6px; &:last-child { margin-bottom: 0; } } } } ================================================ FILE: platform/resources/less/em/container.less ================================================ .em_container { display: inline-block; margin: auto; /*max-width: 1440px;*/ width: 100%; text-align: left; background: #282c34; min-height: 100vh; } ================================================ FILE: platform/resources/less/em/contests/contest.less ================================================ .em_contests_contest { .ql-editor { padding-left: 0; padding-right: 0; } .header { margin-bottom: 0; } .description { padding: 30px 0; } .case_text { color: #fff; background: #24282f; padding: 8px; } .submission { padding: 10px; background: rgba(0, 0, 0, 0.1); margin-bottom: 10px; .heading { display: flex; .main { flex: 1; } .summary { img { width: auto; height: 28px; margin-left: 6px; } } .user { padding-top: 8px; color: #fff; img { width: 28px; height: 28px; } } .time { font-size: 12px; color: #aaa; } .explanation_text { font-size: 12px; } } .solution { margin-left: -8px; margin-right: -8px; margin-top: 5px; padding: 10px; font-size: 12px; font-family: monospace; word-wrap: break-word; color: #fff; background: rgba(0, 0, 0, 0.1); margin-bottom: 0; white-space: pre-wrap; } } .tab-active { background-color: #3771b8; } .space-between { display: flex; justify-content: space-between; align-items: center; } } ================================================ FILE: platform/resources/less/em/contests/home.less ================================================ .em_contests_home { * { color: #fff; } .active { margin-bottom: 40px; } .past { margin-bottom: 40px; } .contest { display: block; background: rgba(0, 0, 0, 0.3); padding: 15px; margin-bottom: 20px; .name { font-size: 22px; margin-bottom: 10px; } .time_left { background: rgba(67, 103, 82, 0.5); padding: 8px 12px; margin-bottom: 6px; } .solutions { background: rgb(37, 42, 49); padding: 8px 12px; font-size: 20px; font-weight: 700; margin-top: 14px; img { width: 32px; height: 32px; margin-bottom: 4px; } } } } ================================================ FILE: platform/resources/less/em/contests/manage.less ================================================ .em_contest_manage { .wrapper { display: flex; .left { flex: 1; padding-right: 15px; } .right { width: 300px; } } .control_button { margin-top: 10px; width: 150px; } } ================================================ FILE: platform/resources/less/em/footer.less ================================================ .em_footer { position: absolute; bottom: 0; left: 0; right: 0; background: #36b96e; font-size: 12px; padding: 0 10px; text-align: right; a { color: #fff; } } ================================================ FILE: platform/resources/less/em/language_choice.less ================================================ @import '../colors.less'; .em_language_choice { .icons > div { text-align: center; margin-bottom: 30px; } h4 { margin: 15px 0; } .easy { color: @challenge_easy; } .medium { color: @challenge_medium; } .hard { color: @challenge_hard; } } .badge-easy { background-color: @challenge_easy; } .badge-medium { background-color: @challenge_medium; } .badge-hard { background-color: @challenge_hard; } ================================================ FILE: platform/resources/less/em/login.less ================================================ .em_login { display: none; &.open { display: block; } .backdrop { position: absolute; top: 0; left: 0; bottom: 0; right: 0; background: rgba(0, 0, 0, 0.2); text-align: center; z-index: 10; } .close { position: absolute; top: 8px; right: 8px; cursor: pointer; i { color: #fff; &:hover { color: #eee; } } } .box { display: inline-block; position: relative; max-width: 450px; width: 100%; margin-top: 30px; background: #222; padding: 30px; p { color: #aaa; margin-top: 20px; margin-bottom: 25px; } a { color: #fff; background: #7289da; &:hover { background: #687bc0; } } } } ================================================ FILE: platform/resources/less/em/manage_snippet.less ================================================ .em_manage_snippet { #editor { height: calc(100vh - 144px); @media (max-width: 700px) { height: calc(100vh - 190px); } } .menu { .wrapper { display: flex; background: #21252b; align-items: center; padding: 10px 10px 10px 75px; @media (max-width: 700px) { display: grid; grid-template-columns: 1fr; align-items: unset; place-items: center; gap: 0.5rem; } > * { display: inline-block; vertical-align: middle; } .language { flex: 1; select { width: 200px; } } .language_label { margin-right: 10px; flex: 1; } .control-button { margin-right: 0.5rem; } } } .run-data { display: flex; width: 100%; overflow: auto; pre { font: unset; color: unset; } .inputs-outputs { width: 100%; padding: 20px 15px; } } .info { background-color: rgba(0, 0, 0, 0.3); min-height: 20px; margin-bottom: 10px; padding: 10px 5px 5px 5px; overflow-x: auto; max-width: 600px; } } ================================================ FILE: platform/resources/less/em/menu.less ================================================ .em_menu { display: flex; padding: 10px; background: #36b96e; .mobile_expand { display: none; i { color: #fff; font-size: 20px; margin: 8px; cursor: pointer; margin-right: 14px; } @media (max-width: 700px) { display: inline; } } .brand_icon { display: inline; img { height: 36px; width: auto; } img:hover { opacity: 70%; } } .main_links { display: inline-block; > * { display: inline-block; vertical-align: middle; } > a { background: rgb(18, 101, 54); color: #fff !important; margin-left: 10px; border-radius: 5px; cursor: pointer; padding: 6px 10px; &:hover { background: #349a60 !important; } } > .dropdown { background: rgb(18, 101, 54); color: #fff !important; margin-left: 10px; border-radius: 5px; cursor: pointer; > a { color: #fff !important; padding: 5px 10px; display: inline-block; } &:hover { background: #349a60; } } @media (max-width: 700px) { display: none; } } .search { flex: 1; margin-left: 10px; margin-right: 10px; input { width: 100%; border: none; background: #4aa571; outline: none; color: #fff; padding: 6px 10px; border-radius: 5px; &::-webkit-input-placeholder { color: #fff; } &:-moz-placeholder { color: #fff; opacity: 1; } &::-moz-placeholder { color: #fff; opacity: 1; } &:-ms-input-placeholder { color: #fff; } &::-ms-input-placeholder { color: #fff; } &::placeholder { color: #fff; } } } .user_meta { * { vertical-align: middle; } img { border-radius: 50%; height: 36px; width: auto; margin-left: 10px; } .dropdown { display: inline-block; cursor: pointer; } i { margin-right: 3px; } @media (max-width: 700px) { display: none; } } .login { > a { display: inline-block; vertical-align: middle; background: #1987b1; color: #fff !important; border-radius: 5px; cursor: pointer; padding: 6px 10px; &:hover { background: #37a7d2 !important; } } } } ================================================ FILE: platform/resources/less/em/mobile_nav.less ================================================ .em_mobile_nav { display: none; &.open { display: inline; } .backdrop { position: absolute; top: 0; left: 0; bottom: 0; right: 0; background: rgba(0, 0, 0, 0.6); text-align: center; } .close { position: absolute; top: 8px; right: 8px; cursor: pointer; i { color: #fff; &:hover { color: #eee; } } } .menu { position: absolute; top: 0; left: 0; bottom: 0; width: 75%; background: #282c34; color: #fff; text-align: left; z-index: 1; .contents { padding: 16px; a { display: block; padding: 10px; background: #22262c; margin-bottom: 4px; } .spacer { height: 20px; } } } @media (min-width: 701px) { display: none !important; } } ================================================ FILE: platform/resources/less/em/power_system.less ================================================ .em_power_system { .tier_circle { border-radius: 50%; width: 100%; padding-top: 100%; position: relative; margin-bottom: 30px; .wrapper { position: absolute; top: ~'calc(50% - 30px)'; left: 0; right: 0; text-align: center; .tier { font-size: 26px; font-weight: 700; } .score { font-size: 26px; font-weight: 300; } } } .novice { background: #79acbf; } .hero { background: #7d9dc5; } .master { background: #acb2e4; } .legend { background: #d2ace4; } .power_list { .item { display: flex; background: #21252b; margin-bottom: 4px; padding: 6px 12px; font-size: 18px; div { flex: 1; color: #8fdcef; } span { width: 80px; padding-left: 30px; font-weight: 700; } } .heading:first-child { margin-top: 0; } .heading { margin-top: 30px; } } } ================================================ FILE: platform/resources/less/em/profile.less ================================================ @import '../colors.less'; .em_profile { .content { display: flex; .left { width: 220px; .padding { padding: 0 10px; } } .right { flex: 1; } } .avatar { width: 100%; height: auto; margin-bottom: 10px; } .awards { margin-bottom: 30px; .award { display: inline-block; text-align: center; margin: 5px 10px 10px 10px; img { margin-bottom: 5px; cursor: pointer; } } .count { background: rgba(0, 0, 0, 0.4); color: #fff; text-align: center; display: inline-block; border-radius: 20px; padding: 2px 10px; } } .challenge { display: block; background: rgba(0, 0, 0, 0.3); padding: 10px; margin-bottom: 10px; a { color: #fff; } &.easy { border-left: @challenge_easy 5px solid; } &.medium { border-left: @challenge_medium 5px solid; } &.hard { border-left: @challenge_hard 5px solid; } p { margin-bottom: 8px; } } .view_solution { width: 80px; height: 48px; background: #126536; padding-right: 10px; padding-left: 10px; margin-bottom: 10px; & p { margin-bottom: 0; } } } ================================================ FILE: platform/resources/less/em/staff_container.less ================================================ .em_staff_container { padding: 4px 10px; background: #313847; } ================================================ FILE: platform/resources/less/em/stickers.less ================================================ .em_stickers { .sticker { max-width: 200px; width: 100%; height: auto; margin-top: 20px; margin-bottom: 20px; } .quantity_option { display: inline-block; padding: 10px 18px; border: #555 1px solid; &.active { background: #208a4d; } &:hover { cursor: pointer; } } } ================================================ FILE: platform/resources/less/em/top_members.less ================================================ .em_top_members { .user_row { position: relative; display: flex; margin-bottom: 4px; background: #202329; .score_progress { position: absolute; left: 0; top: 85%; bottom: 0; } .picture { z-index: 1; img { width: 40px; height: 40px; } } .name { z-index: 1; flex: 1; .wrapper { display: inline-block; padding: 2px 8px; border-radius: 20px; text-align: center; margin-top: 6px; margin-left: 6px; color: #fff; } } .power { z-index: 1; width: 100px; text-align: right; .wrapper { display: inline-block; padding: 2px 8px; border-radius: 20px; text-align: center; margin-top: 6px; margin-right: 6px; color: #fff; } } } } ================================================ FILE: platform/resources/less/global.less ================================================ html, body { font-family: 'Lato', sans-serif; color: #fff; } body { text-align: center; background: #282c34; } a { color: #68e69e; &:visited, &:active { color: #68e69e; } &:hover { color: #32a965; text-decoration: none; } } table { .actions { a { margin-right: 10px; } } } .pointer { cursor: pointer; } .accent_text { font-style: italic; color: #8aecb4; } .center { text-align: center; } .f100 { font-weight: 100; } .f300 { font-weight: 300; } .f400 { font-weight: 400; } .f700 { font-weight: 700; } .f900 { font-weight: 900; } .margin0 { margin: 0 !important; } .margintop5 { margin-top: 5px !important; } .margintop10 { margin-top: 10px !important; } .margintop15 { margin-top: 15px !important; } .margintop20 { margin-top: 20px !important; } .margintop25 { margin-top: 25px !important; } .margintop30 { margin-top: 30px !important; } .margintop40 { margin-top: 40px !important; } .margintop50 { margin-top: 50px !important; } .margintop60 { margin-top: 60px !important; } .margintop70 { margin-top: 70px !important; } .margintop80 { margin-top: 80px !important; } .margintop90 { margin-top: 90px !important; } .margintop100 { margin-top: 100px !important; } .marginbottom0 { margin-bottom: 0 !important; } .marginbottom5 { margin-bottom: 5px !important; } .marginbottom10 { margin-bottom: 10px !important; } .marginbottom20 { margin-bottom: 20px !important; } .marginbottom30 { margin-bottom: 30px !important; } .marginbottom40 { margin-bottom: 40px !important; } .marginbottom50 { margin-bottom: 50px !important; } .marginbottom60 { margin-bottom: 60px !important; } .marginbottom70 { margin-bottom: 70px !important; } .marginbottom80 { margin-bottom: 80px !important; } .marginbottom90 { margin-bottom: 90px !important; } .marginbottom100 { margin-bottom: 100px !important; } .width-60 { width: 60px; } .width-80 { width: 80px; } ::selection { color: white; background: #32a965; } ================================================ FILE: platform/resources/less/highlightjs.less ================================================ td.hljs-ln-code { padding-left: 10px !important; } td.hljs-ln-numbers { background: #1b1f27; padding-left: 5px !important; padding-right: 15px !important; } ================================================ FILE: platform/resources/less/quill.less ================================================ .ql-toolbar { background: #1b1f27 !important; border: 0 !important; svg { * { stroke: #fff !important; } } .ql-strike, .ql-header { svg * { fill: #fff !important; } } .ql-picker-label { &:hover { color: #fff !important; } } button { &:hover { background: #4aa571 !important; } } } .ql-container { border: 0 !important; border-bottom: #7b7b7b 1px solid !important; font-size: 14px !important; background: #1b1f27 !important; font-family: Lato, sans-serif; } .ql-blank { &:before { color: #ddd !important; font-style: normal !important; } } .ql-editor { font-size: 16px; min-height: 200px; .ql-syntax { margin-top: 10px; * { font-family: monospace !important; } } } ================================================ FILE: platform/resources/main.js ================================================ import 'core-js/stable'; import 'regenerator-runtime/runtime'; import axios from 'axios'; try { axios.defaults.validateStatus = () => true; } catch (e) {} ((ctx) => { return ctx.keys().map(ctx); })(require.context('./js', true, /\.js$/)); ((ctx) => { return ctx.keys().map(ctx); })(require.context('./jsx', true, /\.jsx$/)); ((ctx) => { return ctx.keys().map(ctx); })(require.context('./less', true, /\.less$/)); ================================================ FILE: platform/resources/monaco.js ================================================ import * as monaco from 'monaco-editor'; monaco.editor.defineTheme('em', { base: 'vs-dark', inherit: true, rules: [{ background: '282C34' }], colors: { 'editorGutter.background': '#21252B', 'editor.background': '#282C34', 'scrollbarSlider.background': '#21252B', 'scrollbarSlider.hoverBackground': '#21252B', 'scrollbarSlider.activeBackground': '#21252B' } }); window.monaco = monaco; ================================================ FILE: platform/resources/twig/filters.js ================================================ const contains = (array, value) => { if (value === undefined || value === null) { return false; } for (let checking of array) { let found = true; for (let entry of Object.entries(checking)) { if (value[0][entry[0]] !== entry[1]) { found = false; } } if (found) { return true; } } return false; }; module.exports = [ { name: 'contains', filter: contains } ]; ================================================ FILE: platform/start ================================================ #!/usr/bin/env bash APPENV=${APPENV:-development} echo "running in $APPENV mode" if [ $APPENV == "production" ]; then npm run prod else npm run dev fi ================================================ FILE: platform/views/_emails/new_user.twig ================================================ {% extends '_emails/container.twig' %} {% block content %} {% endblock %} ================================================ FILE: platform/views/admin/challenges/update.twig ================================================ {% extends 'master.twig'%} {% block content %}
{% endblock %} ================================================ FILE: platform/views/admin/challenges/view_all.twig ================================================ {% extends 'master.twig'%} {% block content %}

Challenges

{% for challenge in challenges %} {% endfor %}
ID Difficulty Name
{{ challenge.challenge_id }} {{ challenge.difficulty_name }} {{ challenge.name }}
{% endblock %} ================================================ FILE: platform/views/admin/contests/update.twig ================================================ {% extends 'master.twig'%} {% block content %}

Manage Contest

{% endblock %} ================================================ FILE: platform/views/admin/contests/view_all.twig ================================================ {% extends 'master.twig'%} {% block content %}

Contests

{% for contest in contests %} {% endfor %}
ID Name Start End
{{ contest.contest_id }} {{ contest.name }} {{ contest.start_date|date('m/d/Y') }} {{ contest.end_date|date('m/d/Y') }}
{% endblock %} ================================================ FILE: platform/views/admin/dashboard/dashboard.twig ================================================ {% extends 'master.twig'%} {% block content %}

Dashboard

Nothing here, choose from above.
{% endblock %} ================================================ FILE: platform/views/admin/piston/view_all.twig ================================================ {% extends 'master.twig'%} {% block title %}Piston | EMKC{% endblock %} {% block content %}
{% endblock %} ================================================ FILE: platform/views/admin/users/view_all.twig ================================================ {% extends 'master.twig'%} {% block title %}Users | EMKC{% endblock %} {% block content %}
{% endblock %} ================================================ FILE: platform/views/challenges/challenge.twig ================================================ {% extends 'master.twig'%} {% block title %}{{ challenge.difficulty_name_upper }} Challenge: {{ challenge.name }} | EMKC{% endblock %} {% block css %} {{ parent() }} {% endblock %} {% block bundles %} {% endblock %} {% block content %}
{% endblock %} ================================================ FILE: platform/views/challenges/choose_language.twig ================================================ {% extends 'master.twig'%} {% block title %}Coding Challenges | EMKC{% endblock %} {% block content %} {% if challenge.difficulty == sails.local.constant.challenges.difficulty.easy %} {% set diff = 'easy' %} {% endif %} {% if challenge.difficulty == sails.local.constant.challenges.difficulty.medium %} {% set diff = 'medium' %} {% endif %} {% if challenge.difficulty == sails.local.constant.challenges.difficulty.hard %} {% set diff = 'hard' %} {% endif %}
{% if challenge.difficulty == sails.local.constant.challenges.difficulty.easy %}

Easy: {{ challenge.name }}

{% endif %} {% if challenge.difficulty == sails.local.constant.challenges.difficulty.medium %}

Medium: {{ challenge.name }}

{% endif %} {% if challenge.difficulty == sails.local.constant.challenges.difficulty.hard %}

Hard: {{ challenge.name }}

{% endif %}

How do you plan on crushing this challenge?

JavaScript

Node
{{ ('js' in solved) ? 'Solved' : 'Unsolved' }}

Python

{{ ('python' in solved) ? 'Solved' : 'Unsolved' }}

Go

{{ ('go' in solved) ? 'Solved' : 'Unsolved' }}

C

{{ ('c' in solved) ? 'Solved' : 'Unsolved' }}

Ruby

{{ ('ruby' in solved) ? 'Solved' : 'Unsolved' }}

C++

{{ ('cpp' in solved) ? 'Solved' : 'Unsolved' }}

C#

{{ ('cs' in solved) ? 'Solved' : 'Unsolved' }}

PHP

{{ ('php' in solved) ? 'Solved' : 'Unsolved' }}

Swift

{{ ('swift' in solved) ? 'Solved' : 'Unsolved' }}

Java

{{ ('java' in solved) ? 'Solved' : 'Unsolved' }}

Rust

{{ ('rust' in solved) ? 'Solved' : 'Unsolved' }}

Julia

{{ ('julia' in solved) ? 'Solved' : 'Unsolved' }}

Bash

{{ ('bash' in solved) ? 'Solved' : 'Unsolved' }}

Perl

{{ ('perl' in solved) ? 'Solved' : 'Unsolved' }}

Kotlin

{{ ('kotlin' in solved) ? 'Solved' : 'Unsolved' }}

Haskell

{{ ('haskell' in solved) ? 'Solved' : 'Unsolved' }}

Nim

{{ ('nim' in solved) ? 'Solved' : 'Unsolved' }}
{% endblock %} ================================================ FILE: platform/views/challenges/home.twig ================================================ {% extends 'master.twig'%} {% block title %}Coding Challenges | EMKC{% endblock %} {% block desc %}Test out your skills in various challenges using one of 17 available languages.{% endblock %} {% block content %}

Challenges

Welcome to Knowledge Center challenges, a place to test out your skills in one of 17 languages of your choosing on a number of different practical tests. Points are awarded based on difficulty. You can complete the challenge up to 17 times (one for each available language). New challenges are being added all the time.

{% endblock %} ================================================ FILE: platform/views/community/about.twig ================================================ {% extends 'master.twig'%} {% block title %}About Engineer Man Knowledge Center{% endblock %} {% block content %}

About Engineer Man Knowledge Center

The Engineer Man Knowledge Center is a project by Engineer Man and other collaborators designed to create a permanent knowledge resource for the people of Discord and the YouTube channel. The platform has drawn influence from the positive parts of Stack Exchange's Q&A and community systems as well as the discussion format of Reddit.

The need for a Knowledge Center came about when our Discord server was flooded with people, questions, resources, ideas, and discussion. It was not practical to continue operating in that way on a service that was not built for what we were using it for.

{% endblock %} ================================================ FILE: platform/views/community/home.twig ================================================ {% extends 'master.twig'%} {% block title %}Community Resources | EMKC{% endblock %} {% block content %}
Knowledge Center
Power System
{% endblock %} ================================================ FILE: platform/views/community/power.twig ================================================ {% extends 'master.twig'%} {% block title %}How To Gain Power | EMKC{% endblock %} {% block content %}

Power System

The power system is a system which measures a person's meaningful contributions to the Engineer Man Community as well as recognize people for their knowledge in various regards. With more power comes more recognition and privileges in the Knowledge Center, recognition on Discord, moderation abilities, secret functionality, and more. You can earn power by people recognizing your contributions, finishing challenges, and winning official Engineer Man contests.

Knowledge Community Ranks

Novice
40+
Hero
300+
Master
1,000+
Legend
5,000+

How Power Is Earned

Contests

Winner is defined as the shortest solution that was submitted the quickest. Placing top 3 also earns you the participation points. Participation points (50) will only be awarded once per contest.

Place #1 in a contest (overall)
+500
Place #2 in a contest (overall)
+200
Place #3 in a contest (overall)
+75
Place #1 in a contest (per language)
+50
Participate in a contest (submit a solution)
+50
Challenges

Points are awarded per language and per challenge.

Finish hard difficulty challenges
+50
Finish medium difficulty challenges
+30
Finish easy difficulty challenges
+10
{% endblock %} ================================================ FILE: platform/views/contests/contest.twig ================================================ {% extends 'master.twig'%} {% block title %}Coding Contest: {{ contest.name|e }} | EMKC{% endblock %} {% block content %}
{% endblock %} ================================================ FILE: platform/views/contests/home.twig ================================================ {% extends 'master.twig'%} {% block title %}Weekly Contests | EMKC{% endblock %} {% block desc %}Got what it takes to create the shortest possible solution for the weekly contest? Give it a shot!{% endblock %} {% block content %}

Contests

The Engineer Man Knowledge Center hosts contests weekly which are done in a Code Golf format. For those not familiar with Code Golf, it basically means that the winner of the contest is the person who can accomplish the given objective with the least amount of code, measured in bytes.

Supported languages are those which Piston supports. To request new languages, submit a request in #emkc-felix-piston on Discord. Our intent is to add proper golfing languages over time as well as a separate leaderboard for these languages.

Overview
  1. Contests start at 12:00pm CDT (5:00pm UTC) on Sundays and run for 3 days ending at 12:00pm CDT (5:00pm UTC) on Wednesdays.
  2. You can update your solution as many times as you want during the contest period. Submitting a solution that is shorter than your last submitted solution will result in the submitted time changed. This is important to understand because tiebreakers are resolved by the oldest solution.
  3. Points are awarded to the shortest solutions that meet the objective both overall and per language. If there are solutions that are the same length, the solution submitted the earliest will take precedent. Please see how to gain power for more information.
  4. Leading and trailing whitespace is automatically trimmed before calculating the number of bytes used.
  5. Inputs are provided as command line arguments (ARGV) and standard input (STDIN) with each input separated by a newline character, you may use either one.
Rules
  1. No sharing solutions or discussing approach during the contest period.
  2. Submitted solutions must pass automated code execution before they are recorded as a contest submission. This is done using the Piston engine.
  3. For those using Bash, you can use any of the GNU coreutils as well as sed and awk. You may not call into any of the other contest languages (julia, perl, python, etc.).
  4. Don't submit duplicate solutions for similar languages (e.g. c/c++, js/ts/deno, etc).
  5. Solutions which depend on RNG to pass are not allowed.

{% endblock %} ================================================ FILE: platform/views/home/fourohfour.twig ================================================ {% extends 'master.twig' %} {% block content %}
{% endblock %} ================================================ FILE: platform/views/home/home.twig ================================================ {% extends 'master.twig'%} {% block content %}

Top {{ users|length }} Engineers on Planet Earth

{% for user in users %} {% set color = '#000' %} {% if user.score >= 40 %} {% set color = '#79ACBF' %} {% endif %} {% if user.score >= 300 %} {% set color = '#7D9DC5' %} {% endif %} {% if user.score >= 1000 %} {% set color = '#ACB2E4' %} {% endif %} {% if user.score >= 5000 %} {% set color = '#D2ACE4' %} {% endif %} {% set max_score = users[0].score %}
{{ user.display_name|e }} {% if user.is_staff %} Staff {% endif %}
{{ user.score }}
{% endfor %}
{% endblock %} ================================================ FILE: platform/views/home/login.twig ================================================ {% extends 'master.twig'%} {% block content %} Discord {% endblock %} ================================================ FILE: platform/views/home/privacy.twig ================================================ {% extends 'master.twig'%} {% block title %}Privacy Policy | EMKC{% endblock %} {% block content %}

Privacy Policy

This privacy notice tells you about the information we collect from you when you use our website.

Who are we?

EMKC is operated by EngineerMan. You can contact us by email at em@engineerman.org.

We are not required to have a data protection officer, so any enquiries about our use of your personal data should be addressed to the contact details above.

How we use your information

Certain visitors to our websites choose to interact with EMKC in ways that require EMKC to gather personally-identifying information. The amount and type of information that EMKC gathers depends on the nature of the interaction. For example, when you log in to EMKC using Discord, Discord will transmit your email address. In this case, EMKC collects such information in order to fulfill the purpose of the visitor’s interaction with EMKC.

Like most website operators, EMKC collects non-personally-identifying information of the sort that web browsers and servers typically make available, such as the browser type, language preference, referring site, and the date and time of each visitor request. Our purpose in collecting non-personally identifying information is to better understand how our visitors use the website.

Your information is stored on our website and on our cloud servers, both of which are based within the United States.

We keep your user information for as long as you have a user account with us.

A visitor's IP address may be logged within our system, typically for debugging purposes, separate from our system application databases. The IP address may remain stored within our logs for up to 3 months.

Account deletion

You may decide to delete your account at any time. You can do so by sending an email to the contact information provided above.

Cookies

When you use our website to browse our content and view the information we make available, cookies are used by us to allow the website to function.

The cookies we use are strictly necessary for our website to function. EMKC visitors who do not wish to have cookies placed on their computers should set their browsers to refuse cookies before using our websites, with the drawback that certain features of our websites may not function properly without the aid of cookies.

Information Protection

EMKC takes all measures reasonably necessary to protect against the unauthorized access, use, alteration or destruction of potentially personally-identifying and personally-identifying information

Your rights as a data subject

You can ask us what information we hold about you, and you can ask us to correct it if it is inaccurate. If we have asked for your consent to process your personal data, you may withdraw that consent at any time.

To submit a request regarding your personal data, please use the contact information provided above in the Who Are We section of this policy.

This policy was last updated on February 25th 2019.

{% endblock %} ================================================ FILE: platform/views/master.twig ================================================ {% block title %}Engineer Man Knowledge Center{% endblock %} {% block css %} {% endblock %} {% block js %} {% endblock %}
{% if req.local.user_id %}
{{ req.local.user.score }}
{% else %} {% endif %}
{% if sails.twig.starts_with(req.path, '/admin') and req.local.user.is_staff %}
Staff Stuff: Users | Contests | Challenges | Piston
{% endif %} {% block content %}{% endblock %}
{% if not req.local.user_id %}
{% endif %} {% block bundles %}{% endblock %} ================================================ FILE: platform/views/merch/stickers.twig ================================================ {% extends 'master.twig'%} {% block content %}

Batch Notes:

  • First batch of stickers is 300 in total and are being sold at cost (possibly even a loss). If you're able to see this page, stickers are still available.
  • If you are already an Engineer Man supporter, have donated during stream, have Nitro boosted our Discord server, have been granted the role of Discord Hero, or attained the level of EMKC Master, and have not yet received a sticker, please message EngineerMan#0001 on Discord for a coupon code good for two stickers.

Order Notes:

  • Make sure your address is accurate and exactly as it should appear on an envelope.
  • Checkout button will appear once the form is filled out.
  • Stickers are shipped from Florida, USA. Please allow 3 days for processing, 2-3 days for domestic delivery, 7-14 days for international delivery.
  • After order submission, you'll receive an Order ID. Please record this in case you need to reference this order.

Privacy Notes:

  • No payment information is received or stored by EMKC. Payment is handled entirely by PayPal.
  • Name and address is only stored until your stickers have shipped and then it is deleted.
  • Your email is used only to contact you if for some reason there is a problem processing your order.

{% endblock %} ================================================ FILE: platform/views/profiles/view.twig ================================================ {% extends 'master.twig'%} {% block title %}{{ user.display_name|e }} - EMKC Member{% endblock %} {% block content %}

{{ user.display_name }}

{{ user.score }}


Member Since
{{ user.created_at|date('m/d/Y') }}

Challenges Solved
{{ stat_challenges }}

Contests Entered
{{ stat_contests }}

Awards

{% for award in awards %}
{{ award.count }}
{% else %} This user has no awards yet. {% endif %}

Recent Solved Challenges

{% for challenge in challenges %} {% else %} This user has not solved any challenges. {% endif %}
{% endblock %} ================================================ FILE: platform/views/scripts/home.twig ================================================ {% extends 'master.twig'%} {% block content %}

CLI Script Database

{% for script in scripts %} {% endfor %}
View Title Created
View {{ script.title }} {{ script.created_at|date('m/d/Y g:i a') }}
{% endblock %} ================================================ FILE: platform/views/scripts/view.twig ================================================ {% extends 'master.twig'%} {% block bundles %} {% endblock %} {% block content %}

{{ script.title }}

bash <(curl -sSf {{ sails.config.base_url }}/exec/{{ script.cli_script_id }})
{% endblock %} ================================================ FILE: platform/views/snippets/edit.twig ================================================ {% extends 'master.twig' %} {% block css %} {{ parent() }} {% endblock %} {% block bundles %} {% endblock %} {% block content %}
{% endblock %} ================================================ FILE: platform/views/snippets/mine.twig ================================================ {% extends 'master.twig'%} {% block content %}

My Snippets

{% if snippets.length > 0 %} {% for snippet in snippets %} {% endfor %}
Language Age Preview
    {{ snippet.language }} {{ snippet.time_ago }} {{ snippet.snip|slice(0, 200)|e }}
{% else %} You have not created any snippets. {% endif %}
{% endblock %} ================================================ FILE: platform/webpack.config.js ================================================ const path = require('path'); const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); module.exports = { entry: { main: './resources/main.js', monaco: './resources/monaco.js' }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader' } }, { test: /\.less$/, exclude: /node_modules/, use: [ { loader: MiniCSSExtractPlugin.loader, options: { publicPath: (resourcePath, context) => { return ( path.relative( path.dirname(resourcePath), context ) + '/' ); } } }, { loader: 'css-loader' }, { loader: 'less-loader' } ] }, { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader' } ] }, { test: /\.ttf$/, use: [ { loader: 'file-loader' } ] } ] }, resolve: { extensions: ['.js', '.jsx', '.json'], modules: ['node_modules', path.resolve(__dirname, 'resources/')] }, output: { path: path.resolve(__dirname, 'public/lib/webpack'), publicPath: '/lib/webpack/', filename: '[name].bundle.js' }, optimization: { splitChunks: { cacheGroups: { react: { test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, name: 'react', chunks: 'initial' } } }, sideEffects: false }, plugins: [ new MiniCSSExtractPlugin({ filename: '[name].bundle.css' }), new MonacoWebpackPlugin() ] }; ================================================ FILE: readme.md ================================================ ## Engineer Man Knowledge Center (emkc) This is the official repo and project for the Engineer Man Knowledge Center. The official deployment of this project is located at https://emkc.org. Be sure to familiarize yourself with the contribution guidelines and project license if you plan to use this software. #### Install Instructions Docker is the preferred (and only supported) way to work with EMKC in development. EMKC is known to work on all Linux/macOS machines and Windows machines running either WSL or natively with Windows 10 Pro. - `git clone https://github.com/engineer-man/emkc` - `cd emkc` - `./emkc init` - `./emkc start` - `./emkc rmig migrate` - `./emkc stop` when done. - `./emkc` to view a list of commands. Once started, you can access the local version of the site at http://127.0.0.1:2005 (localhost:2005 for WSL). > **Note:** when using WSL, it is recommended to use the linux filesystem for better performance and fewer errors; however if you intend to use the windows filesystem, make sure to mount your windows volumes with metadata options since the MySQL Docker Container needs permissions to modify files in the volume. You can configure that automatically on WSL startup by adding `options = "metadata"` to /etc/wsl.conf under the [automount] > section (check https://devblogs.microsoft.com/commandline/automatically-configuring-wsl/) #### Local Config There are two files needed to configure the application. Make sure to modify these with your own values. If these files are not present, navigate to the project root and run `./emkc init`. - App: `platform/config/local.js` - DB Migrations: `platform/migrations/config.json` #### Contribution Guidelines All contributions are reviewed to make sure they work, fit well with the design, and fit well with the established code. BDFL is [realtux](https://github.com/realtux) who will do a final review and merge to master and deploy. - Review the issues on GitHub and grab whichever you feel most comfortable doing - Place code on a branch other than master/develop (Fork for non-org developers) - Follow the style that is generally present with the project (details below) - Use established tech in place (Bootstrap 4, React, etc.) - Test to make sure everything works #### General Code Guidelines - Prefer spaces over tabs - 120 character max line length for source - PascalCase for classes, snake_case for everything else - Use ES9 to the fullest extent possible - Single quotes only - In general just make code look like everything else #### License Engineer Man Knowledge Center is licensed under the permissive MIT license. License details can be found in the `license` file in the root of the project. ================================================ FILE: var/502/502.html ================================================ Engineer Man Knowledge Center

Deploying new cool features.
Refresh in a sec.
================================================ FILE: var/docker/clean ================================================ rm -rf ./logs/* rm -rf ./mysql/* rm -rf ./redis/* ================================================ FILE: var/docker/config/mysqld.cnf ================================================ [mysqld] symbolic-links=0 innodb_file_per_table=1 sql_mode = "" [server] #general_log=1 #general_log_file=/opt/emkc/var/docker/logs/sql.log ================================================ FILE: var/docker/init/db.sql ================================================ create database if not exists emkc; ================================================ FILE: var/docker/logs/.gitkeep ================================================ ================================================ FILE: var/docker/mysql/.gitkeep ================================================ ================================================ FILE: var/docker/redis/.gitkeep ================================================ ================================================ FILE: var/text/a.txt ================================================ ================================================ FILE: var/tmp/.gitkeep ================================================ ================================================ FILE: var/tmp/scripts.sql ================================================ insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (21,1,1,1,'Disabling SELinux on CentOS 6','nano /etc/selinux/config\r\n# change SELINUX=enforcing to SELINUX=disabled\r\necho 0 > /selinux/enforce',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (22,1,1,1,'Get Uptime on Linux','uptime',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (3,1,1,1,'Install Git 2.6.2 on CentOS 6/7','sudo yum groupinstall -y \'development tools\'\r\nsudo yum install -y wget curl-devel expat-devel gettext-devel openssl-devel perl-devel zlib-devel\r\nwget https://cmd.bri.io/static/deps/3/git-2.6.2.tar.gz\r\ntar -zxf git-2.6.2.tar.gz\r\ncd git-2.6.2\r\nmake configure\r\n./configure --prefix=/usr\r\nmake all\r\nsudo make install',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (4,1,1,1,'Install Ruby 2.1.0 on CentOS 6/7','sudo yum groupinstall -y \'development tools\'\r\ngpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3\r\ncurl -L get.rvm.io | bash -s stable\r\nsource /etc/profile.d/rvm.sh\r\nrvm reload\r\nrvm install 2.1.0',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (5,1,1,1,'Burn DVD from the command line','wodim -eject -tao speed=2 dev=/dev/sr0 -v -data isoname.iso',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (6,1,1,1,'Generate Private Key and CSR on CentOS 6/7','sudo yum install -y openssl\r\nopenssl genrsa -out server.key 2048\r\nopenssl req -new -sha256 -key server.key -out server.csr',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (7,1,1,1,'Resize Google Compute Engine VM Boot Disk','fdisk -l\r\n# take note of the starting sector\r\n\r\nfdisk /dev/sda\r\n# hit d to delete the partition\r\n# hit n for new partition\r\n# hit p for primary\r\n# hit 1 for partition number\r\n# type the starting sector and hit enter\r\n# hit enter to accept the end sector\r\n# hit w to write the partition table\r\n\r\nresize2fs /dev/sda1',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (8,1,1,1,'Create combined SSL chain file','# order matters\r\ncat yourcert.crt intermediate.crt root.crt yourkey.key > combined.pem',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (9,1,1,1,'Create and use a LUKS Volume','# create luks\r\ndd if=/dev/urandom of=/home/brian/file bs=1M count=512\r\nsudo cryptsetup -y luksFormat /home/brian/file\r\nsudo cryptsetup luksOpen /home/brian/file volume_name\r\nsudo mkfs.ext4 /dev/mapper/volume_name\r\n\r\n# mount\r\nsudo cryptsetup luksOpen /home/brian/file volume_name\r\nsudo mount /dev/mapper/volume_name /mount/point\r\n\r\n# close\r\nsudo umount /dev/mapper/volume_name\r\nsudo cryptsetup luksClose volume_name',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (10,1,1,1,'Install Python 2.7.3 on CentOS 6/7','sudo yum groupinstall -y \'development tools\'\r\nwget http://python.org/ftp/python/2.7.6/Python-2.7.6.tar.xz\r\nxz -d Python-2.7.6.tar.xz\r\ntar -xvf Python-2.7.6.tar\r\nrm -f Python-2.7.6.tar\r\ncd Python-2.7.6\r\n./configure\r\nmake && make altinstall\r\ncd ..',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (11,1,1,1,'Install Latest bmig on CentOS 6/7','sudo yum install -y gcc mysql-devel json-c-devel\r\ngit clone https://github.com/ebrian/bmig\r\ncd bmig\r\nmake\r\nsudo make install',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (12,1,1,1,'Install Latest bmig on Ubuntu','sudo apt-get install build-essential pkg-config git gcc libmysqlclient-dev libjson0-dev\r\ngit clone https://github.com/ebrian/bmig\r\ncd bmig\r\nmake\r\nsudo make install',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (13,1,1,1,'Install GCC 4.8.x on CentOS 6/7','wget http://people.centos.org/tru/devtools-2/devtools-2.repo -O /etc/yum.repos.d/devtools-2.repo\r\nyum install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils\r\nscl enable devtoolset-2 bash',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (14,1,1,1,'Install Node 4.2.1 on CentOS 6/7','wget https://nodejs.org/dist/v4.2.1/node-v4.2.1-linux-x64.tar.gz\r\ntar -xzzvf node-v4.2.1-linux-x64.tar.gz\r\nrm -f node-v4.2.1-linux-x64.tar.gz\r\nmv node-v4.2.1-linux-x64 node4',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (15,1,1,1,'Install MySQL 5.5 on CentOS 6','rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm\r\nyum install -y mysql.`uname -i` yum-plugin-replace\r\nyum replace mysql --replace-with mysql55w\r\nyum install -y mysql55w mysql55w-server',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (16,1,1,1,'MySQL Table to CSV','select *\r\n from table\r\n into outfile \'/tmp/file.csv\'\r\n fields terminated by \',\' optionally enclosed by \'\"\'\r\n lines terminated by \'\\n\';',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (17,1,1,1,'Install Node 4.2.1 on Raspberry PI 2 B+','wget https://nodejs.org/dist/v4.2.1/node-v4.2.1-linux-armv6l.tar.gz\r\ntar -xzzvf node-v4.2.1-linux-armv6l.tar.gz\r\nrm -f node-v4.2.1-linux-armv6l.tar.gz\r\nmv node-v4.2.1-linux-armv6l node4\r\nln -s /root/node4/bin/node /usr/bin/node\r\nln -s /root/node4/bin/npm /usr/bin/npm',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (19,1,1,1,'TAR and GZip to GPG on the fly','# encrypt\r\nexport GPG_TTY=$(tty)\r\ntar zcf - whatever_folder | gpg --symmetric --cipher-algo aes256 -o whatever.gpg\r\n\r\n# decrypt\r\nexport GPG_TTY=$(tty)\r\ngpg -d whatever.gpg | tar xzf -',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (20,1,1,1,'Compress, Encrypt with GPG, and Split','# construct\r\nexport GPG_TTY=$(tty)\r\ntoday=$(date +%Y%m%d)\r\ntar zcf - folder1 folder2 folder3 \\\r\n | gpg --symmetric --cipher-algo aes256 -o - \\\r\n | split -b 2G -d -a 3 - backup.$today.gpg.\r\n\r\n# deconstruct\r\nexport GPG_TTY=$(tty)\r\ncat backup.20160607.gpg.* \\\r\n | gpg -d -o - \\\r\n | tar xzf -',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (23,1,1,1,'Install Node 6 on Centos 6/7','wget https://nodejs.org/dist/v6.3.0/node-v6.3.0-linux-x64.tar.gz\r\ntar -xzzvf node-v6.3.0-linux-x64.tar.gz\r\nrm -f node-v6.3.0-linux-x64.tar.gz\r\nmv node-v6.3.0-linux-x64 node6',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (24,1,1,1,'Wipe Drive Linux','# yes this is secure, stop being paranoid\r\n# https://digital-forensics.sans.org/blog/2009/01/15/overwriting-hard-drive-data/\r\n\r\ndd if=/dev/zero of=/dev/your_device bs=1M',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (26,1,1,1,'Create self-signed SSL Certificate','openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days XXX -nodes',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (27,1,1,1,'Bulk Crop Images','for f in *.jpg; do\r\n convert $f -trim $f\r\ndone',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (28,1,1,1,'CentOS 6 TTY Auto Login','# open config\r\nnano /etc/init/tty.conf\r\n\r\n# replace this\r\nexec /sbin/mingetty $TTY\r\n\r\n# with this (replace username)\r\nexec /sbin/mingetty --autologin username $TTY',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (29,1,1,1,'CentOS 6 No TTY Screensaver','# open config\r\nnano /etc/rc.d/rc.local\r\n\r\n# add this line at the bottom\r\nsetterm -blank 0',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (30,1,1,1,'CentOS 6 SELinux Allow FTP Directory Change','setsebool -P ftp_home_dir=1',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (31,1,1,1,'CentOS Google Cloud SDK Working With Python 2.7','# get pip2.7\r\nwget https://bootstrap.pypa.io/get-pip.py\r\npython2.7 get-pip.py\r\n\r\n# install the gcloud module\r\npip2.7 install google_compute_engine\r\n\r\n# add to .bashrc\r\nexport CLOUDSDK_PYTHON=/usr/local/bin/python2.7',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (33,1,1,1,'Convert Bare Git Repo to Normal Repo','mkdir .git\r\nmv branches/ config description HEAD hooks/ info/ objects/ refs/ .git\r\ngit config --local --bool core.bare false\r\ngit checkout master\r\ngit reset --hard',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (34,1,1,1,'Linux Primitive UDP Hole Punching','# from machine1 (1.2.3.4)\r\n# punch a hole in the firewall\r\nhping2 -c 1 -2 -s 14141 -p 53 5.6.7.8\r\n\r\n# from machine1 (firewalled)\r\n# listen for connections on 1.2.3.4:14141\r\nnc -u -l -p 14141\r\n\r\n# from machine2 (5.6.7.8)\r\n# send a message to 1.2.3.4:14141 from 5.6.7.8:53\r\necho \'test\' | nc -p 53 -u 1.2.3.4 14141',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (35,1,1,1,'Install Python 3.4.5 on CentOS 6/7','sudo yum groupinstall -y \'development tools\'\r\nwget http://python.org/ftp/python/3.4.5/Python-3.4.5.tar.xz\r\nxz -d Python-3.4.5.tar.xz\r\ntar -xvf Python-3.4.5.tar\r\nrm -f Python-3.4.5.tar\r\ncd Python-3.4.5\r\n./configure\r\nmake && make altinstall\r\ncd ..',now()); insert into cli_scripts (cli_script_id, user_id, is_public, is_safe, title, content, created_at) values (36,1,1,1,'Install Latest Docker & Compose on CentOS 6/7','# Docker\r\nsudo yum install -y yum-utils device-mapper-persistent-data lvm2\r\nsudo yum-config-manager -y --add-repo https://download.docker.com/linux/centos/docker-ce.repo\r\nsudo yum install -y docker-ce\r\nsudo usermod -aG docker $(whoami)\r\nsudo systemctl enable docker.service\r\nsudo systemctl start docker.service\r\n\r\n# Docker Compose\r\nsudo yum install -y epel-release\r\nsudo yum install -y python-pip\r\nsudo pip install docker-compose\r\nsudo yum upgrade -y python*',now()); ================================================ FILE: var/tmp/stats.sql ================================================ select user, count(*) as messages from discord_chat_messages where created_at > '2021-07-29 00:00:00' and channel not in ( 'team-room', 'hero-room', 'oof-topic', 'command-center', 'moderator-report', 'gaming', 'music', 'bot-playground' ) and discord_id in ( '252862670842232832', '431464792075665418', '98488345952256000', '460172222489952266', '473160828502409217', '274618567977205761', '187677490452496394', '449274804651032577', '342099904056786945', '186436642356068352', '245697230982479872', '381632413010231309', '173679469872152576' ) group by discord_id order by messages desc; select user, count(*) as messages from discord_chat_messages where created_at > '2021-07-29 00:00:00' and channel not in ( 'team-room', 'hero-room', 'oof-topic', 'command-center', 'moderator-report', 'gaming', 'music', 'bot-playground' ) and discord_id in ( '319509382889209866', '681375864042160128', '222005750598205440', '243412893234757632', '532835388448833556', '271357207180738563', '406634590325964801', '276380118761340928', '563228793704022038', '496790880548814858', '158250066417549312', '266140088138858496', '710952300209766410', '197774061315686400', '536269399783505950' ) group by discord_id order by messages desc; ================================================ FILE: var/tmp/vids.sql ================================================ insert into video_requests values (default, 1, 'General - Design Patterns', now()); insert into video_requests values (default, 1, 'Python - Twitter Bot (posts photos)', now()); insert into video_requests values (default, 1, 'Python - GUI basics', now()); insert into video_requests values (default, 1, 'General - Reverse Engineering', now()); insert into video_requests values (default, 1, 'Python - Image Recognition', now()); insert into video_requests values (default, 1, 'Challenge - Space Invaders game challenge', now()); insert into video_requests values (default, 1, 'Shell - Makefiles', now()); insert into video_requests values (default, 1, 'General - Hashing vs Encryption', now()); insert into video_requests values (default, 1, 'Python - pandas', now()); insert into video_requests values (default, 1, 'General - Google Sheets API', now()); insert into video_requests values (default, 1, 'Shell - awk basics', now()); insert into video_requests values (default, 1, 'General - Staff Hangman Bots (Overview)', now()); insert into video_requests values (default, 1, 'Python - Implementing Regex into code', now()); insert into video_requests values (default, 1, 'General - Bitwise operators', now()); insert into video_requests values (default, 1, 'Python - Object Oriented Programming', now()); insert into video_requests values (default, 1, 'Python - AES Implementation', now()); insert into video_requests values (default, 1, 'Python - JSON and XML', now()); insert into video_requests values (default, 1, 'node.js - Await/Async', now()); insert into video_requests values (default, 1, 'Python - Simple Rest API', now()); insert into video_requests values (default, 1, 'Python - Intermediate Series', now()); insert into video_requests values (default, 1, 'C - Combining and compiling multiple C source files together', now()); insert into video_requests values (default, 1, 'C - Signal handling', now()); insert into video_requests values (default, 1, 'Shell - sed basics', now()); insert into video_requests values (default, 1, 'Shell - grep basics', now()); insert into video_requests values (default, 1, 'Python - Map, Filter, Reduce', now()); insert into video_requests values (default, 1, 'Python - How to use sqlite 3', now()); insert into video_requests values (default, 1, 'Linux - Beginner Commands', now()); insert into video_requests values (default, 1, 'Any - Discord Webhooks', now()); insert into video_requests values (default, 1, 'General - REST API', now()); insert into video_requests values (default, 1, 'Career - Interview Questions', now()); insert into video_requests values (default, 1, 'General - XML', now()); insert into video_requests values (default, 1, 'General - Bash', now()); insert into video_requests values (default, 1, 'Python - Sound Analyzer', now());