├── chrome-extension
├── options.html
├── icons
│ ├── web.png
│ ├── github.png
│ ├── icon128.png
│ ├── icon16.png
│ ├── icon32.png
│ ├── icon48.png
│ └── icon64.png
├── css
│ └── main.css
├── popup.html
├── manifest.json
├── background.js
└── foreground.js
├── .gitignore
├── .vscode
└── settings.json
├── public
├── favicon.ico
├── robots.txt
├── favicon-16x16.png
├── favicon-32x32.png
├── apple-touch-icon.png
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── site.webmanifest
├── js
│ └── darkmode.js
└── stylesheets
│ ├── tablestyle.css
│ ├── darkmode.css
│ └── main.css
├── data
└── screenshots
│ ├── icon.png
│ ├── web_demo.gif
│ ├── bull-dashboard1.png
│ ├── bull-dashboard2.png
│ └── extension_demo.gif
├── services
├── predict-addon
│ ├── addon.js
│ ├── build
│ │ ├── Release
│ │ │ ├── predict_addon.node
│ │ │ ├── obj.target
│ │ │ │ ├── predict_addon.node
│ │ │ │ └── predict_addon
│ │ │ │ │ └── cpp
│ │ │ │ │ └── main.o
│ │ │ └── .deps
│ │ │ │ └── Release
│ │ │ │ ├── predict_addon.node.d
│ │ │ │ └── obj.target
│ │ │ │ ├── predict_addon.node.d
│ │ │ │ └── predict_addon
│ │ │ │ └── cpp
│ │ │ │ └── main.o.d
│ │ ├── binding.Makefile
│ │ ├── predict_addon.target.mk
│ │ ├── config.gypi
│ │ └── Makefile
│ ├── binding.gyp
│ ├── package.json
│ ├── cpp
│ │ ├── main.cpp
│ │ ├── helpers.h
│ │ └── predict.h
│ └── test
│ │ └── test.js
├── redis.js
├── predict.js
├── job-queues
│ ├── contestPredictionQueue.js
│ └── jobScheduler.js
├── contests.js
└── users.js
├── web.js
├── views
├── errors
│ └── 404.ejs
├── login.ejs
├── layouts
│ └── layout.ejs
├── index.ejs
└── ranking.ejs
├── .env.example
├── routes
├── api.js
├── index.js
└── auth.js
├── .github
└── FUNDING.yml
├── models
├── user.js
└── contest.js
├── LICENSE
├── background.js
├── package.json
├── helpers.js
├── controllers
├── predictionsController.js
├── sitemapController.js
└── rankingsController.js
├── tests
└── ratelimit.test.js
├── main.js
└── README.md
/chrome-extension/options.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | node_modules
3 | .snyk
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "iostream": "cpp"
4 | }
5 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | Sitemap: https://lcpredictor.onrender.com/sitemap.xml
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/public/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/public/favicon-32x32.png
--------------------------------------------------------------------------------
/data/screenshots/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/data/screenshots/icon.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/services/predict-addon/addon.js:
--------------------------------------------------------------------------------
1 | const addon = require("./build/Release/predict_addon");
2 | module.exports = addon;
3 |
--------------------------------------------------------------------------------
/data/screenshots/web_demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/data/screenshots/web_demo.gif
--------------------------------------------------------------------------------
/chrome-extension/icons/web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/chrome-extension/icons/web.png
--------------------------------------------------------------------------------
/chrome-extension/icons/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/chrome-extension/icons/github.png
--------------------------------------------------------------------------------
/chrome-extension/icons/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/chrome-extension/icons/icon128.png
--------------------------------------------------------------------------------
/chrome-extension/icons/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/chrome-extension/icons/icon16.png
--------------------------------------------------------------------------------
/chrome-extension/icons/icon32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/chrome-extension/icons/icon32.png
--------------------------------------------------------------------------------
/chrome-extension/icons/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/chrome-extension/icons/icon48.png
--------------------------------------------------------------------------------
/chrome-extension/icons/icon64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/chrome-extension/icons/icon64.png
--------------------------------------------------------------------------------
/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/data/screenshots/bull-dashboard1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/data/screenshots/bull-dashboard1.png
--------------------------------------------------------------------------------
/data/screenshots/bull-dashboard2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/data/screenshots/bull-dashboard2.png
--------------------------------------------------------------------------------
/data/screenshots/extension_demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/data/screenshots/extension_demo.gif
--------------------------------------------------------------------------------
/services/predict-addon/build/Release/predict_addon.node:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/services/predict-addon/build/Release/predict_addon.node
--------------------------------------------------------------------------------
/services/predict-addon/build/binding.Makefile:
--------------------------------------------------------------------------------
1 | # This file is generated by gyp; do not edit.
2 |
3 | export builddir_name ?= ./build/.
4 | .PHONY: all
5 | all:
6 | $(MAKE) predict_addon
7 |
--------------------------------------------------------------------------------
/services/predict-addon/binding.gyp:
--------------------------------------------------------------------------------
1 | {
2 | "targets": [
3 | {
4 | "target_name": "predict_addon",
5 | "sources": ["./cpp/main.cpp"],
6 | },
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/services/predict-addon/build/Release/obj.target/predict_addon.node:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/services/predict-addon/build/Release/obj.target/predict_addon.node
--------------------------------------------------------------------------------
/services/predict-addon/build/Release/obj.target/predict_addon/cpp/main.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SysSn13/leetcode-rating-predictor/HEAD/services/predict-addon/build/Release/obj.target/predict_addon/cpp/main.o
--------------------------------------------------------------------------------
/services/predict-addon/build/Release/.deps/Release/predict_addon.node.d:
--------------------------------------------------------------------------------
1 | cmd_Release/predict_addon.node := rm -rf "Release/predict_addon.node" && cp -af "Release/obj.target/predict_addon.node" "Release/predict_addon.node"
2 |
--------------------------------------------------------------------------------
/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/web.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const app = express();
3 | app.use(express.urlencoded({ extended: true }));
4 | const indexRouter = require("./routes/index");
5 |
6 | const router = express.Router();
7 | router.use("/", indexRouter);
8 |
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/chrome-extension/css/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Arial, sans-serif;
3 | font-weight: 400;
4 | min-width: 320px;
5 | padding: 0;
6 | margin: 0;
7 | }
8 | .icon{
9 | max-width: 32px;
10 | }
--------------------------------------------------------------------------------
/services/predict-addon/build/Release/.deps/Release/obj.target/predict_addon.node.d:
--------------------------------------------------------------------------------
1 | cmd_Release/obj.target/predict_addon.node := g++ -shared -pthread -rdynamic -m64 -Wl,-soname=predict_addon.node -o Release/obj.target/predict_addon.node -Wl,--start-group Release/obj.target/predict_addon/cpp/main.o -Wl,--end-group
2 |
--------------------------------------------------------------------------------
/views/errors/404.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 | 404
4 |
5 |
6 |
7 | This page does not exist.
8 |
9 |
10 |
Back to home
11 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | DATABASE_URL=mongodb://localhost
2 |
3 | WEB=1
4 | RATE_LIMIT_WINDOW=10000
5 | RATE_LIMIT=50
6 |
7 | API_DISABLED=0
8 | API_RATE_LIMIT_WINDOW=10000
9 | API_RATE_LIMIT=20
10 |
11 | BACKGROUND=0
12 | REDIS_URL=redis://127.0.0.1:6379
13 | THREAD_CNT=4
14 |
15 | BULLBOARD_USERNAME=bull-board
16 | BULLBOARD_PASS=admin
17 | SESSION_SECRET=keyboard-key
--------------------------------------------------------------------------------
/services/predict-addon/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "predict-addon",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "addon.js",
6 | "scripts": {
7 | "test": "node ./test/test.js",
8 | "build":"node-gyp clean && node-gyp configure && node-gyp build"
9 | },
10 | "keywords": [],
11 | "author": "Sudesh Chaudhary",
12 | "license": "MIT"
13 | }
14 |
--------------------------------------------------------------------------------
/views/login.ejs:
--------------------------------------------------------------------------------
1 |
2 |
Login to bull-board
3 |
8 |
--------------------------------------------------------------------------------
/routes/api.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const predictionsController = require("../controllers/predictionsController.js");
3 | router.get("/ping", function (req, res) {
4 | res.json({
5 | status: "OK",
6 | message: "pong",
7 | });
8 | });
9 |
10 | router.route("/predictions").get(predictionsController.get);
11 | module.exports = router;
12 |
--------------------------------------------------------------------------------
/public/js/darkmode.js:
--------------------------------------------------------------------------------
1 | var preference = JSON.parse(localStorage.getItem("dark"));
2 | if (preference === null) {
3 | localStorage.setItem("dark", false);
4 | preference=false;
5 | }
6 | var checkBox = document.getElementById("checkDark");
7 | if(checkBox){
8 | checkBox.checked = preference;
9 | }
10 | const html = document.getElementsByTagName("html")[0];
11 |
12 | if (preference) {
13 | html.style.filter = "invert(0.9) hue-rotate(150deg)";
14 | } else {
15 | html.style.filter = "";
16 | }
17 |
18 | function toggle_darkmode() {
19 | preference = !preference;
20 | checkBox.checked = preference;
21 | localStorage.setItem("dark", preference);
22 |
23 | if (preference) {
24 | html.style.filter = "invert(0.9) hue-rotate(150deg)";
25 | } else {
26 | html.style.filter = "";
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/services/redis.js:
--------------------------------------------------------------------------------
1 | const REDIS_URL = process.env.REDIS_URL || "redis://127.0.0.1:6379";
2 |
3 | const Redis = require("ioredis");
4 | const client = new Redis(REDIS_URL);
5 | const subscriber = new Redis(REDIS_URL);
6 |
7 | const opts = {
8 | // redisOpts here will contain at least a property of connectionName which will identify the queue based on its name
9 | createClient: function (type, redisOpts) {
10 | switch (type) {
11 | case "client":
12 | return client;
13 | case "subscriber":
14 | return subscriber;
15 | case "bclient":
16 | return new Redis(REDIS_URL, redisOpts);
17 | default:
18 | throw new Error("Unexpected connection type: ", type);
19 | }
20 | },
21 | };
22 | module.exports = opts;
23 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: leetcode-rating-predictor # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/routes/index.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const Contest = require("../models/contest");
3 | const router = express.Router();
4 | const rankingsController = require("../controllers/rankingsController");
5 | const sitemapController = require("../controllers/sitemapController");
6 |
7 | router.get("/", async (req, res) => {
8 | try {
9 | let contests = await Contest.find({}, { rankings: 0 }).sort({
10 | startTime: "desc",
11 | });
12 |
13 | res.render("index", {
14 | contests: contests,
15 | title: "Leetcode Rating Predictor",
16 | });
17 | } catch (err) {
18 | console.error(err);
19 | res.sendStatus(500);
20 | }
21 | });
22 |
23 | router.get("/contest/:contestSlug/ranking/:page", rankingsController.get);
24 | router.post("/contest/:contestSlug/ranking/search", rankingsController.search);
25 | router.get("/sitemap.xml", sitemapController.get);
26 | module.exports = router;
27 |
--------------------------------------------------------------------------------
/models/user.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose")
2 |
3 | const contestHistorySchema = new mongoose.Schema({
4 | _id: String,
5 | title: String,
6 | startTime: Number,
7 | rating: {
8 | type: Number,
9 | default:1500,
10 | },
11 | ranking:{
12 | type:Number,
13 | default: 0
14 | },
15 | })
16 | const userSchema = new mongoose.Schema({
17 | _id:{
18 | type: String
19 | },
20 | attendedContestsCount:{
21 | type: Number,
22 | default: 0
23 | },
24 | rating:{
25 | type: Number,
26 | default: 1500
27 | },
28 | globalRanking:{
29 | type: Number,
30 | default:0
31 | },
32 | contestsHistory: [contestHistorySchema],
33 | lastUpdated:{
34 | type: Date,
35 | default: Date.now,
36 | },
37 | })
38 |
39 | exports.User = mongoose.model("User",userSchema)
40 | exports.ContestHistory = mongoose.model("ContestHistory",contestHistorySchema)
--------------------------------------------------------------------------------
/chrome-extension/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | LC Predictor
6 |
7 |
8 |
9 |
10 |
11 |
12 |

13 |
14 | Leetcode rating predictor
15 |
16 |
17 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/routes/auth.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const router = express.Router();
3 |
4 | const passport = require('passport');
5 | const LocalStrategy = require('passport-local').Strategy;
6 |
7 | passport.use(
8 | new LocalStrategy(function (username, password, cb) {
9 | if (username === process.env.BULLBOARD_USERNAME && password === process.env.BULLBOARD_PASS) {
10 | return cb(null, {user : process.env.BULLBOARD_USERNAME});
11 | }
12 | return cb(null, false);
13 | })
14 | );
15 |
16 | passport.serializeUser((user, cb) => {
17 | cb(null, user);
18 | });
19 |
20 | passport.deserializeUser((user, cb) => {
21 | cb(null, user);
22 | });
23 |
24 | router.get('/', (req, res) => {
25 | res.render('login', {
26 | title : 'Login'
27 | });
28 | });
29 |
30 | router.post('/',
31 | passport.authenticate('local', { failureRedirect: '/login' }),
32 | function(req, res){
33 | res.redirect('/bull-board');
34 | }
35 | );
36 |
37 | module.exports = router;
38 |
--------------------------------------------------------------------------------
/chrome-extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 3,
3 | "name": "LC Predictor",
4 | "version": "1.0.1",
5 |
6 | "short_name": "LC Predictor",
7 | "background": {
8 | "service_worker": "background.js"
9 | },
10 | "action": {
11 | "default_popup": "./popup.html",
12 | "icons": {
13 | "16": "/icons/icon16.png",
14 | "32": "/icons/icon32.png",
15 | "48": "/icons/icon48.png",
16 | "64": "/icons/icon64.png",
17 | "128": "/icons/icon128.png"
18 | }
19 | },
20 | "description": "Browser extension for predicting leetcode contest rating. It shows approximate rating delta after contests on leetcode itself.",
21 | "icons": {
22 | "16": "/icons/icon16.png",
23 | "32": "/icons/icon32.png",
24 | "48": "/icons/icon48.png",
25 | "64": "/icons/icon64.png",
26 | "128": "/icons/icon128.png"
27 | },
28 | "options_page": "./options.html",
29 | "permissions": [
30 | "tabs",
31 | "storage",
32 | "scripting"
33 | ],
34 | "host_permissions": [
35 | "https://leetcode.com/*",
36 | "https://lcpredictor.onrender.com/*"
37 | ]
38 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Sudesh Chaudhary
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/services/predict-addon/cpp/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "helpers.h"
5 |
6 | using namespace v8;
7 | using namespace std;
8 |
9 | void PredictRatings(const FunctionCallbackInfo &args){
10 | Isolate* isolate = args.GetIsolate();
11 | Local context = isolate->GetCurrentContext();
12 | vector rankList = unpackRankList(isolate,args);
13 | int THREAD_CNT = 1;
14 | if(args.Length()>1){
15 | if(!args[1]->IsNumber()){
16 | isolate->ThrowException(
17 | Exception::TypeError(
18 | String::NewFromUtf8(
19 | isolate,"Wrong arguments. THREAD_CNT must be a Number."
20 | ).ToLocalChecked()
21 | )
22 | );
23 | }
24 | THREAD_CNT = max(THREAD_CNT,int(args[1]->NumberValue(context).FromMaybe(1)));
25 | }
26 | Predict(rankList,THREAD_CNT);
27 | Local predictedRatings = packRankList(rankList);
28 | args.GetReturnValue().Set(predictedRatings);
29 | }
30 |
31 | void init(Local