From 27721c5d2a21399b2fbb8d0ff00360b03fd870b5 Mon Sep 17 00:00:00 2001 From: Arth Date: Sun, 24 Sep 2023 21:46:33 +0530 Subject: [PATCH 1/2] broken logic --- cogs/daily_cp.py | 30 +++++++++++++++++++++++++++ main.py | 12 +++++++++++ utils/codeforces.py | 50 +++++++++++++++++++++++++++++++++++++++++++++ utils/env.py | 1 + utils/mongo.py | 7 +++++++ 5 files changed, 100 insertions(+) create mode 100644 cogs/daily_cp.py create mode 100644 utils/codeforces.py create mode 100644 utils/mongo.py diff --git a/cogs/daily_cp.py b/cogs/daily_cp.py new file mode 100644 index 0000000..576ffdd --- /dev/null +++ b/cogs/daily_cp.py @@ -0,0 +1,30 @@ +from discord.ext import commands +from discord import ApplicationContext +from codeforces_api import CodeforcesApi +from datetime import datetime +from utils.mongo import problems_collection + + +class DailyCP(commands.Cog): + def __init__(self, bot: commands.Bot): + self.bot = bot + self.cf_api = CodeforcesApi() + + @commands.slash_command(description="Get your daily challenge") + async def daily_cp(self, ctx: ApplicationContext): + user_id = ctx.author.id + dateAndTime = datetime.now() + date = dateAndTime.date() + today_problems = problems_collection.find_one( + {"discord_id": user_id, "date": date} + ) + if today_problems is not None: + given_problems = today_problems.problems + await ctx.respond( + f"problem 1 (same rating) - {given_problems[0].link}\nproblem 1 (highger rating) - {given_problems[1].link}" + ) + return + + +def setup(bot): + bot.add_cog(DailyCP(bot)) diff --git a/main.py b/main.py index 7bfa315..294360a 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,6 @@ from discord import ApplicationContext, Bot from utils.env import DISCORD_BOT_TOKEN +from utils.mongo import user_collection import os bot = Bot() @@ -15,6 +16,17 @@ async def on_ready(): print(f"Saini Certified is online.") +@bot.command(description="register for daily cp questions") +async def register(ctx: ApplicationContext): + if user_collection.find_one({"discord_id": ctx.author.id}) is not None: + await ctx.respond(f"Already Registered") + return + user_collection.insert_one( + {"discord_id": ctx.author.id, "discord_username": ctx.author.name} + ) + await ctx.respond("Registered!") + + for filename in os.listdir("./cogs"): if filename.endswith(".py"): bot.load_extension(f"cogs.{filename[:-3]}") diff --git a/utils/codeforces.py b/utils/codeforces.py new file mode 100644 index 0000000..f6c0227 --- /dev/null +++ b/utils/codeforces.py @@ -0,0 +1,50 @@ +from codeforces_api import CodeforcesApi +from requests import get + +cf_api = CodeforcesApi() + + +def has_successful_submission(user_data, contest_id, problem_index): + for submission in user_data["result"]: + if ( + submission["verdict"] == "OK" + and submission["problem"]["contestId"] == contest_id + and submission["problem"]["index"] == problem_index + ): + return True + + return False + + +def get_contest_standings(contest_id): + request_url = f"https://codeforces.com/api/contest.standings?contestId={contest_id}" + response = get(request_url) + response = response.json() + return response + + +def getTwoProblems(username, rating): + final_problems = [0, 0] + + url = f"https://codeforces.com/api/user.status?handle={username}" + response = get(url) + user_data = response.json() + + for contest in cf_api.contest_list(): + standings = get_contest_standings(contest.id) + if standings["status"] == "OK": + for problem in standings["result"]["problems"]: + if final_problems[0] != 0 and final_problems[1] != 0: + return final_problems + if "rating" in problem and not has_successful_submission( + user_data, contest.id, problem["index"] + ): + if final_problems[0] != 0 and problem["rating"] == rating: + final_problems[0] = problem + if final_problems[1] != 0 and problem["rating"] == rating + 200: + final_problems[1] = problem + + return final_problems + + +print(getTwoProblems("probablyarth", 800)) diff --git a/utils/env.py b/utils/env.py index fe3452e..80c4dd5 100644 --- a/utils/env.py +++ b/utils/env.py @@ -3,3 +3,4 @@ load_dotenv() DISCORD_BOT_TOKEN = environ.get("DISCORD_BOT_TOKEN") +MONGO_URI = environ.get("MONGO_URI") \ No newline at end of file diff --git a/utils/mongo.py b/utils/mongo.py new file mode 100644 index 0000000..50b38db --- /dev/null +++ b/utils/mongo.py @@ -0,0 +1,7 @@ +from pymongo import MongoClient, database +from .env import MONGO_URI + +client = MongoClient(MONGO_URI) +db = client.saini_certified +user_collection = db.users +problems_collection = db.problems From 1c0e055d07df221b7b05de6b700670785a979c88 Mon Sep 17 00:00:00 2001 From: Arth Date: Mon, 25 Sep 2023 00:00:21 +0530 Subject: [PATCH 2/2] finish --- cogs/daily_cp.py | 55 +++++++++++++++++++++++---- main.py | 8 +++- utils/codeforces.py | 90 ++++++++++++++++++++++----------------------- utils/env.py | 2 +- 4 files changed, 99 insertions(+), 56 deletions(-) diff --git a/cogs/daily_cp.py b/cogs/daily_cp.py index 576ffdd..1ad1ffa 100644 --- a/cogs/daily_cp.py +++ b/cogs/daily_cp.py @@ -1,8 +1,10 @@ from discord.ext import commands -from discord import ApplicationContext +from discord import Interaction, ApplicationContext from codeforces_api import CodeforcesApi from datetime import datetime -from utils.mongo import problems_collection +from utils.mongo import problems_collection, user_collection +from utils.codeforces import getTwoProblems +from requests import get class DailyCP(commands.Cog): @@ -11,19 +13,56 @@ def __init__(self, bot: commands.Bot): self.cf_api = CodeforcesApi() @commands.slash_command(description="Get your daily challenge") - async def daily_cp(self, ctx: ApplicationContext): + async def daily_cp(self, ctx: Interaction | ApplicationContext): + await ctx.response.defer() user_id = ctx.author.id dateAndTime = datetime.now() - date = dateAndTime.date() + date = dateAndTime.strftime("%d/%m/%Y") + user_obj = user_collection.find_one({"discord_id": user_id}) + if user_obj is None: + await ctx.respond("First you need to register using `/register` command") today_problems = problems_collection.find_one( {"discord_id": user_id, "date": date} ) if today_problems is not None: - given_problems = today_problems.problems - await ctx.respond( - f"problem 1 (same rating) - {given_problems[0].link}\nproblem 1 (highger rating) - {given_problems[1].link}" - ) + given_problems = today_problems["problems"] + msg = f"problem 1 - {given_problems[0]['link']}\nproblem 1 - {given_problems[1]['link']}" + await ctx.respond(msg) return + username = user_obj["username"] + url = f"https://codeforces.com/api/user.info?handles={username}" + formatted_response = get(url) + if formatted_response.status_code != 200: + await ctx.respond("Oopsie, an error occurred") + return + try: + data = formatted_response.json() + except ValueError: + await ctx.respond("Oopsie, an error occurred") + return + if "rating" not in data["result"][0]: + await ctx.respond("Skill Issue: you are unrated") + return + new_problems = getTwoProblems(username, data["result"][0]["rating"]) + new_problems_doc = { + "discord_id": user_id, + "problems": [ + { + "contestId": new_problems[0]["contestId"], + "index": new_problems[0]["index"], + "link": f"https://codeforces.com/problemset/problem/{new_problems[0]['contestId']}/{new_problems[0]['index']}", + }, + { + "contestId": new_problems[1]["contestId"], + "index": new_problems[1]["index"], + "link": f"https://codeforces.com/problemset/problem/{new_problems[1]['contestId']}/{new_problems[1]['index']}", + }, + ], + "date": date, + } + problems_collection.insert_one(new_problems_doc) + msg = f"problem 1 - {new_problems_doc['problems'][0]['link']}\nproblem 2 - {new_problems_doc['problems'][1]['link']}" + await ctx.respond(msg) def setup(bot): diff --git a/main.py b/main.py index 294360a..272b63d 100644 --- a/main.py +++ b/main.py @@ -17,12 +17,16 @@ async def on_ready(): @bot.command(description="register for daily cp questions") -async def register(ctx: ApplicationContext): +async def register(ctx: ApplicationContext, username: str): if user_collection.find_one({"discord_id": ctx.author.id}) is not None: await ctx.respond(f"Already Registered") return user_collection.insert_one( - {"discord_id": ctx.author.id, "discord_username": ctx.author.name} + { + "discord_id": ctx.author.id, + "discord_username": ctx.author.name, + "username": username, + } ) await ctx.respond("Registered!") diff --git a/utils/codeforces.py b/utils/codeforces.py index f6c0227..705d26e 100644 --- a/utils/codeforces.py +++ b/utils/codeforces.py @@ -1,50 +1,50 @@ -from codeforces_api import CodeforcesApi -from requests import get +import requests -cf_api = CodeforcesApi() - -def has_successful_submission(user_data, contest_id, problem_index): - for submission in user_data["result"]: +def getTwoProblems(username, rating): + rounded_rating = round(rating / 100) * 100 + higher_rating = rounded_rating + 200 + + submissions_url = ( + f"https://codeforces.com/api/user.status?handle={username}&from=1&count=1000000" + ) + response = requests.get(submissions_url) + data = response.json() + if data["status"] != "OK": + return [] + + solved_problems = set() + for submission in data["result"]: + if submission["verdict"] == "OK": + problem_id = ( + submission["problem"]["contestId"], + submission["problem"]["index"], + ) + solved_problems.add(problem_id) + + problems_url = "https://codeforces.com/api/problemset.problems" + response = requests.get(problems_url) + data = response.json() + if data["status"] != "OK": + return [] + + selected_problems = [] + for problem in data["result"]["problems"]: + if "rating" not in problem: + continue if ( - submission["verdict"] == "OK" - and submission["problem"]["contestId"] == contest_id - and submission["problem"]["index"] == problem_index + problem["rating"] == rounded_rating + and (problem["contestId"], problem["index"]) not in solved_problems ): - return True - - return False - - -def get_contest_standings(contest_id): - request_url = f"https://codeforces.com/api/contest.standings?contestId={contest_id}" - response = get(request_url) - response = response.json() - return response - - -def getTwoProblems(username, rating): - final_problems = [0, 0] - - url = f"https://codeforces.com/api/user.status?handle={username}" - response = get(url) - user_data = response.json() - - for contest in cf_api.contest_list(): - standings = get_contest_standings(contest.id) - if standings["status"] == "OK": - for problem in standings["result"]["problems"]: - if final_problems[0] != 0 and final_problems[1] != 0: - return final_problems - if "rating" in problem and not has_successful_submission( - user_data, contest.id, problem["index"] - ): - if final_problems[0] != 0 and problem["rating"] == rating: - final_problems[0] = problem - if final_problems[1] != 0 and problem["rating"] == rating + 200: - final_problems[1] = problem - - return final_problems - + selected_problems.append(problem) + if len(selected_problems) == 2: + break + elif ( + problem["rating"] == higher_rating + and (problem["contestId"], problem["index"]) not in solved_problems + ): + selected_problems.append(problem) + if len(selected_problems) == 2: + break -print(getTwoProblems("probablyarth", 800)) + return selected_problems diff --git a/utils/env.py b/utils/env.py index 80c4dd5..325dd57 100644 --- a/utils/env.py +++ b/utils/env.py @@ -3,4 +3,4 @@ load_dotenv() DISCORD_BOT_TOKEN = environ.get("DISCORD_BOT_TOKEN") -MONGO_URI = environ.get("MONGO_URI") \ No newline at end of file +MONGO_URI = environ.get("MONGO_URI")