Skip to content

Commit

Permalink
Initializing the repo
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohab Yaser committed Nov 5, 2023
1 parent e78e8b2 commit c835c55
Show file tree
Hide file tree
Showing 4 changed files with 391 additions and 0 deletions.
95 changes: 95 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Codeforces Problem Selector</title>
</head>
<body>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<div class="tags-container">
<button class="tag-btn">2-sat</button>
<button class="tag-btn">binary search</button>
<button class="tag-btn">bitmasks</button>
<button class="tag-btn">brute force</button>
<button class="tag-btn">combinatorics</button>
<button class="tag-btn">constructive algorithms</button>
<button class="tag-btn">data structures</button>
<button class="tag-btn">dfs and similar</button>
<button class="tag-btn">divide and conquer</button>
<button class="tag-btn">dp</button>
<button class="tag-btn">dsu</button>
<button class="tag-btn">expression parsing</button>
<button class="tag-btn">fft</button>
<button class="tag-btn">flow</button>
<button class="tag-btn">games</button>
<button class="tag-btn">geometry</button>
<button class="tag-btn">graph matchings</button>
<button class="tag-btn">graphs</button>
<button class="tag-btn">greedy</button>
<button class="tag-btn">hashing</button>
<button class="tag-btn">implementation</button>
<button class="tag-btn">interactive</button>
<button class="tag-btn">math</button>
<button class="tag-btn">matrices</button>
<button class="tag-btn">number theory</button>
<button class="tag-btn">probability</button>
<button class="tag-btn">schedules</button>
<button class="tag-btn">shortest path</button>
<button class="tag-btn">sorting</button>
<button class="tag-btn">strings</button>
<button class="tag-btn">ternary search</button>
<button class="tag-btn">trees</button>
<button class="tag-btn">two pointers</button>
</div>
<div class="slider-container">
<label for="rating" class="rating-label">Rating 800 - 3500</label>
<input type="range" class="rating" id="rating" min="800" max="3500"step="100">
</div>
<div class="handles-container">
<label for="handles" class="handles-label">Handles (not solved by)</label>
<input type="text" id="handles" placeholder=" Enter codeforces handles">
<button class="add-handle-btn">Add</button>
<div class="accepted-handles">
<!-- TODO -->
<div class="accepted-handles-container"></div>
</div>
<span style="margin-left: 600px;">* to remove a handle, click on it</span>
</div>
<div class="problems-container">
<div class="problem"></div>
</div>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<script src="main.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</body>
</html>
59 changes: 59 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// const Swal = require('sweetalert2')
// import Swal from 'sweetalert2'


let btns = document.getElementsByClassName('tag-btn');

for (let i = 0; i < btns.length; i++) {
let element = btns[i];
let green = "rgb(51, 172, 113)";
let blue = "rgb(0, 188, 212)";

element.style.backgroundColor = blue;

element.addEventListener("click",
() => {
if (element.style.backgroundColor == blue) {
// Include
element.style.backgroundColor = green;
} else {
// Exclude
element.style.backgroundColor = blue;
}
}
);
}

let rating_slider = document.getElementById('rating');

rating_slider.addEventListener("change",
() => {
// console.log(rating_slider.value);
});

function valid_handle(handle) {
if (handle == '')
return false;

let url = `https://codeforces.com/api/user.status?handle=${handle}`;
return true;
}

let add_handle_btn = document.getElementsByClassName('add-handle-btn')[0];

add_handle_btn.addEventListener('click',
() => {
let handle = document.getElementById('handles').value;

if (valid_handle(handle)) {

} else {
// Swal.fire({
// title: 'Error!',
// text: 'Invalid Codefroces Handle',
// icon: 'error',
// confirmButtonText: 'Try again'
// });
alert('Invalid Codeforces Handle');
}
});
136 changes: 136 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import requests
import random
import webbrowser
import argparse

# handles to choose problems not problems not solved by any one of them
not_solved_by = ['wrong_handle']

# problems not solved by any handle in "not_solved_by"
problems_out_of_scope = set([])


def remove_solved_problems():
# extracting all the problems solved by all handles in "not_solved_by"
for handle in not_solved_by:
user = f'https://codeforces.com/api/user.status?handle={handle}'
submissions = requests.get(user).json()
if submissions.get('status') != 'FAILED':
for submission in submissions['result']:
if submission.get('verdict') == 'OK':
problems_out_of_scope.add(
submission.get('problem').get('name'))


DEFAULT_MIN_RATE = 1300
DEFAULT_MAX_RATE = 1500
DEFAULT_PROBLEMS_CNT = 1


def get_args():
parser = argparse.ArgumentParser()

parser.add_argument("-o", "--open",
help="Whether you want the problems to be opened directly in your browser or not [y/n].",
type=str, default=False)

parser.add_argument("-c", "--count",
help="The number of problems you wanna get.",
type=int, default=DEFAULT_PROBLEMS_CNT)

parser.add_argument("-mn", "--minRate",
help="The rate that you don't want to get any problems with rate less than it.",
type=int, default=DEFAULT_MIN_RATE)

parser.add_argument("-mx", "--maxRate",
help="The rate that you don't want to get any problems with rate more than it.",
type=int, default=DEFAULT_MAX_RATE)

args = parser.parse_args()

return args


available_problems = []

url = 'https://codeforces.com/api/problemset.problems'
problemset = requests.get(url).json()

# tags that I want to see one or more of them in all problems (and only them)
desired_tags = ['binary search',
'bitmasks',
'brute force',
'combinatorics',
'constructive algorithms',
'data structures',
'dfs and similar',
'dp',
'dsu',
'graphs',
'greedy',
'implementation',
'math',
'number theory',
'ternary search',
'trees',
'two pointers',
'sortings'
]


def valid(problem, min, max):
# if solved by any user in "not_solved_by"
if problem.get('name') in problems_out_of_scope:
return False

rate = problem.get('rating', 0)

# if the rate is not in the desired rage
if rate < min or rate > max:
return False

# if it have any tag that I don't want
for tag in problem.get('tags'):
if tag not in desired_tags:
return False
return True


def filter_problems(min=DEFAULT_MIN_RATE, max=DEFAULT_MAX_RATE):
for problem in problemset['result']['problems']:
if valid(problem, min, max):
available_problems.append(problem)


def get_the_problems(problems_cnt=DEFAULT_PROBLEMS_CNT, open=False):
random.shuffle(available_problems)

for i in range(problems_cnt):
index = str(available_problems[i].get('index'))
contestID = available_problems[i].get('contestId')

link = f'https://codeforces.com/contest/{contestID}/problem/{index}'

print(link)

if open:
webbrowser.open(link)


if __name__ == '__main__':
remove_solved_problems()
args = get_args()

mn = args.__dict__['minRate']
mx = args.__dict__['maxRate']
cnt = args.__dict__['count']
opn = args.__dict__['open']

assert cnt > 0, 'Enter a positive number of problems'
assert mn >= 800 and mn <= 3500, 'Enter a min rating between 800 and 3500'
assert mx >= 800 and mx <= 3500, 'Enter a max rating between 800 and 3500'
assert mn <= mx, 'The max is less than min'
assert opn == 'y' or opn == 'n', "Enter \'y\' or \'n\'"

filter_problems(mn, mx)
get_the_problems(cnt, True if opn == 'y' else False)
101 changes: 101 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
body {
display: flex;
flex-direction: column;
}

.tags-container {
border: solid 2.5px;
border-color: lightgrey;
border-radius: 5px;
padding: 7px;
}

.tag-btn {
background-color: rgb(0, 188, 212);
border: 0px;
padding: 8px;
color: white;
font-weight: bold;
font-size: 18px;
border-radius: 5px;
font-family: arial;
cursor: pointer;
margin: 4px;
transition: 0.5s;
}

/*.tag-btn:hover {
background-color: rgb(215 208 54);
}*/

.slider-container{
margin-top: 10px;
margin-bottom: 10px;
}

.rating-label {
font-weight: bold;
font-family: sans-serif;
font-size: 18px;
}

.handles-label {
font-weight: bold;
font-family: sans-serif;
font-size: 18px;
}

.add-handle-btn {
background-color: #00ff4c;
border: 0px;
border-radius: 3px;
padding: 7px 12px;
color: white;
font-weight: bold;
font-family: sans-serif;
font-size: 16px;
cursor: pointer;
transition: 0.5s;
}

.add-handle-btn:hover {
background-color: #16a942;
}

#handles {
height: 25px;
border: 3px solid lightgrey;
border-radius: 6px;
}

input {
font-size: 20px;
}

.handles-container {

}

.accepted-handles {
margin-top: 10px;
border: 4px solid grey;
border-radius: 10px;
padding: 10px;
}

.accepted-handles-container {
margin-top: 10px;
border: 4px solid grey;
border-radius: 10px;
padding: 10px;
width: 120px;
height: 15px;
}

.problems-container {

}

.problem {

}

0 comments on commit c835c55

Please sign in to comment.