├── config ├── __init__.py ├── __pycache__ │ ├── urls.cpython-312.pyc │ ├── wsgi.cpython-312.pyc │ ├── __init__.cpython-312.pyc │ └── settings.cpython-312.pyc ├── asgi.py ├── wsgi.py ├── urls.py └── settings.py ├── profiles ├── __init__.py ├── migrations │ ├── __init__.py │ └── __pycache__ │ │ └── __init__.cpython-312.pyc ├── models.py ├── admin.py ├── tests.py ├── urls.py ├── __pycache__ │ ├── admin.cpython-312.pyc │ ├── apps.cpython-312.pyc │ ├── urls.cpython-312.pyc │ ├── views.cpython-312.pyc │ ├── __init__.cpython-312.pyc │ └── models.cpython-312.pyc ├── apps.py └── views.py ├── db.sqlite3 ├── static ├── img │ └── SitePreview.png └── css │ └── rank.css ├── README.md ├── requirements.txt ├── .gitignore ├── manage.py └── templates └── rank.html /config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /profiles/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /profiles/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/db.sqlite3 -------------------------------------------------------------------------------- /profiles/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /profiles/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /profiles/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /static/img/SitePreview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/static/img/SitePreview.png -------------------------------------------------------------------------------- /profiles/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | urlpatterns = [ 5 | path('', views.rank, name='rank'), 6 | ] -------------------------------------------------------------------------------- /config/__pycache__/urls.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/config/__pycache__/urls.cpython-312.pyc -------------------------------------------------------------------------------- /config/__pycache__/wsgi.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/config/__pycache__/wsgi.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/__pycache__/admin.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/profiles/__pycache__/admin.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/__pycache__/apps.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/profiles/__pycache__/apps.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/__pycache__/urls.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/profiles/__pycache__/urls.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/__pycache__/views.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/profiles/__pycache__/views.cpython-312.pyc -------------------------------------------------------------------------------- /config/__pycache__/__init__.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/config/__pycache__/__init__.cpython-312.pyc -------------------------------------------------------------------------------- /config/__pycache__/settings.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/config/__pycache__/settings.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/__pycache__/__init__.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/profiles/__pycache__/__init__.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/__pycache__/models.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/profiles/__pycache__/models.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/migrations/__pycache__/__init__.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevOgabek/LeetCodeReputationRank/HEAD/profiles/migrations/__pycache__/__init__.cpython-312.pyc -------------------------------------------------------------------------------- /profiles/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ProfilesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'profiles' 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LeetCode Reputation Rank 2 | 3 | [![Site Preview](static/img/SitePreview.png)](http://leetcodereputationrank.pythonanywhere.com) 4 | 5 | ## Live Demo 6 | Check out the live demo: [LeetCode Reputation Rank](http://leetcodereputationrank.pythonanywhere.com) 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiosignal==1.3.1 2 | asgiref==3.7.2 3 | attrs==23.2.0 4 | beautifulsoup4==4.12.3 5 | bs4==0.0.2 6 | certifi==2024.2.2 7 | charset-normalizer==3.3.2 8 | Django==5.0.3 9 | frozenlist==1.4.1 10 | idna==3.6 11 | multidict==6.0.5 12 | python-decouple==3.8 13 | requests==2.31.0 14 | soupsieve==2.5 15 | sqlparse==0.4.4 16 | urllib3==2.2.1 17 | yarl==1.9.4 18 | -------------------------------------------------------------------------------- /config/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for config project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /config/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for config project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Icon must end with two \r 7 | Icon 8 | 9 | 10 | # Thumbnails 11 | ._* 12 | 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | .com.apple.timemachine.donotpresent 21 | 22 | # Directories potentially created on remote AFP share 23 | .AppleDB 24 | .AppleDesktop 25 | Network Trash Folder 26 | Temporary Items 27 | .apdisk 28 | 29 | .env -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /config/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URL configuration for config project. 3 | 4 | The `urlpatterns` list routes URLs to views. For more information please see: 5 | https://docs.djangoproject.com/en/5.0/topics/http/urls/ 6 | Examples: 7 | Function views 8 | 1. Add an import: from my_app import views 9 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 10 | Class-based views 11 | 1. Add an import: from other_app.views import Home 12 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 13 | Including another URLconf 14 | 1. Import the include() function: from django.urls import include, path 15 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 16 | """ 17 | from django.contrib import admin 18 | from django.urls import path, include 19 | 20 | urlpatterns = [ 21 | path('admin/', admin.site.urls), 22 | path('', include('profiles.urls')) 23 | ] 24 | -------------------------------------------------------------------------------- /profiles/views.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | from decouple import config 4 | from django.shortcuts import render 5 | 6 | URL = config("URL") 7 | 8 | def rank(request): 9 | profiles = [] 10 | profiles += get_leetcode_profiles(start=0, end=98) 11 | profiles += get_leetcode_profiles(start=100, end=198) 12 | profiles += get_leetcode_profiles(start=200, end=298) 13 | profiles += get_leetcode_profiles(start=300, end=398) 14 | profiles += get_leetcode_profiles(start=400, end=499) 15 | return render(request, 'rank.html', {'profiles': profiles}) 16 | 17 | def get_leetcode_profiles(url=URL, start=1, end=98): 18 | try: 19 | with requests.Session() as session: 20 | response = session.get(url) 21 | response.raise_for_status() 22 | 23 | soup = BeautifulSoup(response.text, 'html.parser') 24 | 25 | profiles = [] 26 | for index, row in enumerate(soup.find_all('tr', class_='layout_trCenter__6KUQy')): 27 | if end is not None and index > end: 28 | break 29 | 30 | if index + 1 < start: 31 | continue 32 | 33 | columns = row.find_all('td') 34 | 35 | if len(columns) >= 3: 36 | avatar_url = columns[0].find('img')['src'] 37 | reputation_count = columns[1].text.strip() 38 | rank = columns[2].text.strip() 39 | username = columns[0].text.split()[-1] 40 | profile_info = { 41 | 'username': username, 42 | 'avatar_url': avatar_url, 43 | 'reputation_count': reputation_count, 44 | 'rank': int(rank) 45 | } 46 | profiles.append(profile_info) 47 | 48 | return profiles 49 | 50 | except requests.RequestException as e: 51 | print(f"Error fetching data: {e}") 52 | return None -------------------------------------------------------------------------------- /static/css/rank.css: -------------------------------------------------------------------------------- 1 | .ranking { 2 | max-width: 800px; 3 | margin: 20px auto; 4 | background-color: #f7f7f7; 5 | border-radius: 8px; 6 | overflow: hidden; 7 | } 8 | 9 | 10 | .rank-item-th { 11 | height: 20px; 12 | display: flex; 13 | align-items: center; 14 | border-bottom: 1px solid #eee; 15 | padding: 15px; 16 | transition: background-color 0.3s; 17 | } 18 | 19 | 20 | @keyframes fadeIn { 21 | from { 22 | opacity: 0; 23 | transform: translateY(-20px); 24 | } 25 | 26 | to { 27 | opacity: 1; 28 | transform: translateY(0); 29 | } 30 | } 31 | 32 | 33 | .rank-item { 34 | display: flex; 35 | align-items: center; 36 | border-bottom: 1px solid #eee; 37 | padding: 15px; 38 | transition: background-color 0.3s, opacity 0.3s, transform 0.3s; 39 | cursor: pointer; 40 | animation: fadeIn 0.5s ease-out; 41 | } 42 | 43 | .rank-item:hover { 44 | background-color: #eee; 45 | } 46 | 47 | 48 | .rank, 49 | .rank-th { 50 | font-size: 1.5em; 51 | font-weight: bold; 52 | color: #333; 53 | position: absolute; 54 | } 55 | 56 | .rank { 57 | margin-left: 730px; 58 | } 59 | 60 | .rank-th { 61 | margin-top: 5px; 62 | margin-left: 715px; 63 | } 64 | 65 | 66 | .profile-container { 67 | display: flex; 68 | align-items: center; 69 | } 70 | 71 | .profile-img { 72 | width: 60px; 73 | height: 60px; 74 | border-radius: 50%; 75 | margin-right: 20px; 76 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); 77 | } 78 | 79 | .details { 80 | flex-grow: 1; 81 | } 82 | 83 | 84 | .name, 85 | .name-th { 86 | font-size: 1.2em; 87 | color: #333; 88 | font-weight: bold; 89 | position: absolute; 90 | } 91 | 92 | .name { 93 | margin-left: auto; 94 | margin-top: -10px; 95 | } 96 | 97 | .name-th { 98 | margin-left: auto; 99 | margin-top: -5px; 100 | } 101 | 102 | .reputation, 103 | .reputation-th { 104 | color: #666; 105 | position: absolute; 106 | } 107 | 108 | .reputation { 109 | margin-top: -5px; 110 | margin-left: 560px; 111 | } 112 | 113 | .reputation-th { 114 | margin-top: -5px; 115 | margin-left: 620px; 116 | } 117 | 118 | 119 | .top-1 { 120 | background-color: #c0c0c0; 121 | } 122 | 123 | .top-2 { 124 | background-color: #d2d2d2; 125 | } 126 | 127 | .top-3 { 128 | background-color: #e8e8e8; 129 | } 130 | 131 | 132 | .th { 133 | height: 10px; 134 | } 135 | 136 | .me { 137 | background-color: rgb(203, 214, 236); 138 | } 139 | 140 | 141 | footer { 142 | position: fixed; 143 | bottom: 0; 144 | width: 800px; 145 | 146 | } 147 | 148 | @media only screen and (max-width: 600px) { 149 | 150 | 151 | .rank-th { 152 | font-size: 0.9em; 153 | margin-left: 255px; 154 | } 155 | 156 | .rank { 157 | font-size: 0.9em; 158 | margin-left: 270px; 159 | } 160 | 161 | .name, 162 | .name-th { 163 | font-size: 0.8em; 164 | } 165 | 166 | 167 | .reputation-th { 168 | font-size: 0.8em; 169 | margin-left: 180px; 170 | } 171 | .reputation { 172 | font-size: 0.8em; 173 | margin-left: 135px; 174 | } 175 | 176 | .profile-img { 177 | width: 40px; 178 | height: 40px; 179 | } 180 | footer { 181 | position: fixed; 182 | bottom: 0; 183 | width: 322.5px; 184 | } 185 | } -------------------------------------------------------------------------------- /config/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for config project. 3 | 4 | Generated by 'django-admin startproject' using Django 5.0.2. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/5.0/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'django-insecure-wi-l7c%1!zxj-+q$&5m^ypwaw==r6ykjvxo%%!!stt240sf_jh' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'profiles' 41 | ] 42 | 43 | MIDDLEWARE = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'django.contrib.sessions.middleware.SessionMiddleware', 46 | 'django.middleware.common.CommonMiddleware', 47 | 'django.middleware.csrf.CsrfViewMiddleware', 48 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 49 | 'django.contrib.messages.middleware.MessageMiddleware', 50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 51 | ] 52 | 53 | ROOT_URLCONF = 'config.urls' 54 | 55 | TEMPLATES = [ 56 | { 57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 58 | 'DIRS': [BASE_DIR / 'templates'], 59 | 'APP_DIRS': True, 60 | 'OPTIONS': { 61 | 'context_processors': [ 62 | 'django.template.context_processors.debug', 63 | 'django.template.context_processors.request', 64 | 'django.contrib.auth.context_processors.auth', 65 | 'django.contrib.messages.context_processors.messages', 66 | ], 67 | }, 68 | }, 69 | ] 70 | 71 | WSGI_APPLICATION = 'config.wsgi.application' 72 | 73 | 74 | # Database 75 | # https://docs.djangoproject.com/en/5.0/ref/settings/#databases 76 | 77 | DATABASES = { 78 | 'default': { 79 | 'ENGINE': 'django.db.backends.sqlite3', 80 | 'NAME': BASE_DIR / 'db.sqlite3', 81 | } 82 | } 83 | 84 | 85 | # Password validation 86 | # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators 87 | 88 | AUTH_PASSWORD_VALIDATORS = [ 89 | { 90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 91 | }, 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 100 | }, 101 | ] 102 | 103 | 104 | # Internationalization 105 | # https://docs.djangoproject.com/en/5.0/topics/i18n/ 106 | 107 | LANGUAGE_CODE = 'en-us' 108 | 109 | TIME_ZONE = 'UTC' 110 | 111 | USE_I18N = True 112 | 113 | USE_TZ = True 114 | 115 | 116 | # Static files (CSS, JavaScript, Images) 117 | # https://docs.djangoproject.com/en/5.0/howto/static-files/ 118 | 119 | STATIC_URL = 'static/' 120 | STATICFILES_DIRS = [BASE_DIR / 'static'] 121 | 122 | 123 | # Default primary key field type 124 | # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field 125 | 126 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 127 | -------------------------------------------------------------------------------- /templates/rank.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | Ranking Page 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | Username 16 | Reputation 17 |
18 |
19 | Rank 20 |
21 | {% for profile in profiles %} 22 | 23 | {% if profile.rank == 1 %} 24 |
25 |
26 | Another Jane's Profile Image 27 |
28 | {{ profile.username }} 29 | {{ profile.reputation_count }} 30 |
31 |
32 | {{ profile.rank }} 33 |
34 | {% elif profile.rank == 2 %} 35 |
36 |
37 | Another Jane's Profile Image 38 |
39 | {{ profile.username }} 40 | {{ profile.reputation_count }} 41 |
42 |
43 | {{ profile.rank }} 44 |
45 | {% elif profile.rank == 3 %} 46 |
47 |
48 | Another Jane's Profile Image 49 |
50 | {{ profile.username }} 51 | {{ profile.reputation_count }} 52 |
53 |
54 | {{ profile.rank }} 55 |
56 | {% elif profile.username == "DevOgabek" %} 57 |
58 |
59 | Another Jane's Profile Image 60 |
61 | {{ profile.username }} 62 | {{ profile.reputation_count }} 63 |
64 |
65 | {{ profile.rank }} 66 |
67 |
68 |
69 |
70 | Another Jane's Profile Image 71 |
72 | {{ profile.username }} 73 | {{ profile.reputation_count }} 74 |
75 |
76 | {{ profile.rank }} 77 |
78 |
79 | {% else %} 80 |
81 |
82 | Another Jane's Profile Image 83 |
84 | {{ profile.username }} 85 | {{ profile.reputation_count }} 86 |
87 |
88 | {{ profile.rank }} 89 |
90 | {% endif %} 91 |
92 | {% endfor %} 93 |
94 |
95 |
96 |
97 |
98 |
99 | 100 | 101 | 102 | --------------------------------------------------------------------------------