chefmate 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chefmate/__init__.py +0 -0
- chefmate/browser_manager.py +70 -0
- chefmate/chefmate_core.py +1536 -0
- chefmate/cli.py +275 -0
- chefmate/config.py +64 -0
- chefmate-1.0.0.dist-info/METADATA +313 -0
- chefmate-1.0.0.dist-info/RECORD +11 -0
- chefmate-1.0.0.dist-info/WHEEL +5 -0
- chefmate-1.0.0.dist-info/entry_points.txt +2 -0
- chefmate-1.0.0.dist-info/licenses/LICENSE +21 -0
- chefmate-1.0.0.dist-info/top_level.txt +1 -0
chefmate/cli.py
ADDED
@@ -0,0 +1,275 @@
|
|
1
|
+
# cli.py
|
2
|
+
import os
|
3
|
+
import sys
|
4
|
+
import click
|
5
|
+
import time
|
6
|
+
import platform
|
7
|
+
import colorama
|
8
|
+
import threading
|
9
|
+
from colorama import Fore
|
10
|
+
from chefmate.chefmate_core import ChefMate
|
11
|
+
from InquirerPy import inquirer
|
12
|
+
from InquirerPy.base.control import Choice
|
13
|
+
from rich import box
|
14
|
+
from rich.text import Text
|
15
|
+
from rich.table import Table
|
16
|
+
from rich.console import Console
|
17
|
+
|
18
|
+
colorama.init(autoreset=True)
|
19
|
+
console = Console()
|
20
|
+
|
21
|
+
def hide_cursor():
|
22
|
+
sys.stdout.write("\033[?25l")
|
23
|
+
sys.stdout.flush()
|
24
|
+
|
25
|
+
def show_cursor():
|
26
|
+
sys.stdout.write("\033[?25h")
|
27
|
+
sys.stdout.flush()
|
28
|
+
|
29
|
+
def loading_animation(stop_event):
|
30
|
+
while not stop_event.is_set():
|
31
|
+
for i in range(4):
|
32
|
+
if stop_event.is_set():
|
33
|
+
break
|
34
|
+
sys.stdout.write(f"\r{Fore.YELLOW} Loading {'.' * i} ")
|
35
|
+
sys.stdout.flush()
|
36
|
+
time.sleep(0.25)
|
37
|
+
|
38
|
+
def clear_terminal():
|
39
|
+
"""Clears the terminal screen based on the OS"""
|
40
|
+
os.system('cls' if platform.system() == 'Windows' else 'clear')
|
41
|
+
print(f"{Fore.GREEN} Terminal cleared successfully! \u2714\n")
|
42
|
+
|
43
|
+
@click.group()
|
44
|
+
def cli():
|
45
|
+
"""ChefMate - CodeChef Automation Tool"""
|
46
|
+
pass
|
47
|
+
|
48
|
+
@cli.command()
|
49
|
+
def setup():
|
50
|
+
"""Configure ChefMate settings"""
|
51
|
+
cm = ChefMate()
|
52
|
+
cm.setup()
|
53
|
+
|
54
|
+
@cli.command()
|
55
|
+
def login():
|
56
|
+
"""Login to CodeChef"""
|
57
|
+
cm = ChefMate()
|
58
|
+
if cm.initialize():
|
59
|
+
cm.login()
|
60
|
+
else:
|
61
|
+
click.echo(f"{Fore.RED} Failed to initialize browser.")
|
62
|
+
|
63
|
+
@cli.command()
|
64
|
+
def logout():
|
65
|
+
"""Logout from CodeChef"""
|
66
|
+
cm = ChefMate()
|
67
|
+
if cm.initialize():
|
68
|
+
cm.logout()
|
69
|
+
else:
|
70
|
+
click.echo(f"{Fore.RED} Failed to initialize browser.")
|
71
|
+
|
72
|
+
@cli.command()
|
73
|
+
@click.option('--problem', '-p', type=int, help='Problem number to check')
|
74
|
+
def check(problem):
|
75
|
+
"""Check sample test cases for a problem"""
|
76
|
+
cm = ChefMate()
|
77
|
+
if cm.initialize() and cm.login():
|
78
|
+
if cm.open_contest():
|
79
|
+
cm.demo_cases_check(problem)
|
80
|
+
else:
|
81
|
+
click.echo(f"{Fore.RED} Failed to initialize session.")
|
82
|
+
|
83
|
+
@cli.command()
|
84
|
+
@click.option('--problem', '-p', type=int, help='Problem number to submit')
|
85
|
+
def submit(problem):
|
86
|
+
"""Submit solution for a problem"""
|
87
|
+
cm = ChefMate()
|
88
|
+
if cm.initialize() and cm.login():
|
89
|
+
if cm.open_contest():
|
90
|
+
cm.submit_solution(problem)
|
91
|
+
else:
|
92
|
+
click.echo(f"{Fore.RED} Failed to initialize session.")
|
93
|
+
|
94
|
+
@cli.command()
|
95
|
+
def contest():
|
96
|
+
"""Open a contest and load problems"""
|
97
|
+
cm = ChefMate()
|
98
|
+
if cm.initialize() and cm.login():
|
99
|
+
cm.open_contest()
|
100
|
+
else:
|
101
|
+
click.echo(f"{Fore.RED} Failed to initialize session.")
|
102
|
+
# -------------------- Interactive Mode ------------------
|
103
|
+
@cli.command()
|
104
|
+
def interactive():
|
105
|
+
"""Run ChefMate in interactive mode"""
|
106
|
+
cm = ChefMate()
|
107
|
+
|
108
|
+
cm.display_logo()
|
109
|
+
|
110
|
+
click.echo("\n" + f"{Fore.CYAN}=" * 50)
|
111
|
+
click.echo(f"{Fore.CYAN}ChefMate Interactive Mode")
|
112
|
+
click.echo(f"{Fore.CYAN}=" * 50)
|
113
|
+
|
114
|
+
try:
|
115
|
+
hide_cursor()
|
116
|
+
stop_event = threading.Event()
|
117
|
+
loading_thread = threading.Thread(target=loading_animation, args=(stop_event,))
|
118
|
+
loading_thread.start()
|
119
|
+
|
120
|
+
first_login = False
|
121
|
+
if not cm.config.get("username", "") or not cm.config.get("password", "") or not cm.config.get("solution_path", ""):
|
122
|
+
stop_event.set()
|
123
|
+
loading_thread.join()
|
124
|
+
sys.stdout.write("\r")
|
125
|
+
sys.stdout.flush()
|
126
|
+
print(f"{Fore.CYAN} We need to configure first.")
|
127
|
+
first_login = True
|
128
|
+
cm.setup()
|
129
|
+
|
130
|
+
if not cm.initialize():
|
131
|
+
stop_event.set()
|
132
|
+
loading_thread.join()
|
133
|
+
sys.stdout.write("\r")
|
134
|
+
sys.stdout.flush()
|
135
|
+
click.echo(f"{Fore.RED} Failed to initialize browser.")
|
136
|
+
cm.quit()
|
137
|
+
return
|
138
|
+
|
139
|
+
stop_event.set()
|
140
|
+
loading_thread.join()
|
141
|
+
sys.stdout.write("\r")
|
142
|
+
sys.stdout.flush()
|
143
|
+
finally: show_cursor()
|
144
|
+
|
145
|
+
quest_list = [
|
146
|
+
Choice(value="_login", name="Login"),
|
147
|
+
Choice(value="_logout", name="Logout"),
|
148
|
+
Choice(value="_exit", name="Exit"),
|
149
|
+
Choice(value="_contest_ini", name="Open Contest"),
|
150
|
+
Choice(value="_solve", name="Solve Problems"),
|
151
|
+
Choice(value="_demo", name="Check Demo test cases"),
|
152
|
+
Choice(value="_submit", name="Submit Solution"),
|
153
|
+
Choice(value="_reconfig", name="Re-configure ChefMate"),
|
154
|
+
Choice(value="_log_and_ex", name="Logout and Exit"),
|
155
|
+
Choice(value="_clear", name="Clear Terminal"),
|
156
|
+
]
|
157
|
+
|
158
|
+
current_choice = "_login" # Set a default starting choice
|
159
|
+
|
160
|
+
while True:
|
161
|
+
choice = inquirer.select(
|
162
|
+
message="Select an option: ",
|
163
|
+
choices=quest_list,
|
164
|
+
default=current_choice, # Use the stored current choice
|
165
|
+
qmark="", # Remove the default [?]
|
166
|
+
pointer=">", # Custom arrow pointer
|
167
|
+
instruction="(Use arrow keys to navigate)"
|
168
|
+
).execute()
|
169
|
+
|
170
|
+
# Update the current choice for next iteration
|
171
|
+
current_choice = choice
|
172
|
+
|
173
|
+
print("\033[F\033[2K", end="")
|
174
|
+
selected_name = next((c.name for c in quest_list if c.value == choice), choice)
|
175
|
+
table = Table(show_header=False, box=box.ROUNDED, border_style='green')
|
176
|
+
|
177
|
+
# Create a Text object with styling for selected name
|
178
|
+
styled_text = Text("You Selected: ")
|
179
|
+
styled_text.append(selected_name, style="cyan")
|
180
|
+
|
181
|
+
table.add_row(styled_text)
|
182
|
+
console.print(table)
|
183
|
+
|
184
|
+
if choice == '_login':
|
185
|
+
if first_login:
|
186
|
+
cm.login(first_login=True)
|
187
|
+
else: cm.login()
|
188
|
+
elif choice == '_logout': cm.logout()
|
189
|
+
elif choice == '_config': cm.setup()
|
190
|
+
elif choice == '_clear': clear_terminal()
|
191
|
+
elif choice == '_contest_ini':
|
192
|
+
quest_list.pop(3)
|
193
|
+
quest_list.insert(3, Choice(value="_track_problelm", name="Problem Tracker"))
|
194
|
+
quest_list.insert(4, Choice(value="_close_curr_cont", name="Close Current Contest"))
|
195
|
+
quest_list.insert(5, Choice(value="_contest_again", name="Open another Contest"))
|
196
|
+
cm.open_contest()
|
197
|
+
elif choice == '_solve': cm.solve()
|
198
|
+
elif choice == '_reconfig': cm.reconfig()
|
199
|
+
elif choice == '_submit': cm.submit_solution()
|
200
|
+
elif choice == '_demo': cm.demo_cases_check()
|
201
|
+
elif choice == '_exit':
|
202
|
+
cm.quit()
|
203
|
+
break
|
204
|
+
elif choice == '_log_and_ex':
|
205
|
+
cm.logout()
|
206
|
+
cm.quit()
|
207
|
+
break
|
208
|
+
elif choice == '_close_curr_cont':
|
209
|
+
# Close all problem tabs
|
210
|
+
if cm.tabs and len(cm.tabs) > 1:
|
211
|
+
cm.browser.driver.switch_to.window(cm.tabs[0])
|
212
|
+
|
213
|
+
for tab in cm.tabs[1:]:
|
214
|
+
cm.browser.driver.switch_to.window(tab)
|
215
|
+
cm.browser.driver.close()
|
216
|
+
|
217
|
+
cm.tabs = [cm.tabs[0]]
|
218
|
+
cm.browser.driver.switch_to.window(cm.tabs[0])
|
219
|
+
print(f"{Fore.GREEN} Closed contest tabs successfully! \u2714")
|
220
|
+
|
221
|
+
dashboard_text = " Loading Dashboard now ..."
|
222
|
+
for char in dashboard_text:
|
223
|
+
sys.stdout.write(Fore.YELLOW + char)
|
224
|
+
sys.stdout.flush()
|
225
|
+
time.sleep(0.04)
|
226
|
+
|
227
|
+
sys.stdout.write('\n')
|
228
|
+
cm.goto_dashboard()
|
229
|
+
|
230
|
+
quest_list.pop(4)
|
231
|
+
quest_list.pop(3)
|
232
|
+
quest_list.insert(3, Choice(value="_contest_ini", name="Open Contest"))
|
233
|
+
|
234
|
+
# Reset problems list
|
235
|
+
cm.problems = []
|
236
|
+
|
237
|
+
# Reset contest ID and directory
|
238
|
+
cm.contest_id = None
|
239
|
+
cm.contest_dir = None
|
240
|
+
elif choice == '_track_problelm':
|
241
|
+
cm.show_tracker()
|
242
|
+
elif choice == '_contest_again':
|
243
|
+
# Close all problem tabs except the first one (contest page)
|
244
|
+
if cm.tabs and len(cm.tabs) > 1:
|
245
|
+
# Switch to first tab (contest page)
|
246
|
+
cm.browser.driver.switch_to.window(cm.tabs[0])
|
247
|
+
|
248
|
+
# Close all problem tabs
|
249
|
+
for tab in cm.tabs[1:]:
|
250
|
+
cm.browser.driver.switch_to.window(tab)
|
251
|
+
cm.browser.driver.close()
|
252
|
+
|
253
|
+
# Reset tabs list to only include the first tab
|
254
|
+
cm.tabs = [cm.tabs[0]]
|
255
|
+
cm.browser.driver.switch_to.window(cm.tabs[0])
|
256
|
+
print(f"{Fore.GREEN} Closed previous contest tabs successfully! \u2714")
|
257
|
+
|
258
|
+
# Reset problems list
|
259
|
+
cm.problems = []
|
260
|
+
|
261
|
+
# Reset contest ID and directory
|
262
|
+
cm.contest_id = None
|
263
|
+
cm.contest_dir = None
|
264
|
+
|
265
|
+
# Open new contest
|
266
|
+
cm.open_contest()
|
267
|
+
else: click.echo(f"{Fore.RED} Invalid choice!")
|
268
|
+
# --------------------------------------------------------
|
269
|
+
|
270
|
+
cli.add_command(interactive)
|
271
|
+
|
272
|
+
# ------ Main Script -------
|
273
|
+
if __name__ == "__main__":
|
274
|
+
interactive()
|
275
|
+
# --------------------------
|
chefmate/config.py
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# config.py
|
2
|
+
import os
|
3
|
+
import json
|
4
|
+
|
5
|
+
DEFAULT_CONFIG_DIR = os.path.join(os.path.expanduser("~"), ".chefmate")
|
6
|
+
DEFAULT_CONFIG_FILE = os.path.join(DEFAULT_CONFIG_DIR, "config.json")
|
7
|
+
|
8
|
+
class Config:
|
9
|
+
"""Configuration manager for ChefMate"""
|
10
|
+
|
11
|
+
def __init__(self, config_file=DEFAULT_CONFIG_FILE):
|
12
|
+
self.config_file = config_file
|
13
|
+
self.config = self.load_config()
|
14
|
+
|
15
|
+
def load_config(self):
|
16
|
+
"""Load configuration from file or create default"""
|
17
|
+
if not os.path.exists(os.path.dirname(self.config_file)):
|
18
|
+
os.makedirs(os.path.dirname(self.config_file))
|
19
|
+
|
20
|
+
if os.path.exists(self.config_file):
|
21
|
+
try:
|
22
|
+
with open(self.config_file, 'r') as f:
|
23
|
+
return json.load(f)
|
24
|
+
except json.JSONDecodeError:
|
25
|
+
print(f"Error: Config file {self.config_file} is corrupted. Creating new config.")
|
26
|
+
return self.create_default_config()
|
27
|
+
else:
|
28
|
+
return self.create_default_config()
|
29
|
+
|
30
|
+
def create_default_config(self):
|
31
|
+
"""Create default configuration"""
|
32
|
+
pc_username = os.getlogin()
|
33
|
+
config = {
|
34
|
+
"username": "",
|
35
|
+
"password": "",
|
36
|
+
"preferred_language": "",
|
37
|
+
"solution_path": "",
|
38
|
+
"chrome_user_data_dir": fr"C:\\Users\\{pc_username}\\AppData\\Local\\Google\\Chrome\\User Data",
|
39
|
+
"chrome_profile": "Default",
|
40
|
+
"preferred_editor": ""
|
41
|
+
}
|
42
|
+
self.save_config(config)
|
43
|
+
return config
|
44
|
+
|
45
|
+
def save_config(self, config=None):
|
46
|
+
"""Save configuration to file"""
|
47
|
+
if config is None:
|
48
|
+
config = self.config
|
49
|
+
with open(self.config_file, 'w') as f:
|
50
|
+
json.dump(config, f, indent=4)
|
51
|
+
|
52
|
+
def update_config(self, **kwargs):
|
53
|
+
"""Update configuration with provided values"""
|
54
|
+
self.config.update(kwargs)
|
55
|
+
self.save_config()
|
56
|
+
|
57
|
+
def get(self, key, default=None):
|
58
|
+
"""Get configuration value"""
|
59
|
+
return self.config.get(key, default)
|
60
|
+
|
61
|
+
def set(self, key, value):
|
62
|
+
"""Set configuration value"""
|
63
|
+
self.config[key] = value
|
64
|
+
self.save_config()
|
@@ -0,0 +1,313 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: chefmate
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: A CodeChef automation CLI tool
|
5
|
+
Home-page: https://github.com/Anuj-72/ChefMate
|
6
|
+
Author: Anuj Kumar Sah
|
7
|
+
Author-email: anujsah282005@gmail.com
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Requires-Python: >=3.7
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
License-File: LICENSE
|
14
|
+
Requires-Dist: selenium
|
15
|
+
Requires-Dist: webdriver-manager
|
16
|
+
Requires-Dist: click
|
17
|
+
Requires-Dist: colorama
|
18
|
+
Requires-Dist: inquirer
|
19
|
+
Requires-Dist: InquirerPy
|
20
|
+
Requires-Dist: rich
|
21
|
+
Requires-Dist: tabulate
|
22
|
+
Requires-Dist: pandas
|
23
|
+
Dynamic: author
|
24
|
+
Dynamic: author-email
|
25
|
+
Dynamic: classifier
|
26
|
+
Dynamic: description
|
27
|
+
Dynamic: description-content-type
|
28
|
+
Dynamic: home-page
|
29
|
+
Dynamic: license-file
|
30
|
+
Dynamic: requires-dist
|
31
|
+
Dynamic: requires-python
|
32
|
+
Dynamic: summary
|
33
|
+
|
34
|
+
# ChefMate
|
35
|
+
|
36
|
+
ChefMate is an automation tool designed to simplify and streamline your CodeChef contest participation. It leverages browser automation (using Selenium and ChromeDriver) along with a versatile command-line interface (CLI) to handle tasks such as logging in, contest management, problem scraping, solution submissions, and demo test case validations. ChefMate also helps set up directories and template files so that you can focus on solving problems quickly and efficiently.
|
37
|
+
|
38
|
+
---
|
39
|
+
|
40
|
+
## Table of Contents
|
41
|
+
|
42
|
+
- [Introduction](#introduction)
|
43
|
+
- [Features](#features)
|
44
|
+
- [Architecture and Code Structure](#architecture-and-code-structure)
|
45
|
+
- [Browser Manager (`browser_manager.py`)](#browser-manager)
|
46
|
+
- [Core Functionality (`chefmate_core.py`)](#core-functionality)
|
47
|
+
- [Command Line Interface (`cli.py`)](#command-line-interface)
|
48
|
+
- [Configuration Management (`config.py`)](#configuration-management)
|
49
|
+
- [Installation](#installation)
|
50
|
+
- [Usage](#usage)
|
51
|
+
- [Setup](#setup)
|
52
|
+
- [Login and Logout](#login-and-logout)
|
53
|
+
- [Contest and Problem Management](#contest-and-problem-management)
|
54
|
+
- [Testing and Submissions](#testing-and-submissions)
|
55
|
+
- [Interactive Mode](#interactive-mode)
|
56
|
+
- [Dependencies](#dependencies)
|
57
|
+
- [Troubleshooting](#troubleshooting)
|
58
|
+
- [Future Improvements](#future-improvements)
|
59
|
+
- [License](#license)
|
60
|
+
|
61
|
+
---
|
62
|
+
|
63
|
+
## Introduction
|
64
|
+
|
65
|
+
ChefMate is built to help competitive programmers who participate in CodeChef contests. By automating several routine tasks (such as logging in, opening contest pages, fetching problems, and managing solution submissions), ChefMate removes friction from the contest environment. With its modular design, the tool offers easy configurability and a friendly CLI interface, making the CodeChef contest experience smoother and more productive.
|
66
|
+
|
67
|
+
---
|
68
|
+
|
69
|
+
## Features
|
70
|
+
|
71
|
+
- **Browser Management:**
|
72
|
+
- Detects and prevents conflicts with existing Chrome sessions.
|
73
|
+
- Initializes a ChromeDriver with custom profiles and directories.
|
74
|
+
- Configurable options to bypass common Chrome logging and automation detections.
|
75
|
+
|
76
|
+
- **Automated Contest Interaction:**
|
77
|
+
- Logs into CodeChef and navigates to the contest dashboard.
|
78
|
+
- Opens contest pages and scrapes problem links and details.
|
79
|
+
- Provides an interactive problem tracker to monitor submission statuses.
|
80
|
+
|
81
|
+
- **Solution Management:**
|
82
|
+
- Creates and manages solution directories for contests.
|
83
|
+
- Generates template solution files in your preferred programming language.
|
84
|
+
- Facilitates opening solution files in your favorite code editor.
|
85
|
+
|
86
|
+
- **Submission and Testing:**
|
87
|
+
- Automates the process of selecting the language from the CodeChef UI.
|
88
|
+
- Loads solutions from files and submits them via the browser.
|
89
|
+
- Runs sample test cases to verify outputs before actual submission.
|
90
|
+
- Displays detailed verdict tables and highlights errors.
|
91
|
+
|
92
|
+
- **Command-Line Interface (CLI):**
|
93
|
+
- Offers a range of commands (setup, login, logout, contest, submit, check, interactive mode).
|
94
|
+
- Provides an intuitive interactive mode with a clear menu-driven experience.
|
95
|
+
- Uses libraries such as Click and InquirerPy for enhanced user interaction.
|
96
|
+
|
97
|
+
- **Configuration Management:**
|
98
|
+
- Manages user settings (username, password, solution paths, preferred language, Chrome profile, editor preferences) through a JSON configuration file stored in the user's home directory.
|
99
|
+
- Ensures persistence and easy updates of user configuration.
|
100
|
+
|
101
|
+
---
|
102
|
+
|
103
|
+
## Architecture and Code Structure
|
104
|
+
|
105
|
+
ChefMate’s code is organized into four main modules:
|
106
|
+
|
107
|
+
### Browser Manager
|
108
|
+
|
109
|
+
**File:** `browser_manager.py`
|
110
|
+
|
111
|
+
- **Purpose:**
|
112
|
+
Manages the Chrome browser session using Selenium WebDriver.
|
113
|
+
- **Key Functions:**
|
114
|
+
- **Initialization:** Sets up the ChromeDriver with options such as user-data-dir and profile-directory for isolated sessions.
|
115
|
+
- **Conflict Detection:** Checks if a Chrome instance is already running and prompts the user accordingly.
|
116
|
+
- **Session Management:** Provides methods to initialize, operate, and close the browser session.
|
117
|
+
- **Highlights:**
|
118
|
+
Uses `webdriver_manager` to ensure the correct ChromeDriver is installed and employs custom options to reduce unwanted automation flags.
|
119
|
+
|
120
|
+
### Core Functionality
|
121
|
+
|
122
|
+
**File:** `chefmate_core.py`
|
123
|
+
|
124
|
+
- **Purpose:**
|
125
|
+
Acts as the primary interface to ChefMate functionality. It integrates browser automation with the CodeChef website.
|
126
|
+
- **Components:**
|
127
|
+
- **Login/Logout:**
|
128
|
+
Automates the CodeChef login procedure including form filling, waiting for dashboard elements, and handling potential errors.
|
129
|
+
- **Contest Handling:**
|
130
|
+
Opens a contest page, scrapes all available problem links, and dynamically creates a problem tracker.
|
131
|
+
- **Solution Handling:**
|
132
|
+
Searches for or prompts for the correct solution file. Generates solution templates based on the preferred programming language.
|
133
|
+
- **Submission and Testing:**
|
134
|
+
Provides mechanisms to load code into the CodeChef code editor, submit solutions, and analyze output results by parsing verdict tables.
|
135
|
+
- **Interactive Utilities:**
|
136
|
+
Functions like typewriter text effects, dashboard redirection, and dynamic problem tracking to enhance the user experience.
|
137
|
+
|
138
|
+
### Command Line Interface
|
139
|
+
|
140
|
+
**File:** `cli.py`
|
141
|
+
|
142
|
+
- **Purpose:**
|
143
|
+
Provides a user-friendly CLI to interact with ChefMate.
|
144
|
+
- **Features:**
|
145
|
+
- **CLI Commands:**
|
146
|
+
Implements commands using Click. Commands include `setup`, `login`, `logout`, `check`, `submit`, `contest`, and `interactive`.
|
147
|
+
- **Interactive Mode:**
|
148
|
+
An extended menu-driven interface built using InquirerPy that lets users select among different operational modes such as logging in, solving problems, or reconfiguring settings.
|
149
|
+
- **UI Enhancements:**
|
150
|
+
Uses the Rich library for improved terminal output, such as styled tables and animated loaders.
|
151
|
+
|
152
|
+
### Configuration Management
|
153
|
+
|
154
|
+
**File:** `config.py`
|
155
|
+
|
156
|
+
- **Purpose:**
|
157
|
+
Handles persistent configurations for ChefMate by reading from and writing to a JSON file.
|
158
|
+
- **Details:**
|
159
|
+
- **Default Configuration:**
|
160
|
+
Automatically creates a configuration file in the user's home directory (`~/.chefmate/config.json`) if it does not exist.
|
161
|
+
- **Dynamic Updates:**
|
162
|
+
Offers methods to get, set, and update various settings including username, password, preferred language, solution file paths, and Chrome user data directories.
|
163
|
+
- **Robustness:**
|
164
|
+
Includes error handling to recreate a default configuration if the current configuration file is corrupted.
|
165
|
+
|
166
|
+
---
|
167
|
+
|
168
|
+
## Installation
|
169
|
+
|
170
|
+
1. **Clone the Repository:**
|
171
|
+
|
172
|
+
```bash
|
173
|
+
git clone https://github.com/yourusername/chefmate.git
|
174
|
+
cd chefmate
|
175
|
+
```
|
176
|
+
|
177
|
+
2. **Set Up a Python Virtual Environment (Optional but Recommended):**
|
178
|
+
|
179
|
+
```bash
|
180
|
+
python -m venv venv
|
181
|
+
source venv/bin/activate # Linux/Mac
|
182
|
+
venv\Scripts\activate # Windows
|
183
|
+
```
|
184
|
+
|
185
|
+
3. **Install Dependencies:**
|
186
|
+
|
187
|
+
ChefMate relies on several Python packages. Install them using:
|
188
|
+
|
189
|
+
```bash
|
190
|
+
pip install -r requirements.txt
|
191
|
+
```
|
192
|
+
|
193
|
+
> **Note:** Dependencies include libraries like Selenium, webdriver-manager, Click, InquirerPy, Rich, and Colorama. Make sure your environment meets the prerequisites for Selenium and ChromeDriver.
|
194
|
+
|
195
|
+
---
|
196
|
+
|
197
|
+
## Usage
|
198
|
+
|
199
|
+
### Setup
|
200
|
+
|
201
|
+
Run the setup command to configure ChefMate with your CodeChef credentials, preferred language, editor, and solution file path:
|
202
|
+
|
203
|
+
```bash
|
204
|
+
python cli.py setup
|
205
|
+
```
|
206
|
+
|
207
|
+
### Login and Logout
|
208
|
+
|
209
|
+
To login to CodeChef, use:
|
210
|
+
|
211
|
+
```bash
|
212
|
+
python cli.py login
|
213
|
+
```
|
214
|
+
|
215
|
+
And to logout:
|
216
|
+
|
217
|
+
```bash
|
218
|
+
python cli.py logout
|
219
|
+
```
|
220
|
+
|
221
|
+
### Contest and Problem Management
|
222
|
+
|
223
|
+
- **Opening a Contest:**
|
224
|
+
Launch a contest by providing the contest ID and your division using:
|
225
|
+
|
226
|
+
```bash
|
227
|
+
python cli.py contest
|
228
|
+
```
|
229
|
+
|
230
|
+
- **Automatic Problem Scraping:**
|
231
|
+
ChefMate will automatically identify and open all the contest problem tabs and display a problem tracker.
|
232
|
+
|
233
|
+
### Testing and Submissions
|
234
|
+
|
235
|
+
- **Check Demo Test Cases:**
|
236
|
+
Validate your solution using sample test cases:
|
237
|
+
|
238
|
+
```bash
|
239
|
+
python cli.py check --problem 1
|
240
|
+
```
|
241
|
+
|
242
|
+
- **Submitting a Solution:**
|
243
|
+
To submit your solution for a given problem:
|
244
|
+
|
245
|
+
```bash
|
246
|
+
python cli.py submit --problem 1
|
247
|
+
```
|
248
|
+
|
249
|
+
- **Solving Problems (Template Generation & File Management):**
|
250
|
+
ChefMate automatically generates solution template files in a designated contest directory for you to edit. It opens the selected file in your preferred text editor.
|
251
|
+
|
252
|
+
### Interactive Mode
|
253
|
+
|
254
|
+
ChefMate also offers an interactive mode that provides a dynamic menu for operations. Launch it with:
|
255
|
+
|
256
|
+
```bash
|
257
|
+
python cli.py interactive
|
258
|
+
```
|
259
|
+
|
260
|
+
In this mode, you can choose among several actions such as login, logout, opening contests, checking demo cases, submitting solutions, and reconfiguring settings.
|
261
|
+
|
262
|
+
---
|
263
|
+
|
264
|
+
## Dependencies
|
265
|
+
|
266
|
+
- **Selenium:** For browser automation and web interactions.
|
267
|
+
- **webdriver-manager:** To handle ChromeDriver installation and updates.
|
268
|
+
- **Click & InquirerPy:** For building the CLI and interactive prompts.
|
269
|
+
- **Rich & Colorama:** For styled terminal outputs and color support.
|
270
|
+
- **Pandas & Tabulate:** For generating and displaying submission verdict tables.
|
271
|
+
|
272
|
+
Make sure you have the latest version of Google Chrome installed to ensure compatibility with ChromeDriver.
|
273
|
+
|
274
|
+
---
|
275
|
+
|
276
|
+
## Troubleshooting
|
277
|
+
|
278
|
+
- **Chrome Profile in Use:**
|
279
|
+
If you receive an error indicating that the Chrome profile is already being used, ensure that all Chrome windows are closed before starting ChefMate.
|
280
|
+
|
281
|
+
- **Solution File Issues:**
|
282
|
+
If ChefMate cannot locate your solution file, double-check the path in the configuration (or re-run the `setup` command).
|
283
|
+
|
284
|
+
- **Configuration Errors:**
|
285
|
+
If the configuration file is corrupted, ChefMate will automatically generate a new default configuration in `~/.chefmate/config.json`.
|
286
|
+
|
287
|
+
- **Network/Slow Load Problems:**
|
288
|
+
For slow networks, ChefMate includes retries during login and test case checks. If problems persist, try restarting your browser or re-running the command.
|
289
|
+
|
290
|
+
---
|
291
|
+
|
292
|
+
## Future Improvements
|
293
|
+
|
294
|
+
- **Enhanced Error Reporting:**
|
295
|
+
Additional debugging information for failures during submissions and test case validations.
|
296
|
+
- **Multi-Language Support:**
|
297
|
+
Extending support for more languages and custom code editor integration.
|
298
|
+
- **GUI Implementation:**
|
299
|
+
A graphical user interface for those who prefer not to use the CLI.
|
300
|
+
- **Extended Contest Support:**
|
301
|
+
Integration with more competitive programming sites.
|
302
|
+
|
303
|
+
---
|
304
|
+
|
305
|
+
## License
|
306
|
+
|
307
|
+
ChefMate is open source software released under the [MIT License](LICENSE).
|
308
|
+
|
309
|
+
---
|
310
|
+
|
311
|
+
ChefMate is designed with flexibility and practicality in mind to reduce the repetitive tasks of contest participation, leaving you free to concentrate on solving problems and improving your competitive programming skills.
|
312
|
+
|
313
|
+
Happy Coding!
|
@@ -0,0 +1,11 @@
|
|
1
|
+
chefmate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
chefmate/browser_manager.py,sha256=V1khfGVj8aeOmuQmVZLHs5H56vZRvtI97-nNe6pTK6E,2866
|
3
|
+
chefmate/chefmate_core.py,sha256=F66-7gJJtn0_a6nM3HWLe58-3ExcAA82HK0ujmzrmEU,69631
|
4
|
+
chefmate/cli.py,sha256=5GtohPcnSY8ygqLqZyMwZQioWfvMlF9KHTvYN15CB-4,9323
|
5
|
+
chefmate/config.py,sha256=itkFruFKMX7eday8UnAYOfnVMthivn20tiTlG87czyA,2220
|
6
|
+
chefmate-1.0.0.dist-info/licenses/LICENSE,sha256=gIUzdNdf-vbONssDRz-fj0uTywroTk9_ZBedvpj57XU,1094
|
7
|
+
chefmate-1.0.0.dist-info/METADATA,sha256=0rjISJSFc-cUYZqDtbWJdvmf1I8_0Rca49Vbe7to_B4,11858
|
8
|
+
chefmate-1.0.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
9
|
+
chefmate-1.0.0.dist-info/entry_points.txt,sha256=JajQonz6c_uzwcHALUk6VA_zxMhDPsdHC-Z7lJedyyA,46
|
10
|
+
chefmate-1.0.0.dist-info/top_level.txt,sha256=jOlvGtNNEYlsbwLBD2lpAmZBSo1wq2dydfAM1lP_Ago,9
|
11
|
+
chefmate-1.0.0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) [2025] [Anuj Kumar Sah]
|
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.
|