Full Code of engineer-man/emkc for AI

develop 4b7e6c3baba6 cached
246 files
491.3 KB
120.5k tokens
272 symbols
1 requests
Download .txt
Showing preview only (553K chars total). Download the full file or copy to clipboard to get everything.
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 + ' <no-reply@emkc.org>';

        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 = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

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

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <span class="badge badge-info">value1</span><br />
            The string to reverse
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Cases</h4>

        <div class="test_case">
            <div class="f700">Simple string</div>
            <div class="wrap"><span class="badge badge-info">value1</span> cat</div>
            <div class="wrap"><span class="badge badge-dark">output</span> tac</div>
        </div>
        <div class="test_case">
            <div class="f700">Complex string</div>
            <div class="wrap"><span class="badge badge-info">value1</span> sd#$)(&*09&M0</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 0M&90*&()$#ds</div>
        </div>
    </div>
</div>
' where folder = '1_reverse_string';
update challenges set html = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

        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.
    </div>

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <span class="badge badge-info">value1</span><br />
            String of numbers
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Cases</h4>

        <div class="test_case">
            <div class="f700">String of numbers</div>
            <div class="wrap"><span class="badge badge-info">value1</span> 08989082882348823838</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 8</div>
        </div>
    </div>
</div>
' where folder = '2_number_frequency';
update challenges set html = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

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

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <span class="badge badge-info">value1</span><br />
            The list to add
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Cases</h4>

        <div class="test_case">
            <div class="f700">Short list</div>
            <div class="wrap"><span class="badge badge-info">value1</span> 2,5,1</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 8</div>
        </div>
        <div class="test_case">
            <div class="f700">Long list</div>
            <div class="wrap"><span class="badge badge-info">value1</span> 3,9,10,5,2,7,9,2</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 47</div>
        </div>
    </div>
</div>
' where folder = '3_list_sum';
update challenges set html = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

        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.
    </div>

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <span class="badge badge-info">value1</span><br />
            A string of invalid JSON
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Cases</h4>

        <div class="test_case">
            <div class="f700">Single Problem</div>
            <div class="wrap"><span class="badge badge-info">value1</span> {"name":"em"</div>
            <div class="wrap"><span class="badge badge-dark">output</span> {"name":"em"}</div>
        </div>
        <div class="test_case">
            <div class="f700">Multiple Problems</div>
            <div class="wrap"><span class="badge badge-info">value1</span> "name":"em</div>
            <div class="wrap"><span class="badge badge-dark">output</span> {"name":"em"}</div>
        </div>
    </div>
</div>
' where folder = '4_invalid_json';
update challenges set html = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

        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.
    </div>

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <span class="badge badge-info">value1</span><br />
            Three lowercase letters
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Case</h4>

        <div class="test_case">
            <div class="f700">Letter</div>
            <div class="wrap"><span class="badge badge-info">value1</span> abc</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 011000010110001001100011</div>
        </div>
    </div>
</div>
' where folder = '5_binary_convert';
update challenges set html = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

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

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <p>
                <span class="badge badge-info">value1</span><br />
                The starting number
            </p>
            <p>
                <span class="badge badge-info">value2</span><br />
                n number to calculate after value1
            </p>
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Cases</h4>

        <div class="test_case">
            <div class="f700">Small Number</div>
            <div class="wrap"><span class="badge badge-info">value1</span> 5</div>
            <div class="wrap"><span class="badge badge-info">value2</span> 2</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 8,13</div>
        </div>
        <div class="test_case">
            <div class="f700">Large Numbers</div>
            <div class="wrap"><span class="badge badge-info">value1</span> 34</div>
            <div class="wrap"><span class="badge badge-info">value2</span> 7</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 55,89,144,233,377,610,987</div>
        </div>
    </div>
</div>
' where folder = '6_fibonacci_sequence';
update challenges set html = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

        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.
    </div>

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <span class="badge badge-info">value1</span><br />
            Two strings separated by a comma
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Case</h4>

        <div class="test_case">
            <div class="f700">Permutation</div>
            <div class="wrap"><span class="badge badge-info">value1</span> brian,airbn</div>
            <div class="wrap"><span class="badge badge-dark">output</span> Yes</div>
        </div>
    </div>
</div>
' where folder = '7_check_permutation';
update challenges set html = '<div class="em_challenge_abstract">
    <div class="section">
        <h4 class="f300">Instructions</h4>

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

    <div class="section">
        <h4 class="f300">Inputs</h4>

        <div class="input">
            <span class="badge badge-info">value1</span><br />
            The list to sort
        </div>
    </div>

    <div class="section">
        <h4 class="f300">Sample Test Cases</h4>

        <div class="test_case">
            <div class="f700">Short list</div>
            <div class="wrap"><span class="badge badge-info">value1</span> 3,4,-9</div>
            <div class="wrap"><span class="badge badge-dark">output</span> 4,3,-9</div>
        </div>
        <div class="test_case">
            <div class="f700">Long list</div>
            <div class="wrap"><span class="badge badge-info">value1</span> 3,9,10,5,2,7,9,2</div>
            <div class="wrap"><span class="badge badge-dark">output</sp
Download .txt
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
Download .txt
SYMBOL INDEX (272 symbols across 85 files)

FILE: platform/api/controllers/AuthController.js
  method discord (line 5) | discord(req, res) {
  method discord_cb (line 24) | async discord_cb(req, res) {

FILE: platform/api/controllers/ChallengesController.js
  method home (line 5) | async home(req, res) {
  method choose_language (line 43) | async choose_language(req, res) {
  method challenge (line 73) | async challenge(req, res) {
  method execute (line 326) | async execute(req, res) {
  method view_other (line 401) | async view_other(req, res) {

FILE: platform/api/controllers/CommunityController.js
  method home (line 2) | home(req, res) {
  method about (line 6) | about(req, res) {
  method power (line 10) | power(req, res) {

FILE: platform/api/controllers/ContestsController.js
  method home (line 4) | async home(req, res) {
  method contest (line 86) | async contest(req, res) {
  method submit (line 193) | async submit(req, res) {
  method disallowed_languages (line 364) | async disallowed_languages(req, res) {

FILE: platform/api/controllers/HomeController.js
  method home (line 2) | async home(req, res) {
  method privacy (line 13) | privacy(req, res) {
  method login (line 17) | login() {
  method logout_as (line 21) | async logout_as(req, res) {
  method logout (line 33) | logout(req, res) {
  method fourohfour (line 38) | fourohfour(req, res) {

FILE: platform/api/controllers/MerchController.js
  method stickers (line 4) | stickers(req, res) {
  method order_stickers (line 15) | async order_stickers(req, res) {
  method check_code (line 43) | check_code(req, res) {

FILE: platform/api/controllers/ProfilesController.js
  method view (line 2) | async view(req, res) {

FILE: platform/api/controllers/ScriptsController.js
  method home (line 2) | async home(req, res) {
  method view (line 14) | async view(req, res) {
  method exec (line 28) | async exec(req, res) {

FILE: platform/api/controllers/SnippetsController.js
  method view (line 2) | async view(req, res) {
  method mine (line 38) | async mine(req, res) {
  method create (line 51) | async create(req, res) {
  method delete (line 86) | async delete(req, res) {
  method edit (line 105) | async edit(req, res) {

FILE: platform/api/controllers/TagsController.js
  method search (line 2) | async search(req, res) {

FILE: platform/api/controllers/admin/ChallengesController.js
  method view_all (line 35) | async view_all(req, res) {
  method create (line 45) | async create(req, res) {
  method update (line 96) | async update(req, res) {

FILE: platform/api/controllers/admin/ContestsController.js
  method view_all (line 4) | async view_all(req, res) {
  method create (line 14) | async create(req, res) {
  method update (line 65) | async update(req, res) {
  method delete_submission (line 108) | async delete_submission(req, res) {
  method validate_submissions (line 126) | async validate_submissions(req, res) {

FILE: platform/api/controllers/admin/DashboardController.js
  method dashboard (line 2) | async dashboard(req, res) {

FILE: platform/api/controllers/admin/PistonController.js
  method view_all (line 2) | async view_all(req, res) {
  method packages (line 8) | async packages(req, res) {
  method install (line 14) | async install(req, res) {
  method uninstall (line 28) | async uninstall(req, res) {

FILE: platform/api/controllers/admin/UsersController.js
  method view_all (line 2) | async view_all(req, res) {
  method login_as (line 18) | async login_as(req, res) {

FILE: platform/api/controllers/api/internal/ChatsController.js
  method last (line 5) | async last(req, res) {
  method create (line 22) | async create(req, res) {

FILE: platform/api/controllers/api/internal/PistonController.js
  method log (line 2) | async log(req, res) {

FILE: platform/api/controllers/api/v1/PistonController.js
  method versions (line 5) | async versions(req, res) {
  method execute (line 26) | async execute(req, res) {

FILE: platform/api/controllers/api/v1/UsersController.js
  method read_all (line 2) | async read_all(req, res) {
  method read (line 25) | async read(req, res) {

FILE: platform/api/controllers/api/v1/stats/DiscordController.js
  method messages (line 4) | async messages(req, res) {
  method channels (line 78) | async channels(req, res) {

FILE: platform/api/controllers/api/v1/stats/PistonController.js
  method usage (line 4) | async usage(req, res) {

FILE: platform/api/controllers/api/v2/PistonController.js
  method runtimes (line 5) | async runtimes(req, res) {
  method execute (line 18) | async execute(req, res) {

FILE: platform/api/services/api.js
  method handle_err (line 2) | handle_err(res, err) {

FILE: platform/api/services/constant.js
  method set_dynamic (line 92) | set_dynamic() {

FILE: platform/api/services/contests.js
  method get_cases (line 2) | get_cases(contest, redact = false) {
  method validate_submission (line 54) | async validate_submission(test_cases, solution, language, version) {

FILE: platform/api/services/discord.js
  method api (line 4) | async api(method, url, body = null) {

FILE: platform/api/services/dispenserd.js
  method schedule (line 13) | schedule(job, options) {

FILE: platform/api/services/error.js
  method log (line 4) | log(err, msg) {

FILE: platform/api/services/mailer.js
  method send (line 9) | send(to, subject, content, template, variables) {

FILE: platform/api/services/piston.js
  class PistonError (line 9) | class PistonError extends Error {
    method constructor (line 10) | constructor(message, status_code) {
  method runtimes (line 32) | async runtimes() {
  method packages (line 38) | async packages() {
  method install (line 44) | async install(language, version) {
  method uninstall (line 52) | async uninstall(language, version) {
  method execute (line 60) | async execute(

FILE: platform/api/services/test_cases.js
  method get_inputs_and_outputs (line 2) | get_inputs_and_outputs(test_object) {
  method are_valid (line 10) | are_valid(test_object) {

FILE: platform/api/services/twig.js
  method starts_with (line 14) | starts_with(string, path) {

FILE: platform/api/services/util.js
  method now (line 5) | now() {
  method slugify (line 9) | slugify(string) {
  method time_diff (line 19) | time_diff(start_date, end_date) {
  method time_ago (line 81) | time_ago(the_time) {
  method bury_upload (line 88) | bury_upload(file) {

FILE: platform/api/services/views.js
  method render (line 4) | async render(template, data) {

FILE: platform/config/http.js
  method test_json (line 20) | test_json(err, req, res, next) {
  method bodyParser (line 31) | bodyParser() {

FILE: platform/console/cron.js
  method calculate_score (line 10) | async calculate_score() {
  method process_awards (line 114) | async process_awards() {
  method update_staff (line 222) | async update_staff() {
  method repair_roles (line 274) | async repair_roles() {
  method contest_status (line 328) | async contest_status() {

FILE: platform/console/util.js
  method ingest_chats (line 8) | ingest_chats() {

FILE: platform/migrations/migrations/20180320123747-initial.sql
  type users (line 2) | create table users (
  type questions (line 20) | create table questions (
  type snippets (line 35) | create table snippets (
  type comments (line 47) | create table comments (
  type question_votes (line 67) | create table question_votes (
  type comment_votes (line 78) | create table comment_votes (
  type tags (line 89) | create table tags (

FILE: platform/migrations/migrations/20180903013450-question-tags.sql
  type question_tags (line 2) | create table question_tags (

FILE: platform/migrations/migrations/20180905220531-notification-table.sql
  type notifications (line 2) | create table notifications (

FILE: platform/migrations/migrations/20180915035412-code-rooms.sql
  type code_rooms (line 2) | create table code_rooms (

FILE: platform/migrations/migrations/20180930153901-video-requests.sql
  type video_requests (line 2) | create table video_requests (
  type video_request_votes (line 11) | create table video_request_votes (

FILE: platform/migrations/migrations/20181005005500-challenges-tables.sql
  type challenges (line 2) | create table challenges (
  type user_challenges (line 16) | create table user_challenges (

FILE: platform/migrations/migrations/20181021204739-chats-table.sql
  type discord_chat_messages (line 2) | create table discord_chat_messages (

FILE: platform/migrations/migrations/20190624224428-script-town.sql
  type cli_scripts (line 2) | create table cli_scripts (

FILE: platform/migrations/migrations/20191023224428-stickers.sql
  type sticker_orders (line 2) | create table sticker_orders (

FILE: platform/migrations/migrations/20200711133430-piston-stats.sql
  type piston_runs (line 2) | create table piston_runs (

FILE: platform/migrations/migrations/20200830224428-contests-tables.sql
  type contests (line 2) | create table contests (
  type contest_submissions (line 19) | create table contest_submissions (

FILE: platform/migrations/migrations/20200918012206-cleanup-old-tables.sql
  type `code_rooms` (line 13) | CREATE TABLE `code_rooms` (
  type `comment_votes` (line 25) | CREATE TABLE `comment_votes` (
  type `comments` (line 36) | CREATE TABLE `comments` (
  type `notifications` (line 56) | CREATE TABLE `notifications` (
  type `question_tags` (line 71) | CREATE TABLE `question_tags` (
  type `question_votes` (line 80) | CREATE TABLE `question_votes` (
  type `questions` (line 91) | CREATE TABLE `questions` (
  type `video_request_votes` (line 107) | CREATE TABLE `video_request_votes` (
  type `video_requests` (line 116) | CREATE TABLE `video_requests` (

FILE: platform/migrations/migrations/20200918012216-award-table.sql
  type awards (line 2) | create table awards (

FILE: platform/migrations/migrations/20210117161957-create-tests-table.sql
  type challenge_tests (line 2) | create table challenge_tests (

FILE: platform/models/awards.js
  class awards (line 4) | class awards extends Sequelize.Model {}
  method get (line 23) | get() {
  method beforeCreate (line 46) | beforeCreate(instance) {

FILE: platform/models/challenge_tests.js
  class challenge_tests (line 4) | class challenge_tests extends Sequelize.Model {}

FILE: platform/models/challenges.js
  class challenges (line 4) | class challenges extends Sequelize.Model {}
  method get (line 23) | get() {
  method get (line 35) | get() {

FILE: platform/models/cli_scripts.js
  class cli_scripts (line 4) | class cli_scripts extends Sequelize.Model {}
  method get (line 23) | get() {
  method get (line 34) | get() {
  method beforeCreate (line 44) | beforeCreate(instance) {

FILE: platform/models/contest_submissions.js
  class contest_submissions (line 4) | class contest_submissions extends Sequelize.Model {}
  method beforeCreate (line 31) | beforeCreate(instance) {

FILE: platform/models/contests.js
  class contests (line 5) | class contests extends Sequelize.Model {}
  method get (line 26) | get() {
  method get (line 35) | get() {
  method get (line 46) | get() {
  method get (line 52) | get() {
  method beforeCreate (line 126) | beforeCreate(instance) {

FILE: platform/models/discord_chat_messages.js
  class discord_chat_messages (line 4) | class discord_chat_messages extends Sequelize.Model {}
  method beforeCreate (line 25) | beforeCreate(instance) {

FILE: platform/models/piston_runs.js
  class piston_runs (line 4) | class piston_runs extends Sequelize.Model {}
  method beforeCreate (line 26) | beforeCreate(instance) {

FILE: platform/models/snippets.js
  class snippets (line 5) | class snippets extends Sequelize.Model {}
  method get (line 23) | get() {
  method get (line 29) | get() {
  method beforeCreate (line 39) | async beforeCreate(instance) {

FILE: platform/models/sticker_orders.js
  class sticker_orders (line 4) | class sticker_orders extends Sequelize.Model {}
  method beforeCreate (line 28) | beforeCreate(instance) {

FILE: platform/models/tags.js
  class tags (line 4) | class tags extends Sequelize.Model {}

FILE: platform/models/user_challenges.js
  class user_challenges (line 4) | class user_challenges extends Sequelize.Model {}
  method beforeCreate (line 24) | beforeCreate(instance) {

FILE: platform/models/users.js
  class users (line 5) | class users extends Sequelize.Model {}
  method beforeCreate (line 30) | beforeCreate(instance) {
  method beforeUpdate (line 40) | beforeUpdate(instance) {

FILE: platform/public/lib/bootbox/bootbox.js
  function d (line 6) | function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}
  function e (line 6) | function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunct...
  function f (line 6) | function f(a){var b,c=0;for(b in a)c++;return c}
  function g (line 6) | function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}
  function h (line 6) | function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supp...
  function i (line 6) | function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid...
  function j (line 6) | function j(a,c,d){return b.extend(!0,{},a,i(c,d))}
  function k (line 6) | function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b...
  function l (line 6) | function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=argument...
  function m (line 6) | function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,...

FILE: platform/public/lib/highlightjs/highlight-ln.js
  function t (line 1) | function t(){var n=e.createElement("style");n.type="text/css",n.innerHTM...
  function r (line 1) | function r(t){"complete"===e.readyState?l(t):n.addEventListener("DOMCont...
  function l (line 1) | function l(t){try{var r=e.querySelectorAll("code.hljs");for(var l in r)r...
  function i (line 1) | function i(n,e){if("object"==typeof n){e=e||{singleLine:!1};var t=e.sing...
  function o (line 1) | function o(n,e){var t=c(n);if(""===t[t.length-1].trim()&&t.pop(),t.lengt...
  function s (line 1) | function s(n){var e=n.childNodes;for(var t in e)if(e.hasOwnProperty(t)){...
  function a (line 1) | function a(n){var e=n.className;if(/hljs-/.test(e)){for(var t=c(n.innerH...
  function c (line 1) | function c(n){return 0===n.length?[]:n.split(L)}
  function d (line 1) | function d(n){return(n.trim().match(L)||[]).length}
  function u (line 1) | function u(e){n.setTimeout(e,0)}
  function h (line 1) | function h(n,e){return n.replace(/\{(\d+)\}/g,function(n,t){return e[t]?...

FILE: platform/public/lib/highlightjs/highlight.pack.js
  function n (line 2) | function n(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replac...
  function t (line 2) | function t(e){return e.nodeName.toLowerCase()}
  function r (line 2) | function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}
  function a (line 2) | function a(e){return k.test(e)}
  function i (line 2) | function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentN...
  function o (line 2) | function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n...
  function u (line 2) | function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i...
  function c (line 2) | function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r...
  function l (line 2) | function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map...
  function s (line 2) | function s(e){function n(e){return e&&e.source||e}function t(t,r){return...
  function f (line 2) | function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++...
  function g (line 2) | function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return...
  function p (line 2) | function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){ret...
  function h (line 2) | function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)...
  function d (line 2) | function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElem...
  function b (line 2) | function b(e){I=o(I,e)}
  function v (line 2) | function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("...
  function m (line 2) | function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener(...
  function N (line 2) | function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e)...
  function R (line 2) | function R(){return x(y)}
  function w (line 2) | function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}

FILE: platform/resources/challenges/templates/template.c
  function main (line 5) | int main(int argc, char **argv) {

FILE: platform/resources/challenges/templates/template.cs
  class MainClass (line 3) | class MainClass {
    method Main (line 4) | static void Main(string[] args) {

FILE: platform/resources/challenges/templates/template.go
  function main (line 9) | func main() {

FILE: platform/resources/challenges/templates/template.java
  class Main (line 1) | public class Main {
    method main (line 2) | public static void main(String[] args) {

FILE: platform/resources/challenges/templates/template.rs
  function main (line 5) | fn main() {

FILE: platform/resources/js/util.js
  class Util (line 4) | class Util {
    method unpack_props (line 5) | static unpack_props(props) {
    method try_render (line 13) | static try_render(id, comp) {
    method are_test_cases_valid (line 32) | static are_test_cases_valid(test_object) {

FILE: platform/resources/jsx/challenges/challenge.jsx
  method constructor (line 7) | constructor(props) {
  method componentDidMount (line 33) | componentDidMount() {
  method componentWillUnmount (line 46) | componentWillUnmount() {
  method execute (line 51) | async execute() {
  method editor_change (line 100) | editor_change(_) {
  method before_unload (line 110) | before_unload(e) {

FILE: platform/resources/jsx/challenges/manage_challenge.jsx
  method constructor (line 8) | constructor(props) {
  method componentDidMount (line 27) | componentDidMount() {
  method handle_change (line 69) | handle_change(e) {
  method save (line 91) | async save() {
  method manage_test (line 118) | manage_test(editing_test) {
  method delete_test (line 122) | async delete_test(index_to_delete) {
  method save_test (line 128) | async save_test() {

FILE: platform/resources/jsx/cli_script.jsx
  class CliScript (line 5) | class CliScript extends React.Component {
    method componentDidMount (line 6) | componentDidMount() {
    method render (line 28) | render() {

FILE: platform/resources/jsx/contests/contest.jsx
  method constructor (line 10) | constructor(props) {
  method highlight_blocks (line 56) | highlight_blocks() {
  method componentDidMount (line 62) | async componentDidMount() {
  method delete (line 231) | async delete(contest_submission_id) {

FILE: platform/resources/jsx/contests/description.jsx
  class Description (line 4) | class Description extends React.PureComponent {
    method ops_to_html (line 5) | ops_to_html(ops) {
    method render (line 16) | render() {

FILE: platform/resources/jsx/contests/manage.jsx
  class Manage (line 7) | class Manage extends React.Component {
    method constructor (line 8) | constructor(props) {
    method componentDidMount (line 17) | async componentDidMount() {
    method render (line 156) | render() {

FILE: platform/resources/jsx/login.jsx
  class Login (line 5) | class Login extends React.Component {
    method constructor (line 6) | constructor(props) {
    method open (line 17) | open(redirect) {
    method close (line 24) | close() {
    method render (line 30) | render() {

FILE: platform/resources/jsx/manage_snippet.jsx
  class ManageSnippet (line 6) | class ManageSnippet extends React.Component {
    method constructor (line 7) | constructor(props) {
    method componentDidMount (line 146) | componentDidMount() {
    method check_runnable_language (line 167) | check_runnable_language() {
    method execute (line 175) | async execute() {
    method handle_change (line 207) | handle_change(e) {
    method change_language (line 213) | change_language(event) {
    method toggle_word_wrap (line 227) | toggle_word_wrap() {
    method save (line 237) | async save() {
    method render (line 254) | render() {

FILE: platform/resources/jsx/mobile_nav.jsx
  class MobileNav (line 5) | class MobileNav extends React.Component {
    method constructor (line 6) | constructor(props) {
    method open (line 17) | open(redirect) {
    method close (line 23) | close() {
    method render (line 29) | render() {

FILE: platform/resources/jsx/ppman.jsx
  class PistonPackageManager (line 6) | class PistonPackageManager extends React.Component {
    method constructor (line 7) | constructor(props) {
    method componentDidMount (line 16) | async componentDidMount() {
    method render (line 24) | render() {

FILE: platform/resources/jsx/stickers.jsx
  class Stickers (line 7) | class Stickers extends React.Component {
    method constructor (line 8) | constructor(props) {
    method componentDidMount (line 30) | componentDidMount() {
    method handle_update (line 93) | handle_update(e) {
    method check_coupon (line 115) | check_coupon() {
    method submit (line 134) | submit(e) {
    method render (line 163) | render() {

FILE: platform/resources/jsx/users.jsx
  class Users (line 7) | class Users extends React.Component {
    method constructor (line 8) | constructor(props) {
    method render (line 28) | render() {
Condensed preview — 246 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (540K chars).
[
  {
    "path": ".gitignore",
    "chars": 377,
    "preview": "platform/config/local.js\nplatform/migrations/config.json\nplatform/public/css/*.css\nplatform/public/lib/webpack/*\n!platfo"
  },
  {
    "path": ".prettierignore",
    "chars": 216,
    "preview": "platform/config/local.js\nplatform/migrations/config.json\nplatform/public/css/*.css\nplatform/public/lib\nplatform/resource"
  },
  {
    "path": ".prettierrc.json",
    "chars": 76,
    "preview": "{\n    \"tabWidth\": 4,\n    \"singleQuote\": true,\n    \"trailingComma\": \"none\"\n}\n"
  },
  {
    "path": "Dockerfile",
    "chars": 313,
    "preview": "FROM node:14.3.0-stretch\n\nRUN apt update && apt install -y inotify-tools libjson-c-dev\nRUN cd /opt && \\\n    wget https:/"
  },
  {
    "path": "cdn/avatars/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docker-compose.yml",
    "chars": 907,
    "preview": "version: '3'\nservices:\n    emkc:\n        container_name: emkc\n        build: .\n        ports:\n            - '2005:2727'\n"
  },
  {
    "path": "emkc",
    "chars": 2280,
    "preview": "#!/usr/bin/env bash\n\nfunction init_files {\n    chmod 0444 var/docker/config/mysqld.cnf\n}\n\ncase $* in\n    init )\n        "
  },
  {
    "path": "license",
    "chars": 1081,
    "preview": "Copyright (c) 2018-2019 Brian Seymour, EMKC Contributors\n\nPermission is hereby granted, free of charge, to any person ob"
  },
  {
    "path": "package.json",
    "chars": 168,
    "preview": "{\n    \"scripts\": {\n        \"lint\": \"prettier --write .\",\n        \"check-lint\": \"prettier --check .\"\n    },\n    \"devDepen"
  },
  {
    "path": "platform/.babelrc",
    "chars": 245,
    "preview": "{\n    \"presets\": [\"@babel/preset-env\", \"@babel/preset-react\"],\n    \"plugins\": [\n        \"@babel/plugin-proposal-object-r"
  },
  {
    "path": "platform/api/controllers/AuthController.js",
    "chars": 5310,
    "preview": "const fs = require('fs');\nconst request = require('request-promise');\n\nmodule.exports = {\n    discord(req, res) {\n      "
  },
  {
    "path": "platform/api/controllers/ChallengesController.js",
    "chars": 14900,
    "preview": "const fs = require('fs');\nconst util = require('util');\n\nmodule.exports = {\n    async home(req, res) {\n        let optio"
  },
  {
    "path": "platform/api/controllers/CommunityController.js",
    "chars": 190,
    "preview": "module.exports = {\n    home(req, res) {\n        return res.view();\n    },\n\n    about(req, res) {\n        return res.view"
  },
  {
    "path": "platform/api/controllers/ContestsController.js",
    "chars": 12790,
    "preview": "const moment = require('moment');\n\nmodule.exports = {\n    async home(req, res) {\n        let past_contests = await db.co"
  },
  {
    "path": "platform/api/controllers/HomeController.js",
    "chars": 844,
    "preview": "module.exports = {\n    async home(req, res) {\n        let users = await db.users.find_all({\n            order: [['score'"
  },
  {
    "path": "platform/api/controllers/MerchController.js",
    "chars": 1189,
    "preview": "const moment = require('moment');\n\nmodule.exports = {\n    stickers(req, res) {\n        return res.view({\n            opt"
  },
  {
    "path": "platform/api/controllers/ProfilesController.js",
    "chars": 2679,
    "preview": "module.exports = {\n    async view(req, res) {\n        const username = req.params.username;\n\n        let user = await db"
  },
  {
    "path": "platform/api/controllers/ScriptsController.js",
    "chars": 857,
    "preview": "module.exports = {\n    async home(req, res) {\n        let scripts = await db.cli_scripts.find_all({\n            where: {"
  },
  {
    "path": "platform/api/controllers/SnippetsController.js",
    "chars": 3636,
    "preview": "module.exports = {\n    async view(req, res) {\n        const { hash } = req.params;\n\n        let snippet = await db.snipp"
  },
  {
    "path": "platform/api/controllers/TagsController.js",
    "chars": 469,
    "preview": "module.exports = {\n    async search(req, res) {\n        const name = req.query.name;\n\n        let tags = await db.tags.f"
  },
  {
    "path": "platform/api/controllers/admin/ChallengesController.js",
    "chars": 4547,
    "preview": "const create_tests = async (tests) => {\n    for (const test of tests) {\n        const { challenge_id, name, input, outpu"
  },
  {
    "path": "platform/api/controllers/admin/ContestsController.js",
    "chars": 4988,
    "preview": "const moment = require('moment');\n\nmodule.exports = {\n    async view_all(req, res) {\n        let all_contests = await db"
  },
  {
    "path": "platform/api/controllers/admin/DashboardController.js",
    "chars": 87,
    "preview": "module.exports = {\n    async dashboard(req, res) {\n        return res.view();\n    }\n};\n"
  },
  {
    "path": "platform/api/controllers/admin/PistonController.js",
    "chars": 1050,
    "preview": "module.exports = {\n    async view_all(req, res) {\n        return res.view({\n            message: null\n        });\n    },"
  },
  {
    "path": "platform/api/controllers/admin/UsersController.js",
    "chars": 1019,
    "preview": "module.exports = {\n    async view_all(req, res) {\n        let users = await db.users.find_all({\n            attributes: "
  },
  {
    "path": "platform/api/controllers/api/internal/ChatsController.js",
    "chars": 2704,
    "preview": "const crypto = require('crypto');\nconst moment = require('moment');\n\nmodule.exports = {\n    async last(req, res) {\n     "
  },
  {
    "path": "platform/api/controllers/api/internal/PistonController.js",
    "chars": 565,
    "preview": "module.exports = {\n    async log(req, res) {\n        let { server, server_id, user, user_id, language, source } = req.bo"
  },
  {
    "path": "platform/api/controllers/api/v1/PistonController.js",
    "chars": 2899,
    "preview": "const axios = require('axios');\nconst Redis = require('ioredis');\n\nmodule.exports = {\n    async versions(req, res) {\n   "
  },
  {
    "path": "platform/api/controllers/api/v1/UsersController.js",
    "chars": 914,
    "preview": "module.exports = {\n    async read_all(req, res) {\n        const { discord_id } = req.query;\n\n        let query = {\n     "
  },
  {
    "path": "platform/api/controllers/api/v1/stats/DiscordController.js",
    "chars": 3367,
    "preview": "const moment = require('moment');\n\nmodule.exports = {\n    async messages(req, res) {\n        let { user, discord_id, ter"
  },
  {
    "path": "platform/api/controllers/api/v1/stats/PistonController.js",
    "chars": 1640,
    "preview": "const moment = require('moment');\n\nmodule.exports = {\n    async usage(req, res) {\n        let { start, end, category } ="
  },
  {
    "path": "platform/api/controllers/api/v2/PistonController.js",
    "chars": 2741,
    "preview": "const axios = require('axios');\nconst Redis = require('ioredis');\n\nmodule.exports = {\n    async runtimes(req, res) {\n   "
  },
  {
    "path": "platform/api/policies/api_internal_auth.js",
    "chars": 396,
    "preview": "module.exports = (req, res, next) => {\n    let authorization;\n\n    Object.keys(req.headers).for_each((key) => {\n        "
  },
  {
    "path": "platform/api/policies/common.js",
    "chars": 404,
    "preview": "module.exports = async (req, res, next) => {\n    req.local = req.local || { user_id: null };\n\n    req.local.constant = c"
  },
  {
    "path": "platform/api/policies/is_admin.js",
    "chars": 157,
    "preview": "module.exports = (req, res, next) => {\n    if (!req.local.user || !req.local.user.is_staff) {\n        return res.redirec"
  },
  {
    "path": "platform/api/policies/is_prod.js",
    "chars": 131,
    "preview": "module.exports = (req, res, next) => {\n    if (!constant.is_prod) {\n        return res.redirect('/');\n    }\n\n    return "
  },
  {
    "path": "platform/api/policies/logged_in.js",
    "chars": 115,
    "preview": "module.exports = (req, res, next) => {\n    if (!req.local.user_id) return res.redirect('/');\n    return next();\n};\n"
  },
  {
    "path": "platform/api/services/api.js",
    "chars": 419,
    "preview": "module.exports = {\n    handle_err(res, err) {\n        console.log(err, '\\n\\n');\n\n        try {\n            err = JSON.pa"
  },
  {
    "path": "platform/api/services/constant.js",
    "chars": 2593,
    "preview": "let constant = {\n    no: 0,\n    yes: 1,\n\n    awards: {\n        type: {\n            contest_first_overall: 1,\n           "
  },
  {
    "path": "platform/api/services/contests.js",
    "chars": 2254,
    "preview": "module.exports = {\n    get_cases(contest, redact = false) {\n        if (contest.input === '' || contest.output === '') {"
  },
  {
    "path": "platform/api/services/discord.js",
    "chars": 560,
    "preview": "const request = require('request-promise');\n\nmodule.exports = {\n    async api(method, url, body = null) {\n        const "
  },
  {
    "path": "platform/api/services/dispenserd.js",
    "chars": 842,
    "preview": "const request = require('request-promise');\n\nmodule.exports = {\n    lane_main: 'main',\n\n    job_test: 'test',\n\n    /**\n "
  },
  {
    "path": "platform/api/services/error.js",
    "chars": 296,
    "preview": "const moment = require('moment');\n\nmodule.exports = {\n    log(err, msg) {\n        var final_message = '[msg] ' + msg + '"
  },
  {
    "path": "platform/api/services/mailer.js",
    "chars": 1481,
    "preview": "const moment = require('moment');\nconst q = require('q');\nconst mailgun = require('mailgun-js')({\n    apiKey: sails.conf"
  },
  {
    "path": "platform/api/services/piston.js",
    "chars": 4634,
    "preview": "const axios = require('axios');\nconst timeout = (ms) => new Promise((res) => set_timeout(res, ms));\n\nconst emkc_internal"
  },
  {
    "path": "platform/api/services/test_cases.js",
    "chars": 528,
    "preview": "module.exports = {\n    get_inputs_and_outputs(test_object) {\n        const inputs = test_object.input\n            .split"
  },
  {
    "path": "platform/api/services/twig.js",
    "chars": 366,
    "preview": "const moment = require('moment');\n\nconst twig = require('twig');\n\ntwig.extendFilter('noscript', (value) => {\n    if (!va"
  },
  {
    "path": "platform/api/services/util.js",
    "chars": 2285,
    "preview": "const fs = require('fs');\nconst moment = require('moment');\n\nmodule.exports = {\n    now() {\n        return moment().form"
  },
  {
    "path": "platform/api/services/views.js",
    "chars": 443,
    "preview": "const twig = require('twig');\n\nmodule.exports = {\n    async render(template, data) {\n        data.sails = sails;\n       "
  },
  {
    "path": "platform/config/blueprints.js",
    "chars": 109,
    "preview": "module.exports.blueprints = {\n    actions: false,\n    shortcuts: false,\n    rest: false,\n    index: false\n};\n"
  },
  {
    "path": "platform/config/bootstrap.js",
    "chars": 901,
    "preview": "process.env.TZ = 'UTC';\n\nrequire('nocamel');\n\nconst path = require('path');\nroot_dir = path.resolve(__dirname + '/../../"
  },
  {
    "path": "platform/config/controllers.js",
    "chars": 221,
    "preview": "module.exports.controllers = {\n    blueprints: {\n        actions: false,\n        rest: false,\n        shortcuts: false,\n"
  },
  {
    "path": "platform/config/http.js",
    "chars": 780,
    "preview": "module.exports.http = {\n    middleware: {\n        xframe: require('lusca').xframe('SAMEORIGIN'),\n        order: [\n      "
  },
  {
    "path": "platform/config/local.js.sample",
    "chars": 1096,
    "preview": "module.exports = {\n\n    port: 2727,\n    environment: 'development',\n    base_url: 'http://127.0.0.1:2005',\n    db: {\n   "
  },
  {
    "path": "platform/config/paths.js",
    "chars": 65,
    "preview": "module.exports.paths = {\n    public: __dirname + '/../public'\n};\n"
  },
  {
    "path": "platform/config/policies.js",
    "chars": 1855,
    "preview": "module.exports.policies = {\n    '*': 'common',\n\n    AuthController: {\n        '*': ['common']\n    },\n\n    ChallengesCont"
  },
  {
    "path": "platform/config/routes.js",
    "chars": 4889,
    "preview": "module.exports.routes = {\n    'GET /': 'HomeController.home',\n    'GET /logout': 'HomeController.logout',\n    'GET /logo"
  },
  {
    "path": "platform/config/session.js",
    "chars": 141,
    "preview": "module.exports.session = {\n    adapter: 'redis',\n    key: 'engineerman.sid',\n    cookie: {\n        maxAge: 60 * 60 * 24 "
  },
  {
    "path": "platform/config/sockets.js",
    "chars": 94,
    "preview": "module.exports.sockets = {\n    adapter: 'socket.io-redis'\n    // transports: ['websocket']\n};\n"
  },
  {
    "path": "platform/config/views.js",
    "chars": 259,
    "preview": "const twig = require('twig');\n\nfor (let filter of require('../resources/twig/filters')) {\n    twig.extendFilter(filter.n"
  },
  {
    "path": "platform/console/common.js",
    "chars": 544,
    "preview": "process.env.TZ = 'UTC';\nprocess.setMaxListeners(0);\n\nrequire('nocamel');\n\nPromise = require('bluebird');\n\nroot_dir = req"
  },
  {
    "path": "platform/console/cron.js",
    "chars": 12954,
    "preview": "#!/usr/bin/env node\nrequire('./common');\n\nconst axios = require('axios');\nconst moment = require('moment');\n\nconst timeo"
  },
  {
    "path": "platform/console/util.js",
    "chars": 1045,
    "preview": "#!/usr/bin/env node\nrequire('./common');\n\nconst moment = require('moment');\nconst request = require('request-promise');\n"
  },
  {
    "path": "platform/emkc.js",
    "chars": 1225,
    "preview": "/**\n * Engineer Man Knowledge Center\n * Copyright (C) 2021 Brian Seymour and EMKC Contributors\n *\n * Permission is hereb"
  },
  {
    "path": "platform/migrations/config.json.sample",
    "chars": 113,
    "preview": "{\n  \"host\": \"mysql\",\n  \"port\": 3306,\n  \"user\": \"root\",\n  \"pass\": \"root\",\n  \"db\": \"emkc\",\n  \"platform\": \"mysql\"\n}\n"
  },
  {
    "path": "platform/migrations/migrations/20180320123747-initial.sql",
    "chars": 33783,
    "preview": "up:\ncreate table users (\n    user_id int unsigned not null auto_increment,\n    is_staff tinyint unsigned not null defaul"
  },
  {
    "path": "platform/migrations/migrations/20180901170431-triggers.sql",
    "chars": 1548,
    "preview": "up:\ndrop trigger if exists question_vote_insert_trigger;\ndelimiter $\ncreate trigger question_vote_insert_trigger after i"
  },
  {
    "path": "platform/migrations/migrations/20180903004942-display-name.sql",
    "chars": 169,
    "preview": "up:\nalter table users add display_name varchar(64) not null after is_staff;\nupdate users set display_name = username;\n\nd"
  },
  {
    "path": "platform/migrations/migrations/20180903013450-question-tags.sql",
    "chars": 330,
    "preview": "up:\ncreate table question_tags (\n    question_tag_id int unsigned not null auto_increment,\n    question_id int not null "
  },
  {
    "path": "platform/migrations/migrations/20180903180404-default-avatar.sql",
    "chars": 192,
    "preview": "up:\nalter table users modify avatar_url varchar(128) not null default '/avatars/default.png' after discord_api;\n\ndown:\na"
  },
  {
    "path": "platform/migrations/migrations/20180903222426-views-field.sql",
    "chars": 129,
    "preview": "up:\nalter table questions add views int unsigned not null default 0 after score;\n\ndown:\nalter table questions drop colum"
  },
  {
    "path": "platform/migrations/migrations/20180905220531-notification-table.sql",
    "chars": 529,
    "preview": "up:\ncreate table notifications (\n    notification_id int unsigned not null auto_increment,\n    user_id int unsigned not "
  },
  {
    "path": "platform/migrations/migrations/20180908000333-new-tags.sql",
    "chars": 4257,
    "preview": "up:\ntruncate tags;\n\ninsert into tags values (default, 'java');\ninsert into tags values (default, 'c');\ninsert into tags "
  },
  {
    "path": "platform/migrations/migrations/20180915035412-code-rooms.sql",
    "chars": 390,
    "preview": "up:\ncreate table code_rooms (\n    code_room_id int unsigned not null auto_increment,\n    user_id int unsigned null,\n    "
  },
  {
    "path": "platform/migrations/migrations/20180917013146-snippet-language.sql",
    "chars": 166,
    "preview": "up:\nalter table snippets add language varchar(32) not null after hash;\nupdate snippets set language = 'javascript';\n\ndow"
  },
  {
    "path": "platform/migrations/migrations/20180930153901-video-requests.sql",
    "chars": 678,
    "preview": "up:\ncreate table video_requests (\n    video_request_id int unsigned not null auto_increment,\n    user_id int not null,\n "
  },
  {
    "path": "platform/migrations/migrations/20181005005500-challenges-tables.sql",
    "chars": 1076,
    "preview": "up:\ncreate table challenges (\n    challenge_id int unsigned not null auto_increment,\n    difficulty tinyint unsigned not"
  },
  {
    "path": "platform/migrations/migrations/20181021204739-chats-table.sql",
    "chars": 498,
    "preview": "up:\ncreate table discord_chat_messages (\n    discord_chat_message_id int unsigned not null auto_increment,\n    hash varc"
  },
  {
    "path": "platform/migrations/migrations/20181107035714-new-challenge.sql",
    "chars": 219,
    "preview": "up:\ninsert into challenges values (2, 1, 10, '2_number_frequency', 'Count number frequency', 'Take a string of numbers a"
  },
  {
    "path": "platform/migrations/migrations/20181111035714-new-challenge.sql",
    "chars": 206,
    "preview": "up:\ninsert into challenges values (3, 1, 10, '3_list_sum', 'Sum a list of numbers', 'Take a string of comma separated nu"
  },
  {
    "path": "platform/migrations/migrations/20181119035714-new-challenge.sql",
    "chars": 426,
    "preview": "up:\ninsert into challenges values (4, 3, 50, '4_invalid_json', 'Detect and fix invalid JSON', 'Take an invalid JSON stri"
  },
  {
    "path": "platform/migrations/migrations/20181121035714-discord-rank-field.sql",
    "chars": 139,
    "preview": "up:\nalter table users add discord_rank tinyint unsigned default null after discord_api;\n\ndown:\nalter table users drop co"
  },
  {
    "path": "platform/migrations/migrations/20181229135021-new-challenge.sql",
    "chars": 444,
    "preview": "up:\ninsert into challenges values (6, 2, 30, '6_fibonacci_sequence', 'Fibonacci Numbers', 'Start with one Fibonacci sequ"
  },
  {
    "path": "platform/migrations/migrations/20190104235301-new-challenge.sql",
    "chars": 466,
    "preview": "up:\ninsert into challenges values (8, 1, 10, '8_sort_integers', 'Integer list sorting', 'Take a list of integers and pri"
  },
  {
    "path": "platform/migrations/migrations/20190405004828-new-challenge.sql",
    "chars": 207,
    "preview": "up:\ninsert into challenges values (10, 3, 50, '10_pig_latin', 'Pig latin translator', 'Take a sentence/phrase in pig lat"
  },
  {
    "path": "platform/migrations/migrations/20190611224428-new-challenge.sql",
    "chars": 335,
    "preview": "up:\ninsert into challenges values (11, 2, 30, '11_array_neighbor', 'Zipper merge', 'Merge two arrays in a zipper-like fa"
  },
  {
    "path": "platform/migrations/migrations/20190622133430-new-challenge.sql",
    "chars": 206,
    "preview": "up:\ninsert into challenges values (12, 1, 10, '12_longest_word', 'Find Longest Word', 'Given a string with multiple word"
  },
  {
    "path": "platform/migrations/migrations/20190622224428-discord-id-chat-messages.sql",
    "chars": 220,
    "preview": "up:\nalter table discord_chat_messages add discord_id varchar(32) not null after user;\nalter table discord_chat_messages "
  },
  {
    "path": "platform/migrations/migrations/20190624224428-script-town.sql",
    "chars": 563,
    "preview": "up:\ncreate table cli_scripts (\n    cli_script_id int unsigned not null auto_increment,\n    user_id int unsigned not null"
  },
  {
    "path": "platform/migrations/migrations/20191023224428-stickers.sql",
    "chars": 577,
    "preview": "up:\ncreate table sticker_orders (\n    sticker_order_id int unsigned not null auto_increment,\n    is_fulfilled tinyint un"
  },
  {
    "path": "platform/migrations/migrations/20191101133430-new-challenge.sql",
    "chars": 232,
    "preview": "up:\ninsert into challenges values (13, 2, 30, '13_most_common_character', 'Find Most Common Characters', 'Given a string"
  },
  {
    "path": "platform/migrations/migrations/20191201133430-new-challenge.sql",
    "chars": 219,
    "preview": "up:\ninsert into challenges values (14, 2, 30, '14_number_digit_sum', 'Digit Sum Even or Odd', 'Given a number, find out "
  },
  {
    "path": "platform/migrations/migrations/20200711133430-piston-stats.sql",
    "chars": 515,
    "preview": "up:\ncreate table piston_runs (\n    piston_run_id int unsigned not null auto_increment,\n    server varchar(64) not null,\n"
  },
  {
    "path": "platform/migrations/migrations/20200711133431-piston-stats.sql",
    "chars": 275,
    "preview": "up:\nalter table piston_runs change discord_id user_id varchar(32) not null;\nalter table piston_runs add server_id varcha"
  },
  {
    "path": "platform/migrations/migrations/20200802133431-new-challenge.sql",
    "chars": 217,
    "preview": "up:\ninsert into challenges values (15, 1, 10, '15_binary_cookie', 'Find The Cookie', 'Given a binary string, a cookie, f"
  },
  {
    "path": "platform/migrations/migrations/20200813092823-new-challenge.sql",
    "chars": 206,
    "preview": "up:\ninsert into challenges values (16, 1, 10, '16_spiral_corner', 'Spiral Sum', 'Given the size of a spiral, calculate t"
  },
  {
    "path": "platform/migrations/migrations/20200825133432-new-challenge.sql",
    "chars": 203,
    "preview": "up:\ninsert into challenges values (17, 2, 30, '17_quadratic_calculator', 'Answer The Quadratic', 'Given a quadratic find"
  },
  {
    "path": "platform/migrations/migrations/20200830224428-contests-tables.sql",
    "chars": 1420,
    "preview": "up:\ncreate table contests (\n    contest_id int unsigned not null auto_increment,\n    name varchar(128) not null,\n    des"
  },
  {
    "path": "platform/migrations/migrations/20200905203703-contest-draft-field.sql",
    "chars": 136,
    "preview": "up:\nalter table contests add draft tinyint unsigned not null default 1 after contest_id;\n\ndown:\nalter table contests dro"
  },
  {
    "path": "platform/migrations/migrations/20200918012206-cleanup-old-tables.sql",
    "chars": 4227,
    "preview": "up:\ndrop table code_rooms;\ndrop table comment_votes;\ndrop table comments;\ndrop table notifications;\ndrop table question_"
  },
  {
    "path": "platform/migrations/migrations/20200918012216-award-table.sql",
    "chars": 524,
    "preview": "up:\ncreate table awards (\n    award_id int unsigned not null auto_increment,\n    type int unsigned not null,\n    points "
  },
  {
    "path": "platform/migrations/migrations/20210117125516-add-html-to-challenges.sql",
    "chars": 22565,
    "preview": "up:\nalter table challenges add html mediumtext default null after description;\nupdate challenges set html = '<div class="
  },
  {
    "path": "platform/migrations/migrations/20210117161957-create-tests-table.sql",
    "chars": 7893,
    "preview": "up:\ncreate table challenge_tests (\n    challenge_test_id int unsigned not null auto_increment,\n    challenge_id int unsi"
  },
  {
    "path": "platform/migrations/migrations/20210220201643-piston-run-changes.sql",
    "chars": 252,
    "preview": "up:\nalter table piston_runs modify server_id varchar(32) null;\nalter table piston_runs modify user_id varchar(32) null;\n"
  },
  {
    "path": "platform/migrations/migrations/20210314201643-challenge-draft.sql",
    "chars": 175,
    "preview": "up:\nalter table challenges add draft tinyint unsigned not null default 1 after challenge_id;\nupdate challenges set draft"
  },
  {
    "path": "platform/migrations/migrations/20210319145442-add-disallowed-languages.sql",
    "chars": 198,
    "preview": "up:\nalter table contests add disallowed_languages varchar(2048) after output;\nupdate contests set disallowed_languages ="
  },
  {
    "path": "platform/migrations/migrations/20210325110214-change-character-set.sql",
    "chars": 1587,
    "preview": "up:\nalter table awards convert to character set utf8mb4;\nalter table challenge_tests convert to character set utf8mb4;\na"
  },
  {
    "path": "platform/migrations/migrations/20210326154806-add-late-submissions.sql",
    "chars": 130,
    "preview": "up:\nalter table contest_submissions add late tinyint unsigned default 0;\n\ndown:\nalter table contest_submissions drop col"
  },
  {
    "path": "platform/migrations/migrations/20210401114642-add-explanation-field.sql",
    "chars": 150,
    "preview": "up:\nalter table contest_submissions add explanation mediumtext not null after length;\n\ndown:\nalter table contest_submiss"
  },
  {
    "path": "platform/migrations/migrations/20210423100104-add-language-version.sql",
    "chars": 161,
    "preview": "up:\nalter table contest_submissions add language_version varchar(32) not null after length;\n\ndown:\nalter table contest_s"
  },
  {
    "path": "platform/migrations/migrations/20210714100104-add-best-length.sql",
    "chars": 152,
    "preview": "up:\nalter table contest_submissions add length_best int unsigned not null after length;\n\ndown:\nalter table contest_submi"
  },
  {
    "path": "platform/migrations/migrations/20210901095201-remove-contest-draft-field.sql",
    "chars": 136,
    "preview": "up:\nalter table contests drop column draft;\n\ndown:\nalter table contests add draft tinyint unsigned not null default 1 af"
  },
  {
    "path": "platform/migrations/migrations/20220706141314-drop-challenges-folder.sql",
    "chars": 116,
    "preview": "up:\nalter table challenges drop column folder;\n\ndown:\nalter table challenges add column folder varchar(64) not null\n"
  },
  {
    "path": "platform/migrations/migrations/20220707092911-drop-official-field.sql",
    "chars": 135,
    "preview": "up:\nalter table challenge_tests drop column official;\n\ndown:\nalter table challenge_tests add column official tinyint(1) "
  },
  {
    "path": "platform/models/awards.js",
    "chars": 1818,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class awards extends Sequelize"
  },
  {
    "path": "platform/models/challenge_tests.js",
    "chars": 655,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class challenge_tests extends "
  },
  {
    "path": "platform/models/challenges.js",
    "chars": 1746,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class challenges extends Seque"
  },
  {
    "path": "platform/models/cli_scripts.js",
    "chars": 1418,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class cli_scripts extends Sequ"
  },
  {
    "path": "platform/models/contest_submissions.js",
    "chars": 1191,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class contest_submissions exte"
  },
  {
    "path": "platform/models/contests.js",
    "chars": 4521,
    "preview": "const Sequelize = require('sequelize');\nconst moment = require('moment');\n\nmodule.exports = (sequelize, DataTypes) => {\n"
  },
  {
    "path": "platform/models/discord_chat_messages.js",
    "chars": 914,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class discord_chat_messages ex"
  },
  {
    "path": "platform/models/index.js",
    "chars": 2586,
    "preview": "const path = require('path');\nconst basename = path.basename(module.filename);\nconst config = sails.config.db;\nconst db "
  },
  {
    "path": "platform/models/piston_runs.js",
    "chars": 902,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class piston_runs extends Sequ"
  },
  {
    "path": "platform/models/snippets.js",
    "chars": 1983,
    "preview": "const Sequelize = require('sequelize');\nconst crypto = require('crypto');\n\nmodule.exports = (sequelize, DataTypes) => {\n"
  },
  {
    "path": "platform/models/sticker_orders.js",
    "chars": 998,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class sticker_orders extends S"
  },
  {
    "path": "platform/models/tags.js",
    "chars": 507,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class tags extends Sequelize.M"
  },
  {
    "path": "platform/models/user_challenges.js",
    "chars": 865,
    "preview": "const Sequelize = require('sequelize');\n\nmodule.exports = (sequelize, DataTypes) => {\n    class user_challenges extends "
  },
  {
    "path": "platform/models/users.js",
    "chars": 1601,
    "preview": "const Sequelize = require('sequelize');\nconst crypto = require('crypto');\n\nmodule.exports = (sequelize, DataTypes) => {\n"
  },
  {
    "path": "platform/package.json",
    "chars": 2021,
    "preview": "{\n    \"scripts\": {\n        \"prod\": \"run-s prod:webpack prod:app\",\n        \"prod:webpack\": \"webpack --mode production --c"
  },
  {
    "path": "platform/pm2.json",
    "chars": 311,
    "preview": "{\n    \"name\": \"emkc\",\n    \"args\": [\"-i 0\"],\n    \"script\": \"emkc.js\",\n    \"node_args\": [\"--max_old_space_size=4096\"],\n   "
  },
  {
    "path": "platform/public/css/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "platform/public/js/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "platform/public/lib/bootbox/bootbox.js",
    "chars": 9817,
    "preview": "/**\n * bootbox.js v4.4.0\n *\n * http://bootboxjs.com/license.txt\n */\n!function(a,b){\"use strict\";\"function\"==typeof defin"
  },
  {
    "path": "platform/public/lib/highlightjs/atom-one-dark.css",
    "chars": 1277,
    "preview": "/*\n\nAtom One Dark by Daniel Gamage\nOriginal One Dark Syntax theme from https://github.com/atom/one-dark-syntax\n\nbase:   "
  },
  {
    "path": "platform/public/lib/highlightjs/default.css",
    "chars": 1159,
    "preview": "/*\n\nOriginal highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>\n\n*/\n\n.hljs {\n  display: block;\n  overflow"
  },
  {
    "path": "platform/public/lib/highlightjs/highlight-ln.js",
    "chars": 1751,
    "preview": "!function(n,e){\"use strict\";function t(){var n=e.createElement(\"style\");n.type=\"text/css\",n.innerHTML=h(\".{0}{border-col"
  },
  {
    "path": "platform/public/lib/highlightjs/highlight.pack.js",
    "chars": 46065,
    "preview": "/*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */\n!function(e){var n=\"object\"==typeof window&&window||\"obj"
  },
  {
    "path": "platform/public/lib/webpack/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "platform/public/other/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "platform/resources/challenges/templates/template.c",
    "chars": 152,
    "preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nint main(int argc, char **argv) {\n    %%_INSERTVALUES_%%\n\n  "
  },
  {
    "path": "platform/resources/challenges/templates/template.cpp",
    "chars": 131,
    "preview": "#include <iostream>\n#include <string>\n\nint main(int argc, char **argv) {\n    %%_INSERTVALUES_%%\n\n    // write your solut"
  },
  {
    "path": "platform/resources/challenges/templates/template.cs",
    "chars": 143,
    "preview": "using System;\n\nclass MainClass {\n    static void Main(string[] args) {\n        %%_INSERTVALUES_%%\n\n        // write your"
  },
  {
    "path": "platform/resources/challenges/templates/template.go",
    "chars": 135,
    "preview": "package main\n\nimport (\n    \"os\"\n    \"fmt\"\n    %%_IMPORTS_%%\n)\n\nfunc main() {\n    %%_INSERTVALUES_%%\n\n    // write your s"
  },
  {
    "path": "platform/resources/challenges/templates/template.hs",
    "chars": 112,
    "preview": "import System.Environment\n\nmain = do\n    args <- getArgs\n    %%_INSERTVALUES_%%\n    -- write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.java",
    "chars": 137,
    "preview": "public class Main {\n    public static void main(String[] args) {\n        %%_INSERTVALUES_%%\n\n        // write your solut"
  },
  {
    "path": "platform/resources/challenges/templates/template.jl",
    "chars": 47,
    "preview": "%%_INSERTVALUES_%%\n\n# write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.js",
    "chars": 48,
    "preview": "%%_INSERTVALUES_%%\n\n// write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.kt",
    "chars": 90,
    "preview": "fun main(args: Array<String>) {\n    %%_INSERTVALUES_%%\n\n    // write your solution here\n}\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.nim",
    "chars": 47,
    "preview": "%%_INSERTVALUES_%%\n\n# write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.php",
    "chars": 55,
    "preview": "<?php\n\n%%_INSERTVALUES_%%\n\n// write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.pl",
    "chars": 47,
    "preview": "%%_INSERTVALUES_%%\n\n# write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.py",
    "chars": 59,
    "preview": "import sys\n\n%%_INSERTVALUES_%%\n\n# write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.rb",
    "chars": 47,
    "preview": "%%_INSERTVALUES_%%\n\n# write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.rs",
    "chars": 176,
    "preview": "#![allow(dead_code,unused_variables)]\n\nuse std::env;\n\nfn main() {\n    let args: Vec<String> = env::args().collect();\n\n  "
  },
  {
    "path": "platform/resources/challenges/templates/template.sh",
    "chars": 47,
    "preview": "%%_INSERTVALUES_%%\n\n# write your solution here\n"
  },
  {
    "path": "platform/resources/challenges/templates/template.swift",
    "chars": 48,
    "preview": "%%_INSERTVALUES_%%\n\n// write your solution here\n"
  },
  {
    "path": "platform/resources/js/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "platform/resources/js/challenges/get_language_version.js",
    "chars": 417,
    "preview": "import axios from 'axios';\n\n$(document).ready(async function () {\n    if ($('.get-versions').length > 0) {\n        var l"
  },
  {
    "path": "platform/resources/js/common.js",
    "chars": 317,
    "preview": "const Constants = {\n    exp_mo: [\n        '01',\n        '02',\n        '03',\n        '04',\n        '05',\n        '06',\n  "
  },
  {
    "path": "platform/resources/js/snippets/delete_snippet.js",
    "chars": 684,
    "preview": "import axios from 'axios';\n\n$(document).on('click', '.confirm-delete', function (e) {\n    var hash = $(this).data('hash'"
  },
  {
    "path": "platform/resources/js/util.js",
    "chars": 1049,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nclass Util {\n    static unpack_props(props) {\n        for "
  },
  {
    "path": "platform/resources/jsx/challenges/challenge.jsx",
    "chars": 8152,
    "preview": "import React from 'react';\nimport axios from 'axios';\n\nimport Util from 'js/util';\n\nclass Challenge extends React.Compon"
  },
  {
    "path": "platform/resources/jsx/challenges/manage_challenge.jsx",
    "chars": 13226,
    "preview": "import React from 'react';\nimport axios from 'axios';\nimport Quill from 'quill';\n\nimport Util from 'js/util';\n\nclass Man"
  },
  {
    "path": "platform/resources/jsx/cli_script.jsx",
    "chars": 875,
    "preview": "import React from 'react';\n\nimport Util from 'js/util';\n\nclass CliScript extends React.Component {\n    componentDidMount"
  },
  {
    "path": "platform/resources/jsx/contests/contest.jsx",
    "chars": 31234,
    "preview": "import React from 'react';\nimport axios from 'axios';\nimport moment from 'moment';\n\nimport Util from 'js/util';\n\nimport "
  },
  {
    "path": "platform/resources/jsx/contests/description.jsx",
    "chars": 817,
    "preview": "import React from 'react';\nimport Quill from 'quill';\n\nclass Description extends React.PureComponent {\n    ops_to_html(o"
  },
  {
    "path": "platform/resources/jsx/contests/manage.jsx",
    "chars": 9516,
    "preview": "import React from 'react';\nimport axios from 'axios';\nimport Quill from 'quill';\n\nimport Util from 'js/util';\n\nclass Man"
  },
  {
    "path": "platform/resources/jsx/login.jsx",
    "chars": 1596,
    "preview": "import React from 'react';\n\nimport Util from 'js/util';\n\nclass Login extends React.Component {\n    constructor(props) {\n"
  },
  {
    "path": "platform/resources/jsx/manage_snippet.jsx",
    "chars": 13393,
    "preview": "import React from 'react';\nimport axios from 'axios';\n\nimport Util from 'js/util';\n\nclass ManageSnippet extends React.Co"
  },
  {
    "path": "platform/resources/jsx/mobile_nav.jsx",
    "chars": 1845,
    "preview": "import React from 'react';\n\nimport Util from 'js/util';\n\nclass MobileNav extends React.Component {\n    constructor(props"
  },
  {
    "path": "platform/resources/jsx/ppman.jsx",
    "chars": 2966,
    "preview": "import React from 'react';\nimport axios from 'axios';\n\nimport Util from 'js/util';\n\nclass PistonPackageManager extends R"
  },
  {
    "path": "platform/resources/jsx/stickers.jsx",
    "chars": 10810,
    "preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport axios from 'axios';\n\nimport Util from 'js/util';\n\ncl"
  },
  {
    "path": "platform/resources/jsx/users.jsx",
    "chars": 2499,
    "preview": "import React from 'react';\nimport axios from 'axios';\nimport moment from 'moment';\n\nimport Util from 'js/util';\n\nclass U"
  },
  {
    "path": "platform/resources/less/bootstrap.less",
    "chars": 1340,
    "preview": ".btn-success {\n    background-color: #37b86e;\n    &:hover {\n        background-color: #289254;\n    }\n}\n\n.badge-success {"
  },
  {
    "path": "platform/resources/less/colors.less",
    "chars": 112,
    "preview": "@challenge_easy: #84e47f;\n@challenge_medium: #e4e37f;\n@challenge_hard: #e47f8d;\n\n.green {\n    color: #8aecb4;\n}\n"
  },
  {
    "path": "platform/resources/less/em/challenge.less",
    "chars": 1176,
    "preview": "@import '../colors.less';\n\n.em_challenge {\n    position: absolute;\n    top: 56px;\n    left: 0;\n    right: 0;\n    bottom:"
  },
  {
    "path": "platform/resources/less/em/challenge_abstract.less",
    "chars": 1552,
    "preview": ".em_challenge .abstract,\n#react_manage_challenge .ql-editor {\n    .input {\n        p:last-child {\n            margin-bot"
  },
  {
    "path": "platform/resources/less/em/challenge_manage.less",
    "chars": 99,
    "preview": ".em_challenge_manage {\n    .case_box {\n        padding: 15px;\n        background: #1b1f27;\n    }\n}\n"
  },
  {
    "path": "platform/resources/less/em/challenges_list.less",
    "chars": 1056,
    "preview": "@import '../colors.less';\n\n.em_challenges_list {\n    .challenge_list {\n        margin-bottom: 20px;\n        .challenge {"
  },
  {
    "path": "platform/resources/less/em/common_content.less",
    "chars": 359,
    "preview": ".em_common_content {\n    max-width: 1140px;\n    width: 100%;\n    margin-left: auto;\n    margin-right: auto;\n    padding:"
  },
  {
    "path": "platform/resources/less/em/community_map.less",
    "chars": 391,
    "preview": ".em_community_map {\n    max-width: 1100px;\n    width: 100%;\n    margin: auto;\n    padding: 30px 15px;\n    .link_list {\n "
  },
  {
    "path": "platform/resources/less/em/container.less",
    "chars": 177,
    "preview": ".em_container {\n    display: inline-block;\n    margin: auto;\n    /*max-width: 1440px;*/\n    width: 100%;\n    text-align:"
  },
  {
    "path": "platform/resources/less/em/contests/contest.less",
    "chars": 1643,
    "preview": ".em_contests_contest {\n    .ql-editor {\n        padding-left: 0;\n        padding-right: 0;\n    }\n    .header {\n        m"
  },
  {
    "path": "platform/resources/less/em/contests/home.less",
    "chars": 839,
    "preview": ".em_contests_home {\n    * {\n        color: #fff;\n    }\n    .active {\n        margin-bottom: 40px;\n    }\n    .past {\n    "
  },
  {
    "path": "platform/resources/less/em/contests/manage.less",
    "chars": 279,
    "preview": ".em_contest_manage {\n    .wrapper {\n        display: flex;\n\n        .left {\n            flex: 1;\n            padding-rig"
  },
  {
    "path": "platform/resources/less/em/footer.less",
    "chars": 206,
    "preview": ".em_footer {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    background: #36b96e;\n    font-size: 1"
  },
  {
    "path": "platform/resources/less/em/language_choice.less",
    "chars": 496,
    "preview": "@import '../colors.less';\n\n.em_language_choice {\n    .icons > div {\n        text-align: center;\n        margin-bottom: 3"
  },
  {
    "path": "platform/resources/less/em/login.less",
    "chars": 968,
    "preview": ".em_login {\n    display: none;\n    &.open {\n        display: block;\n    }\n    .backdrop {\n        position: absolute;\n  "
  },
  {
    "path": "platform/resources/less/em/manage_snippet.less",
    "chars": 1482,
    "preview": ".em_manage_snippet {\n    #editor {\n        height: calc(100vh - 144px);\n        @media (max-width: 700px) {\n            "
  },
  {
    "path": "platform/resources/less/em/menu.less",
    "chars": 3141,
    "preview": ".em_menu {\n    display: flex;\n    padding: 10px;\n    background: #36b96e;\n    .mobile_expand {\n        display: none;\n  "
  },
  {
    "path": "platform/resources/less/em/mobile_nav.less",
    "chars": 1067,
    "preview": ".em_mobile_nav {\n    display: none;\n    &.open {\n        display: inline;\n    }\n    .backdrop {\n        position: absolu"
  },
  {
    "path": "platform/resources/less/em/power_system.less",
    "chars": 1300,
    "preview": ".em_power_system {\n    .tier_circle {\n        border-radius: 50%;\n        width: 100%;\n        padding-top: 100%;\n      "
  },
  {
    "path": "platform/resources/less/em/profile.less",
    "chars": 1580,
    "preview": "@import '../colors.less';\n\n.em_profile {\n    .content {\n        display: flex;\n        .left {\n            width: 220px;"
  },
  {
    "path": "platform/resources/less/em/staff_container.less",
    "chars": 72,
    "preview": ".em_staff_container {\n    padding: 4px 10px;\n    background: #313847;\n}\n"
  },
  {
    "path": "platform/resources/less/em/stickers.less",
    "chars": 401,
    "preview": ".em_stickers {\n    .sticker {\n        max-width: 200px;\n        width: 100%;\n        height: auto;\n        margin-top: 2"
  },
  {
    "path": "platform/resources/less/em/top_members.less",
    "chars": 1166,
    "preview": ".em_top_members {\n    .user_row {\n        position: relative;\n        display: flex;\n        margin-bottom: 4px;\n       "
  },
  {
    "path": "platform/resources/less/global.less",
    "chars": 2182,
    "preview": "html,\nbody {\n    font-family: 'Lato', sans-serif;\n    color: #fff;\n}\n\nbody {\n    text-align: center;\n    background: #28"
  },
  {
    "path": "platform/resources/less/highlightjs.less",
    "chars": 173,
    "preview": "td.hljs-ln-code {\n    padding-left: 10px !important;\n}\ntd.hljs-ln-numbers {\n    background: #1b1f27;\n    padding-left: 5"
  },
  {
    "path": "platform/resources/less/quill.less",
    "chars": 919,
    "preview": ".ql-toolbar {\n    background: #1b1f27 !important;\n    border: 0 !important;\n    svg {\n        * {\n            stroke: #f"
  },
  {
    "path": "platform/resources/main.js",
    "chars": 434,
    "preview": "import 'core-js/stable';\nimport 'regenerator-runtime/runtime';\n\nimport axios from 'axios';\n\ntry {\n    axios.defaults.val"
  }
]

// ... and 46 more files (download for full content)

About this extraction

This page contains the full source code of the engineer-man/emkc GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 246 files (491.3 KB), approximately 120.5k tokens, and a symbol index with 272 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!