From 0341ac29e02c7877c32ee810aa38a6906cc693df Mon Sep 17 00:00:00 2001 From: MeuHubPython Date: Tue, 15 Oct 2024 14:35:07 -0300 Subject: [PATCH 01/38] Python Simple Pomodoro Timer --- Pomodoro Timer/README.md | 27 +++++++++++++++++++++++++++ Pomodoro Timer/main.py | 31 +++++++++++++++++++++++++++++++ Pomodoro Timer/runtime.txt | 1 + 3 files changed, 59 insertions(+) create mode 100644 Pomodoro Timer/README.md create mode 100644 Pomodoro Timer/main.py create mode 100644 Pomodoro Timer/runtime.txt diff --git a/Pomodoro Timer/README.md b/Pomodoro Timer/README.md new file mode 100644 index 0000000..3560f56 --- /dev/null +++ b/Pomodoro Timer/README.md @@ -0,0 +1,27 @@ +# Pomodoro Timer + +A simple, customizable command line pomodoro timer built in Python. + +## Features + +- Customizable work, short and long breaks intervals: Define your own durations for each cycle. +- Cycles: Run Multiple cycles of work and break intervals +- Console output: Show work and break intervals in the console. + +## How it works + +The Pomodoro Timer follow these steps: +1. Set your work and break intervals. +2. Take a short break every work interval. +3. After a set number of cycles, take a long break. + +## Usage + +1. Clone this repository to your machine. +2. Run the Python script from the command line. + '''python pomodoro_timer.py''' + +## Author + +[MeuHubPython](https://github.com/MeuHubPython) + diff --git a/Pomodoro Timer/main.py b/Pomodoro Timer/main.py new file mode 100644 index 0000000..d08d7c5 --- /dev/null +++ b/Pomodoro Timer/main.py @@ -0,0 +1,31 @@ +import time + + +def countdown(minutes, label): + total_seconds = minutes * 60 + while total_seconds: + minutes, seconds = divmod(total_seconds, 60) + timer = f"{minutes:02d}:{seconds:02d}" + print(f"{label} Timer: {timer}", end="\r") + time.sleep(1) + total_seconds -= 1 + print(f"\n{label} finished!") + + +def pomodoro_timer(work_min, short_break_min, long_break_min, cycles): + for i in range(cycles): + print(f"\nCycle {i+1} of {cycles}") + countdown(work_min, "Work") + if i < cycles - 1: + countdown(short_break_min, "Short Break") + else: + countdown(long_break_min, "Long Break") + + +if __name__ == "__main__": + work_minutes = int(input("Enter work interval in minutes: ")) + short_break_minutes = int(input("Enter short break interval in minutes: ")) + long_break_minutes = int(input("Enter long break interval in minutes: ")) + cycles = int(input("Enter the number of cycles: ")) + + pomodoro_timer(work_minutes, short_break_minutes, long_break_minutes, cycles) diff --git a/Pomodoro Timer/runtime.txt b/Pomodoro Timer/runtime.txt new file mode 100644 index 0000000..f63b125 --- /dev/null +++ b/Pomodoro Timer/runtime.txt @@ -0,0 +1 @@ +Python 3.10.12 From 649422a691492d128f6a872fa38d693e52e094c8 Mon Sep 17 00:00:00 2001 From: Nauman Tamboli <141002585+Naumantamboli@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:50:30 +0530 Subject: [PATCH 02/38] Create tic_tac_toc.py --- Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py diff --git a/Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py b/Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py new file mode 100644 index 0000000..28aa3a2 --- /dev/null +++ b/Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py @@ -0,0 +1,168 @@ +import pygame +import sys +import numpy as np + +pygame.init() + +WIDTH, HEIGHT = 600, 600 +LINE_WIDTH = 15 +BOARD_ROWS = 3 +BOARD_COLS = 3 +SQUARE_SIZE = WIDTH // BOARD_COLS +CIRCLE_RADIUS = SQUARE_SIZE // 3 +CIRCLE_WIDTH = 15 +CROSS_WIDTH = 25 +SPACE = SQUARE_SIZE // 4 + +BG_COLOR = (28, 170, 156) +LINE_COLOR = (23, 145, 135) +CIRCLE_COLOR = (239, 231, 200) +CROSS_COLOR = (66, 66, 66) + +screen = pygame.display.set_mode((WIDTH, HEIGHT)) +pygame.display.set_caption('Tic Tac Toe') +screen.fill(BG_COLOR) + +board = np.zeros((BOARD_ROWS, BOARD_COLS)) + +def draw_lines(): + for row in range(1, BOARD_ROWS): + pygame.draw.line(screen, LINE_COLOR, (0, row * SQUARE_SIZE), (WIDTH, row * SQUARE_SIZE), LINE_WIDTH) + for col in range(1, BOARD_COLS): + pygame.draw.line(screen, LINE_COLOR, (col * SQUARE_SIZE, 0), (col * SQUARE_SIZE, HEIGHT), LINE_WIDTH) + +# Draw figures (O and X) +def draw_figures(): + for row in range(BOARD_ROWS): + for col in range(BOARD_COLS): + if board[row][col] == 1: + pygame.draw.circle(screen, CIRCLE_COLOR, + (int(col * SQUARE_SIZE + SQUARE_SIZE // 2), int(row * SQUARE_SIZE + SQUARE_SIZE // 2)), + CIRCLE_RADIUS, CIRCLE_WIDTH) + elif board[row][col] == 2: + pygame.draw.line(screen, CROSS_COLOR, + (col * SQUARE_SIZE + SPACE, row * SQUARE_SIZE + SQUARE_SIZE - SPACE), + (col * SQUARE_SIZE + SQUARE_SIZE - SPACE, row * SQUARE_SIZE + SPACE), CROSS_WIDTH) + pygame.draw.line(screen, CROSS_COLOR, + (col * SQUARE_SIZE + SPACE, row * SQUARE_SIZE + SPACE), + (col * SQUARE_SIZE + SQUARE_SIZE - SPACE, row * SQUARE_SIZE + SQUARE_SIZE - SPACE), + CROSS_WIDTH) + + +def mark_square(row, col, player): + board[row][col] = player + + +def available_square(row, col): + return board[row][col] == 0 + +def is_board_full(): + return np.all(board != 0) + +def check_win(player): + + for row in range(BOARD_ROWS): + if np.all(board[row, :] == player): + return True + for col in range(BOARD_COLS): + if np.all(board[:, col] == player): + return True + if board[0, 0] == player and board[1, 1] == player and board[2, 2] == player: + return True + if board[0, 2] == player and board[1, 1] == player and board[2, 0] == player: + return True + return False + + +# Minimax algorithm +def minimax(board, depth, is_maximizing): + if check_win(2): # AI win + return 1 + elif check_win(1): # Player win + return -1 + elif is_board_full(): + return 0 + + if is_maximizing: + best_score = -np.inf + for row in range(BOARD_ROWS): + for col in range(BOARD_COLS): + if available_square(row, col): + board[row][col] = 2 + score = minimax(board, depth + 1, False) + board[row][col] = 0 + best_score = max(score, best_score) + return best_score + else: + best_score = np.inf + for row in range(BOARD_ROWS): + for col in range(BOARD_COLS): + if available_square(row, col): + board[row][col] = 1 + score = minimax(board, depth + 1, True) + board[row][col] = 0 + best_score = min(score, best_score) + return best_score + + +# AI Move +def ai_move(): + best_score = -np.inf + move = None + for row in range(BOARD_ROWS): + for col in range(BOARD_COLS): + if available_square(row, col): + board[row][col] = 2 + score = minimax(board, 0, False) + board[row][col] = 0 + if score > best_score: + best_score = score + move = (row, col) + if move: + mark_square(move[0], move[1], 2) + +def restart(): + screen.fill(BG_COLOR) + draw_lines() + global board + board = np.zeros((BOARD_ROWS, BOARD_COLS)) + + +player = 1 # Player 1 is human +game_over = False + +draw_lines() + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + + if event.type == pygame.MOUSEBUTTONDOWN and not game_over: + mouseX = event.pos[0] # X coordinate + mouseY = event.pos[1] # Y coordinate + + clicked_row = mouseY // SQUARE_SIZE + clicked_col = mouseX // SQUARE_SIZE + + if available_square(clicked_row, clicked_col): + mark_square(clicked_row, clicked_col, player) + if check_win(player): + game_over = True + player = 2 + + if player == 2 and not game_over: + ai_move() + if check_win(2): + game_over = True + player = 1 + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_r: + restart() + game_over = False + player = 1 + + draw_figures() + pygame.display.update() From 94ef256b40aa7e79a0c4869853049a58bd3005f5 Mon Sep 17 00:00:00 2001 From: Nauman Tamboli <141002585+Naumantamboli@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:05:49 +0530 Subject: [PATCH 03/38] Create README.md --- Tic-Tac-Toc using AI (min-max)/README.md | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Tic-Tac-Toc using AI (min-max)/README.md diff --git a/Tic-Tac-Toc using AI (min-max)/README.md b/Tic-Tac-Toc using AI (min-max)/README.md new file mode 100644 index 0000000..959774b --- /dev/null +++ b/Tic-Tac-Toc using AI (min-max)/README.md @@ -0,0 +1,48 @@ +# Tic-Tac-Toe Game with AI + +This project is a Tic-Tac-Toe game implemented in Python using the Pygame library. The game presents a classic, engaging experience where players can compete against either an AI opponent or another human player. The AI leverages the Minimax algorithm, a decision-making algorithm used in game theory, to evaluate potential moves and choose the best possible action at each turn. This guarantees that the AI will always make optimal moves, creating a challenging and competitive environment for players of all skill levels. + +### Key Features: +- **Two Players**: Play against an AI or another human player. +- **Minimax Algorithm**: The AI makes optimal moves based on the Minimax strategy. +- **Graphical User Interface**: A simple and intuitive GUI using Pygame. +- **Reset Option**: Restart the game easily at any time. + +# Prerequisites +The following libraries are required to run the script: +```bash +pip install pygame numpy +``` + +# Installing Instructions +1. **Clone the Repository**: + Clone this repository to your local machine using: + ```bash + git clone + ``` + +2. **Install Dependencies**: + Navigate to the project directory and install the required packages: + ```bash + pip install pygame numpy + ``` + +3. **Run the Script**: + After cloning and installing dependencies, you can run the script directly: + ```bash + python tic_tac_toe.py + ``` + +4. **Customize the Script**: + You can modify game settings, such as board size and player options, directly in the script. + +# Usage +**Player vs AI**: Click on the grid to make your move. The AI will respond automatically. + +**Restart Game**: Press the R key to restart the game at any time. + +# Example +After starting the game, you can play by clicking on the grid cells. The AI will make its move following your turn, and the game will continue until one player wins or the game ends in a draw. + +# Author +**[Naumantamboli](https://github.com/Naumantamboli)** From 36689b719c67a5d34b9c8ce07d1dad7ae8e1f460 Mon Sep 17 00:00:00 2001 From: Nauman Tamboli <141002585+Naumantamboli@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:07:22 +0530 Subject: [PATCH 04/38] Create requirements.txt --- Tic-Tac-Toc using AI (min-max)/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Tic-Tac-Toc using AI (min-max)/requirements.txt diff --git a/Tic-Tac-Toc using AI (min-max)/requirements.txt b/Tic-Tac-Toc using AI (min-max)/requirements.txt new file mode 100644 index 0000000..4091431 --- /dev/null +++ b/Tic-Tac-Toc using AI (min-max)/requirements.txt @@ -0,0 +1,2 @@ +pygame +numpy From 8546cdf8a0143e5af693c08b7e0cee03ea1f824e Mon Sep 17 00:00:00 2001 From: harsh1501 Date: Thu, 17 Oct 2024 20:41:47 +0530 Subject: [PATCH 05/38] I have created a ToDoList Application using tkinter library in python --- ToDoAppTkInter/To_Do_AppTkInter.py | 210 +++++++++++++++++++++++++++++ tasks.db | Bin 0 -> 8192 bytes 2 files changed, 210 insertions(+) create mode 100644 ToDoAppTkInter/To_Do_AppTkInter.py create mode 100644 tasks.db diff --git a/ToDoAppTkInter/To_Do_AppTkInter.py b/ToDoAppTkInter/To_Do_AppTkInter.py new file mode 100644 index 0000000..c2493ba --- /dev/null +++ b/ToDoAppTkInter/To_Do_AppTkInter.py @@ -0,0 +1,210 @@ +import tkinter as tk +from tkinter import messagebox, ttk +from tkcalendar import DateEntry +import sqlite3 + +class TodoApp: + def __init__(self, root): + self.root = root + self.root.title("Advanced To-Do List") + self.root.geometry("900x600") + + # Initialize attributes + self.is_dark_theme = True # Start with dark theme + + # Create main frame and sidebar frame + self.main_frame = tk.Frame(self.root, bg="#2E2E2E") + self.main_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) + + self.sidebar_frame = tk.Frame(self.root, width=200, bg="#3A3A3A") + self.sidebar_frame.pack(side=tk.LEFT, fill=tk.Y) + + self.create_widgets() + self.create_database() + self.apply_theme() # Apply theme after frames are created + self.create_sidebar() + self.load_tasks() + + def create_sidebar(self): + """Create the sidebar with navigation options.""" + tk.Label(self.sidebar_frame, text="Menu", font=("Helvetica", 16), bg="#3A3A3A", fg="#FFFFFF").pack(pady=10) + + # Create the "View All Tasks" button + self.view_all_button = tk.Button( + self.sidebar_frame, + text="View All Tasks", + command=self.load_tasks, + bg="#5A5A5A", + fg="#FFFFFF", + relief="flat" + ) + self.view_all_button.pack(pady=5, padx=10, fill=tk.X) + + # Create other buttons like "View Completed Tasks", "View Pending Tasks", etc. + self.view_completed_button = tk.Button( + self.sidebar_frame, + text="View Completed Tasks", + command=self.load_completed_tasks, + bg="#5A5A5A", + fg="#FFFFFF", + relief="flat" + ) + self.view_completed_button.pack(pady=5, padx=10, fill=tk.X) + + self.view_pending_button = tk.Button( + self.sidebar_frame, + text="View Pending Tasks", + command=self.load_pending_tasks, + bg="#5A5A5A", + fg="#FFFFFF", + relief="flat" + ) + self.view_pending_button.pack(pady=5, padx=10, fill=tk.X) + + # Search entry and label + tk.Label(self.sidebar_frame, text="Search:", bg="#3A3A3A", fg="#FFFFFF").pack(pady=5) + self.search_entry = tk.Entry(self.sidebar_frame, bg="#4B4B4B", fg="#FFFFFF", relief="flat") + self.search_entry.pack(pady=5, padx=10, fill=tk.X) + self.search_entry.bind('', self.search_tasks) + + # Toggle theme button + self.theme_button = tk.Button( + self.sidebar_frame, + text="Toggle Theme", + command=self.toggle_theme, + bg="#5A5A5A", + fg="#FFFFFF", + relief="flat" + ) + self.theme_button.pack(pady=5, padx=10, fill=tk.X) + + def apply_theme(self): + """Apply the current theme to the application.""" + if self.is_dark_theme: + bg_color = "#2E2E2E" + fg_color = "#FFFFFF" + button_bg = "#5A5A5A" + entry_bg = "#4B4B4B" + else: + bg_color = "#F0F0F0" + fg_color = "#000000" + button_bg = "#D0D0D0" + entry_bg = "#FFFFFF" + + self.root.configure(bg=bg_color) + self.main_frame.configure(bg=bg_color) + self.sidebar_frame.configure(bg="#3A3A3A" if self.is_dark_theme else "#F0F0F0") + + # Update the colors of sidebar elements + for widget in self.sidebar_frame.winfo_children(): + if isinstance(widget, tk.Button): + widget.configure(bg=button_bg, fg=fg_color) + elif isinstance(widget, tk.Entry): + widget.configure(bg=entry_bg, fg=fg_color) + + def toggle_theme(self): + """Toggle between light and dark themes.""" + self.is_dark_theme = not self.is_dark_theme + self.apply_theme() + + def create_database(self): + """Create the tasks table if it doesn't exist.""" + self.conn = sqlite3.connect("tasks.db") + with self.conn: + self.conn.execute(""" + CREATE TABLE IF NOT EXISTS tasks ( + id INTEGER PRIMARY KEY, + task TEXT NOT NULL, + category TEXT, + due_date TEXT, + priority TEXT, + completed INTEGER DEFAULT 0 + ) + """) + + def create_widgets(self): + """Create the main content area widgets.""" + frame = tk.Frame(self.main_frame, bg="#2E2E2E" if self.is_dark_theme else "#FFFFFF", padx=10, pady=10) + frame.pack(pady=20, padx=20, fill=tk.BOTH, expand=True) + + # Task entry + tk.Label(frame, text="Task:", font=("Helvetica", 12), bg=frame["bg"], fg="#FFFFFF" if self.is_dark_theme else "#000000").grid(row=0, column=0, sticky="w", pady=5) + self.task_entry = tk.Entry(frame, width=50, bg="#4B4B4B", fg="#FFFFFF", relief="flat") + self.task_entry.grid(row=0, column=1, sticky="ew", padx=5, pady=5) + + # Category entry + tk.Label(frame, text="Category:", font=("Helvetica", 12), bg=frame["bg"], fg="#FFFFFF" if self.is_dark_theme else "#000000").grid(row=1, column=0, sticky="w", pady=5) + self.category_entry = tk.Entry(frame, width=50, bg="#4B4B4B", fg="#FFFFFF", relief="flat") + self.category_entry.grid(row=1, column=1, sticky="ew", padx=5, pady=5) + + # Due date entry + tk.Label(frame, text="Due Date:", font=("Helvetica", 12), bg=frame["bg"], fg="#FFFFFF" if self.is_dark_theme else "#000000").grid(row=2, column=0, sticky="w", pady=5) + self.due_date_entry = DateEntry(frame, width=20, date_pattern='yyyy-mm-dd', background='#4B4B4B', foreground='white', relief="flat") + self.due_date_entry.grid(row=2, column=1, sticky="w", padx=5, pady=5) + + # Priority menu + tk.Label(frame, text="Priority:", font=("Helvetica", 12), bg=frame["bg"], fg="#FFFFFF" if self.is_dark_theme else "#000000").grid(row=3, column=0, sticky="w", pady=5) + self.priority_var = tk.StringVar(value="Medium") + self.priority_menu = ttk.Combobox(frame, textvariable=self.priority_var, values=["High", "Medium", "Low"], state="readonly") + self.priority_menu.grid(row=3, column=1, sticky="w", padx=5, pady=5) + + # Add task button + self.add_task_button = tk.Button(frame, text="Add Task", command=self.add_task, bg="#5A5A5A", fg="#FFFFFF", relief="flat") + self.add_task_button.grid(row=4, column=1, sticky="e", pady=10) + + # Listbox for tasks + self.task_listbox = tk.Listbox(self.main_frame, font=("Helvetica", 10), bg="#2E2E2E", fg="#FFFFFF", height=15, relief="flat") + self.task_listbox.pack(pady=10, padx=20, fill=tk.BOTH, expand=True) + + def load_tasks(self): + """Load all tasks from the database.""" + self.task_listbox.delete(0, tk.END) + cursor = self.conn.cursor() + cursor.execute("SELECT * FROM tasks WHERE completed=0") + for row in cursor.fetchall(): + self.task_listbox.insert(tk.END, f"{row[1]} | {row[2]} | Due: {row[3]} | Priority: {row[4]}") + + def load_completed_tasks(self): + """Load completed tasks.""" + self.task_listbox.delete(0, tk.END) + cursor = self.conn.cursor() + cursor.execute("SELECT * FROM tasks WHERE completed=1") + for row in cursor.fetchall(): + self.task_listbox.insert(tk.END, f"{row[1]} | {row[2]} | Due: {row[3]} | Priority: {row[4]}") + + def load_pending_tasks(self): + """Load pending tasks.""" + self.load_tasks() + + def add_task(self): + """Add a new task.""" + task = self.task_entry.get() + category = self.category_entry.get() + due_date = self.due_date_entry.get() + priority = self.priority_var.get() + + if task and category and due_date: + with self.conn: + self.conn.execute("INSERT INTO tasks (task, category, due_date, priority) VALUES (?, ?, ?, ?)", + (task, category, due_date, priority)) + self.load_tasks() + self.task_entry.delete(0, tk.END) + self.category_entry.delete(0, tk.END) + else: + messagebox.showwarning("Input Error", "Please fill all fields.") + + def search_tasks(self, event): + """Search tasks based on input.""" + query = self.search_entry.get().lower() + self.task_listbox.delete(0, tk.END) + cursor = self.conn.cursor() + cursor.execute("SELECT * FROM tasks WHERE completed=0") + for row in cursor.fetchall(): + task_str = f"{row[1]} | {row[2]} | Due: {row[3]} | Priority: {row[4]}" + if query in task_str.lower(): + self.task_listbox.insert(tk.END, task_str) + +if __name__ == "__main__": + root = tk.Tk() + app = TodoApp(root) + root.mainloop() diff --git a/tasks.db b/tasks.db new file mode 100644 index 0000000000000000000000000000000000000000..104bb64f8d8fedd86fca04f96ea8be7bf296baf6 GIT binary patch literal 8192 zcmeI#!D_-l5C-5~DF}k4w_N9FMWo;hH0rj9TU*l=>Zzn=m0&|8ZVO&ZZ+*PJkdr|0 z(4ZGjo@`1)~Q)nA2FzJC)h|95U*~(BzSOrge305jwj{vt5y`jzk~! zHR9Nj$R>-^EOy6ES)|E^*S3cphU(6rX+t-E7P!vu=6vZ#K>z{}fB*y_009U<00Izz K00bcLj|KMbze{-l literal 0 HcmV?d00001 From 13a28d21ef20f84475564b6d03092ace04d1cac4 Mon Sep 17 00:00:00 2001 From: Nauman Tamboli <141002585+Naumantamboli@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:30:20 +0530 Subject: [PATCH 06/38] Update requirements.txt --- Tic-Tac-Toc using AI (min-max)/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tic-Tac-Toc using AI (min-max)/requirements.txt b/Tic-Tac-Toc using AI (min-max)/requirements.txt index 4091431..8a894f6 100644 --- a/Tic-Tac-Toc using AI (min-max)/requirements.txt +++ b/Tic-Tac-Toc using AI (min-max)/requirements.txt @@ -1,2 +1,2 @@ -pygame -numpy +pygame==2.1.3 +numpy==1.23.5 From f739cfd38f21610c1e84c92cdb589035e889c8a5 Mon Sep 17 00:00:00 2001 From: Nauman Tamboli <141002585+Naumantamboli@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:34:55 +0530 Subject: [PATCH 07/38] Update tic_tac_toc.py --- Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py b/Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py index 28aa3a2..f6057e1 100644 --- a/Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py +++ b/Tic-Tac-Toc using AI (min-max)/tic_tac_toc.py @@ -18,13 +18,17 @@ LINE_COLOR = (23, 145, 135) CIRCLE_COLOR = (239, 231, 200) CROSS_COLOR = (66, 66, 66) +TEXT_COLOR = (255, 255, 255) screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('Tic Tac Toe') screen.fill(BG_COLOR) +font = pygame.font.Font(None, 40) # Font for displaying messages board = np.zeros((BOARD_ROWS, BOARD_COLS)) +difficulty = "medium" # AI difficulty level ("easy", "medium", "hard") + def draw_lines(): for row in range(1, BOARD_ROWS): pygame.draw.line(screen, LINE_COLOR, (0, row * SQUARE_SIZE), (WIDTH, row * SQUARE_SIZE), LINE_WIDTH) @@ -48,11 +52,9 @@ def draw_figures(): (col * SQUARE_SIZE + SQUARE_SIZE - SPACE, row * SQUARE_SIZE + SQUARE_SIZE - SPACE), CROSS_WIDTH) - def mark_square(row, col, player): board[row][col] = player - def available_square(row, col): return board[row][col] == 0 @@ -60,7 +62,6 @@ def is_board_full(): return np.all(board != 0) def check_win(player): - for row in range(BOARD_ROWS): if np.all(board[row, :] == player): return True @@ -73,8 +74,14 @@ def check_win(player): return True return False +def display_message(message): + text = font.render(message, True, TEXT_COLOR) + text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 2)) + screen.blit(text, text_rect) + pygame.display.update() + pygame.time.wait(2000) # Wait for 2 seconds to display the message -# Minimax algorithm +# Minimax algorithm with difficulty levels def minimax(board, depth, is_maximizing): if check_win(2): # AI win return 1 @@ -104,8 +111,7 @@ def minimax(board, depth, is_maximizing): best_score = min(score, best_score) return best_score - -# AI Move +# AI Move based on difficulty level def ai_move(): best_score = -np.inf move = None @@ -118,16 +124,23 @@ def ai_move(): if score > best_score: best_score = score move = (row, col) + if move: mark_square(move[0], move[1], 2) +# Easy AI move: choose a random available square +def easy_ai_move(): + available_moves = [(row, col) for row in range(BOARD_ROWS) for col in range(BOARD_COLS) if available_square(row, col)] + if available_moves: + move = available_moves[np.random.randint(len(available_moves))] + mark_square(move[0], move[1], 2) + def restart(): screen.fill(BG_COLOR) draw_lines() global board board = np.zeros((BOARD_ROWS, BOARD_COLS)) - player = 1 # Player 1 is human game_over = False @@ -149,12 +162,18 @@ def restart(): if available_square(clicked_row, clicked_col): mark_square(clicked_row, clicked_col, player) if check_win(player): + display_message("Player Wins!") game_over = True player = 2 if player == 2 and not game_over: - ai_move() + if difficulty == "easy": + easy_ai_move() + else: + ai_move() + if check_win(2): + display_message("AI Wins!") game_over = True player = 1 @@ -164,5 +183,9 @@ def restart(): game_over = False player = 1 + if game_over and is_board_full(): + display_message("It's a Draw!") + game_over = True + draw_figures() pygame.display.update() From 113ee106ecb11f5f71f36a2b93cdebe29c3b8e4c Mon Sep 17 00:00:00 2001 From: Nauman Tamboli <141002585+Naumantamboli@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:37:08 +0530 Subject: [PATCH 08/38] Update tic_tac_toc.py From cfa05e9c48f58820e99385e95387905aacfc79cb Mon Sep 17 00:00:00 2001 From: Nauman Tamboli <141002585+Naumantamboli@users.noreply.github.com> Date: Fri, 18 Oct 2024 13:42:27 +0530 Subject: [PATCH 09/38] Update README.md --- Tic-Tac-Toc using AI (min-max)/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tic-Tac-Toc using AI (min-max)/README.md b/Tic-Tac-Toc using AI (min-max)/README.md index 959774b..06d3e22 100644 --- a/Tic-Tac-Toc using AI (min-max)/README.md +++ b/Tic-Tac-Toc using AI (min-max)/README.md @@ -36,6 +36,11 @@ pip install pygame numpy 4. **Customize the Script**: You can modify game settings, such as board size and player options, directly in the script. +# Gameplay Instructions +- **Player vs AI:**: Click on the grid to make your move. The AI will respond automatically. +- **AI Difficulty Levels**: You can adjust the difficulty of the AI in the game settings to suit your skill level. Higher levels make the AI more challenging. +- **Restart Game**: Press the R key to restart the game at any time. + # Usage **Player vs AI**: Click on the grid to make your move. The AI will respond automatically. @@ -43,6 +48,9 @@ pip install pygame numpy # Example After starting the game, you can play by clicking on the grid cells. The AI will make its move following your turn, and the game will continue until one player wins or the game ends in a draw. +![Game Screen](screenshots/screenshot1.png) +![Winning State](screenshots/screenshot2.png) + # Author **[Naumantamboli](https://github.com/Naumantamboli)** From 7265382dff2a068821861f6db65cf21ec798083b Mon Sep 17 00:00:00 2001 From: ashutosh das Date: Fri, 18 Oct 2024 21:51:51 +0530 Subject: [PATCH 10/38] created a Mental health bot with ML and NLP --- Mental Health chatbot/Mental_health_bot.py | 125 +++++++++++++++++++++ Mental Health chatbot/README_BOT.md | 70 ++++++++++++ Mental Health chatbot/requirements.txt | 5 + 3 files changed, 200 insertions(+) create mode 100644 Mental Health chatbot/Mental_health_bot.py create mode 100644 Mental Health chatbot/README_BOT.md create mode 100644 Mental Health chatbot/requirements.txt diff --git a/Mental Health chatbot/Mental_health_bot.py b/Mental Health chatbot/Mental_health_bot.py new file mode 100644 index 0000000..9d05e40 --- /dev/null +++ b/Mental Health chatbot/Mental_health_bot.py @@ -0,0 +1,125 @@ +import pandas as pd +import numpy as np +import json +import nltk +from nltk.stem import WordNetLemmatizer +from sklearn.feature_extraction.text import TfidfVectorizer +from sklearn.metrics.pairwise import cosine_similarity +from tensorflow.keras.models import Sequential +from tensorflow.keras.layers import Dense, Dropout +from tensorflow.keras.optimizers import Adam +import os + +# Download necessary NLTK data +nltk.download('punkt') +nltk.download('wordnet') + +# Initialize lemmatizer +lemmatizer = WordNetLemmatizer() + +# Load datasets +try: + print("Files in current directory:", os.listdir()) + csv_files = [f for f in os.listdir() if f.endswith('.csv') and 'Combined' in f and 'Data' in f] + if csv_files: + df = pd.read_csv(csv_files[0]) + print(f"Loaded file: {csv_files[0]}") + print("DataFrame columns:", df.columns.tolist()) + print("DataFrame shape:", df.shape) + print(df.head()) + else: + raise FileNotFoundError("No matching CSV file found") +except FileNotFoundError as e: + print(f"Error: {str(e)}") + print("Ensure 'Combined_Data.csv' is in the same directory.") + print("Current working directory:", os.getcwd()) + exit(1) + +# Load intents.json +try: + with open('intents.json', 'r') as f: + intents = json.load(f) +except FileNotFoundError as e: + print(f"Error: {str(e)}. Ensure 'intents.json' is available.") + exit(1) + +# Preprocess text data +def preprocess_text(text): + tokens = nltk.word_tokenize(str(text).lower()) + return ' '.join([lemmatizer.lemmatize(token) for token in tokens]) + +# Determine the correct column name for text data +text_column = 'statement' if 'statement' in df.columns else df.columns[0] + +df['processed_text'] = df[text_column].apply(preprocess_text) + +# Create TF-IDF vectorizer +vectorizer = TfidfVectorizer() +tfidf_matrix = vectorizer.fit_transform(df['processed_text']) + +# Prepare data for model training +X, y = [], [] + +for intent in intents['intents']: + for pattern in intent['patterns']: + X.append(preprocess_text(pattern)) + y.append(intent['tag']) + +X = vectorizer.transform(X).toarray() +y = pd.get_dummies(y).values + +# Ensure X and y have the same shape +assert X.shape[0] == y.shape[0], f"Shape mismatch: X={X.shape}, y={y.shape}" + +# Build the model +model = Sequential([ + Dense(128, input_shape=(X.shape[1],), activation='relu'), + Dropout(0.5), + Dense(64, activation='relu'), + Dropout(0.5), + Dense(y.shape[1], activation='softmax') +]) + +model.compile(optimizer=Adam(learning_rate=0.01), loss='categorical_crossentropy', metrics=['accuracy']) + +# Train the model with error handling +try: + model.fit(X, y, epochs=200, batch_size=32, verbose=1) +except Exception as e: + print(f"Error during model training: {str(e)}") + print(f"X shape: {X.shape}, y shape: {y.shape}") + raise + +# Chatbot function +def chatbot_response(user_input): + processed_input = preprocess_text(user_input) + input_vector = vectorizer.transform([processed_input]).toarray() + + # Find similar responses from the dataset + similarities = cosine_similarity(input_vector, tfidf_matrix) + most_similar_idx = similarities.argmax() + response = df.iloc[most_similar_idx][text_column] + + # Classify intent + intent_probs = model.predict(input_vector)[0] + intent_idx = intent_probs.argmax() + intent_tag = list(pd.get_dummies([i['tag'] for i in intents['intents']]).columns)[intent_idx] + + # Get response from intents + for intent in intents['intents']: + if intent['tag'] == intent_tag: + intent_response = np.random.choice(intent['responses']) + break + + return f"Dataset Response: {response}\n\nIntent Response: {intent_response}" + +# Main chat loop +print("Mental Health Chatbot: Hello! I'm here to provide support and resources for mental health. How can I help you today?") +while True: + user_input = input("You: ") + if user_input.lower() in ['quit', 'exit', 'bye']: + print("Mental Health Chatbot: Take care! Remember, it's okay to seek help when you need it.") + break + response = chatbot_response(user_input) + print("Mental Health Chatbot:", response) + diff --git a/Mental Health chatbot/README_BOT.md b/Mental Health chatbot/README_BOT.md new file mode 100644 index 0000000..77d7e13 --- /dev/null +++ b/Mental Health chatbot/README_BOT.md @@ -0,0 +1,70 @@ +# Mental Health Chatbot + +This project implements a chatbot designed to provide support and information related to mental health. It uses natural language processing and machine learning techniques to understand user input and generate appropriate responses. + +## Features + +- Sentiment analysis of user input +- Personalized responses based on user's emotional state +- Information provision on various mental health topics +- Supportive and empathetic conversation + +## Installation + +1. Clone this repository: + ``` + git clone https://github.com/Ashutoshdas-dev/All-In-One-Python-Projects + cd All-In-One-Python-Projects/Mental Health Chatbot + ``` + +2. Set up a virtual environment: + ``` + python -m venv venv + ``` + +3. Activate the virtual environment: + - On Windows: + ``` + venv\Scripts\activate + ``` + - On macOS and Linux: + ``` + source venv/bin/activate + ``` + +4. Install the required dependencies: + ``` + pip install -r requirements.txt + ``` + +## Usage + +1. Ensure your virtual environment is activated (see step 3 in Installation). + +2. Run the main script: + ``` + python mental_health_chatbot.py + ``` + +3. Follow the prompts to interact with the chatbot. + +4. Type 'quit' or 'exit' to end the conversation. + +5. When you're done, deactivate the virtual environment: + ``` + deactivate + ``` + +## Datasets + +This project utilizes the following datasets for training and improving the chatbot's responses: + +1. [Sentiment Analysis for Mental Health](https://www.kaggle.com/datasets/suchintikasarkar/sentiment-analysis-for-mental-health) + - Description: This dataset contains text data labeled with sentiment for mental health-related content. + - Use: Helps in training the sentiment analysis component of the chatbot. + +2. [Mental Health Conversational Data](https://www.kaggle.com/datasets/elvis23/mental-health-conversational-data) + - Description: This dataset includes conversations related to mental health topics. + - Use: Aids in training the chatbot to generate more natural and context-appropriate responses. + + diff --git a/Mental Health chatbot/requirements.txt b/Mental Health chatbot/requirements.txt new file mode 100644 index 0000000..f1e2598 --- /dev/null +++ b/Mental Health chatbot/requirements.txt @@ -0,0 +1,5 @@ +pandas +numpy +nltk +scikit-learn +tensorflow From a7f03293b86074ec3d6d6b90bda592507157a94c Mon Sep 17 00:00:00 2001 From: thugeyy Date: Sat, 19 Oct 2024 08:29:12 +0700 Subject: [PATCH 11/38] Implement OCR Tool for Image-to-Text Conversion --- OCR Image-to-Text Conversion/main.py | 31 +++++++++++++++++++ OCR Image-to-Text Conversion/requirements.txt | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 OCR Image-to-Text Conversion/main.py create mode 100644 OCR Image-to-Text Conversion/requirements.txt diff --git a/OCR Image-to-Text Conversion/main.py b/OCR Image-to-Text Conversion/main.py new file mode 100644 index 0000000..e475973 --- /dev/null +++ b/OCR Image-to-Text Conversion/main.py @@ -0,0 +1,31 @@ +import pytesseract +from PIL import Image +import os + +def extract_text_from_image(image_path): + """Extracts text from an image file using Tesseract OCR.""" + try: + # Open the image file + with Image.open(image_path) as img: + # Use pytesseract to do OCR on the image + extracted_text = pytesseract.image_to_string(img) + return extracted_text + except Exception as e: + print(f"Error processing the image: {e}") + return None + +def main(): + + image_path = input("Enter the path to the image file: ") + + if not os.path.isfile(image_path): + print("File does not exist. Please check the path and try again.") + return + text = extract_text_from_image(image_path) + + if text: + print("Extracted Text:") + print(text) + +if __name__ == "__main__": + main() diff --git a/OCR Image-to-Text Conversion/requirements.txt b/OCR Image-to-Text Conversion/requirements.txt new file mode 100644 index 0000000..f7fcb04 --- /dev/null +++ b/OCR Image-to-Text Conversion/requirements.txt @@ -0,0 +1,2 @@ +pillow==11.0.0 +pytesseract==0.3.13 \ No newline at end of file From ae165e88bee55f218e109ed7857458e804d4dc6e Mon Sep 17 00:00:00 2001 From: harsh1501 Date: Sat, 19 Oct 2024 12:12:11 +0530 Subject: [PATCH 12/38] The required changes are done --- CapCut.lnk | Bin 0 -> 1374 bytes To Do App/README.md | 81 ++++++++++++++++++ .../To_Do_AppTkInter.py | 30 +++++-- tasks.db => To Do App/tasks.db | Bin 4 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 CapCut.lnk create mode 100644 To Do App/README.md rename {ToDoAppTkInter => To Do App}/To_Do_AppTkInter.py (87%) rename tasks.db => To Do App/tasks.db (100%) diff --git a/CapCut.lnk b/CapCut.lnk new file mode 100644 index 0000000000000000000000000000000000000000..61d7b90e105bd611d5380bba224ab9a21bad4b1e GIT binary patch literal 1374 zcmah|ZAg<*6h5z75dBEYrih^=h=eYu`7z0yzGH4}SaVtvUd6FZ9e!+VGaV&KUt}Z_ zVM#wys8FM@Z=xiOkRnQi^oJud`{9oW_hWxTBYN)LoGpaz%Q^SlbI*OwvvbZ2L?k4} zKod=IO_~Yp>5zfzWBxY_enHct}TAj_BSWxPp)LWnEtrBINW@!ysvWlZR^yt(<<6Vamd5o1p9WN=z7ZFDdSQ)OhBUpB?`i5Y@{oMZ)B z8=?}aCJIlqxWrB`(V;LR%ff^quAXHK|E;ESw@eU$<|2_g!IDTuRT0c;a71l9L?uy( z)f|z|ZH8D&_VDk3Ne)1yX{1p2&N7!bsSSa#xUa`f3K&H&V%0u zOF43MLx@r!?T}Om>jK-0A#AYa{G;(UkOi<8$IDA1nKc|li43watjSv)g#EhLS zUdxclb@E`ZcI{%%kvn(A?4RAu_pUsi9hIvC2@~0CWk2G+_WbWYO(2X3jr0LcVLEF1 zcFC-nG!%<3f9<-OIn+MGn$O224F;QY6NoDy1&};$< zY$a@6wKHRr1@V-Iw>k-@+oaklv!#l|J8!_GW!g#*LE$ JKIUIve*kVzH}?Pl literal 0 HcmV?d00001 diff --git a/To Do App/README.md b/To Do App/README.md new file mode 100644 index 0000000..6c83590 --- /dev/null +++ b/To Do App/README.md @@ -0,0 +1,81 @@ +**#To-Do List Application** +A simple and intuitive To-Do List application built with Python's Tkinter library for the GUI and SQLite for persistent task storage. This application helps you manage tasks with categories, due dates, and priority levels, allowing easy organization of daily activities. + +**Features** + +Add Tasks: Add tasks with a description, category, due date, and priority level (High, Medium, Low). + +View Tasks: View all tasks, or filter tasks to see only completed or pending ones. + +Search Tasks: Quickly search tasks by their name or category using the search bar. + +Toggle Theme: Switch between dark and light themes to match your preference. + +Mark Tasks as Complete: Mark tasks as completed to keep track of what’s done. + +Persistent Storage: All tasks are saved in an SQLite database, ensuring data is saved even after closing the app. + + +**Prerequisites** + +Python 3.6+ +Tkinter (Usually included with Python) +SQLite (Included in Python’s standard library) +tkcalendar: Install using pip install tkcalendar + +**Usage Instructions** + +1. Add a Task +Enter a task description in the Task field. +Specify the Category for better organization. +Select a Due Date from the date picker. +Choose a Priority from the drop-down menu (High, Medium, Low). +Click Add Task to save it. + +2. View All Tasks +Click on View All Tasks in the sidebar to display a list of all tasks. +Tasks are displayed with their description, category, due date, and priority level. + +3. View Completed Tasks +Click View Completed Tasks in the sidebar to see tasks that have been marked as complete. + +4. View Pending Tasks +Click View Pending Tasks in the sidebar to view tasks that are yet to be completed. + +5. Search Tasks +Use the Search bar in the sidebar to find tasks by their description or category. +The list of tasks will update as you type, showing only those that match the search term. + +6. Mark Tasks as Complete +Select a task from the list and click Mark as Complete (add this button in your application). +Completed tasks will no longer appear in the pending tasks view. + +7. Toggle Dark/Light Theme +Click Toggle Theme in the sidebar to switch between dark and light modes. +This changes the background color, text color, and button styles for a better visual experience. + +8. Close the Application +Close the application by clicking the window close button (X) or selecting Exit. +The application safely saves your tasks and closes the database connection. + + +**Database Structure** +The application uses an SQLite database with the following table structure: + +Table Name: tasks + +Column Name Type Description + +id INTEGER Primary key, unique task ID +task TEXT Description of the task +category TEXT Category of the task (e.g., Work, Home) +due_date TEXT Due date of the task +priority TEXT Priority level (High, Medium, Low) +completed INTEGER Status (0 = Pending, 1 = Completed) + +**License** +This project is licensed under the MIT License. See the LICENSE file for details. + +**Acknowledgments** +Thanks to the Python community for their extensive libraries and documentation. +Special thanks to the creators of tkcalendar for providing a simple date picker widget for Tkinter. diff --git a/ToDoAppTkInter/To_Do_AppTkInter.py b/To Do App/To_Do_AppTkInter.py similarity index 87% rename from ToDoAppTkInter/To_Do_AppTkInter.py rename to To Do App/To_Do_AppTkInter.py index c2493ba..44aa8e4 100644 --- a/ToDoAppTkInter/To_Do_AppTkInter.py +++ b/To Do App/To_Do_AppTkInter.py @@ -6,7 +6,7 @@ class TodoApp: def __init__(self, root): self.root = root - self.root.title("Advanced To-Do List") + self.root.title("To-Do List App") self.root.geometry("900x600") # Initialize attributes @@ -25,6 +25,9 @@ def __init__(self, root): self.create_sidebar() self.load_tasks() + # Bind the window close event to close the database connection + self.root.protocol("WM_DELETE_WINDOW", self.close_app) + def create_sidebar(self): """Create the sidebar with navigation options.""" tk.Label(self.sidebar_frame, text="Menu", font=("Helvetica", 16), bg="#3A3A3A", fg="#FFFFFF").pack(pady=10) @@ -110,6 +113,7 @@ def toggle_theme(self): def create_database(self): """Create the tasks table if it doesn't exist.""" self.conn = sqlite3.connect("tasks.db") + # Create the table if it doesn't exist yet with self.conn: self.conn.execute(""" CREATE TABLE IF NOT EXISTS tasks ( @@ -157,53 +161,69 @@ def create_widgets(self): self.task_listbox.pack(pady=10, padx=20, fill=tk.BOTH, expand=True) def load_tasks(self): - """Load all tasks from the database.""" + """Load all pending tasks from the database.""" self.task_listbox.delete(0, tk.END) cursor = self.conn.cursor() + # Retrieve tasks that are not yet completed (completed=0) cursor.execute("SELECT * FROM tasks WHERE completed=0") for row in cursor.fetchall(): + # Format the task details for display in the listbox self.task_listbox.insert(tk.END, f"{row[1]} | {row[2]} | Due: {row[3]} | Priority: {row[4]}") def load_completed_tasks(self): - """Load completed tasks.""" + """Load completed tasks from the database.""" self.task_listbox.delete(0, tk.END) cursor = self.conn.cursor() + # Retrieve tasks that are marked as completed (completed=1) cursor.execute("SELECT * FROM tasks WHERE completed=1") for row in cursor.fetchall(): self.task_listbox.insert(tk.END, f"{row[1]} | {row[2]} | Due: {row[3]} | Priority: {row[4]}") def load_pending_tasks(self): """Load pending tasks.""" + # Reuse the load_tasks method since it already loads pending tasks self.load_tasks() def add_task(self): - """Add a new task.""" + """Add a new task to the database.""" task = self.task_entry.get() category = self.category_entry.get() due_date = self.due_date_entry.get() priority = self.priority_var.get() + # Validate that required fields are filled if task and category and due_date: with self.conn: + # Insert a new task into the database self.conn.execute("INSERT INTO tasks (task, category, due_date, priority) VALUES (?, ?, ?, ?)", (task, category, due_date, priority)) + # Refresh the task list to show the new entry self.load_tasks() + # Clear the input fields after adding the task self.task_entry.delete(0, tk.END) self.category_entry.delete(0, tk.END) else: messagebox.showwarning("Input Error", "Please fill all fields.") def search_tasks(self, event): - """Search tasks based on input.""" + """Search tasks based on input in the search bar.""" query = self.search_entry.get().lower() self.task_listbox.delete(0, tk.END) cursor = self.conn.cursor() + # Retrieve all tasks and filter by the search query cursor.execute("SELECT * FROM tasks WHERE completed=0") for row in cursor.fetchall(): task_str = f"{row[1]} | {row[2]} | Due: {row[3]} | Priority: {row[4]}" + # Display only tasks that match the search query if query in task_str.lower(): self.task_listbox.insert(tk.END, task_str) + def close_app(self): + """Close the database connection and exit the application.""" + if self.conn: + self.conn.close() + self.root.destroy() + if __name__ == "__main__": root = tk.Tk() app = TodoApp(root) diff --git a/tasks.db b/To Do App/tasks.db similarity index 100% rename from tasks.db rename to To Do App/tasks.db From f0bcfd91fd1372d4b41b301dcf4dfee42c7e3d25 Mon Sep 17 00:00:00 2001 From: Mill GithHub Actions Date: Sat, 19 Oct 2024 16:03:23 +0530 Subject: [PATCH 13/38] Fixes: #32 ; Feature: Text Summarization Tool Using NLP ; Fixed --- Text Summarizer/README.md | 171 ++++++++++++++++++ Text Summarizer/requirements.txt | 7 + Text Summarizer/runtime.txt | 1 + Text Summarizer/sample.csv | 9 + Text Summarizer/text_summarizer.py | 275 +++++++++++++++++++++++++++++ 5 files changed, 463 insertions(+) create mode 100644 Text Summarizer/README.md create mode 100644 Text Summarizer/requirements.txt create mode 100644 Text Summarizer/runtime.txt create mode 100644 Text Summarizer/sample.csv create mode 100644 Text Summarizer/text_summarizer.py diff --git a/Text Summarizer/README.md b/Text Summarizer/README.md new file mode 100644 index 0000000..8d7f00c --- /dev/null +++ b/Text Summarizer/README.md @@ -0,0 +1,171 @@ +Here's a professional README documentation for the provided TextRank Text Summarization script: + +--- + +# TextRank-based Text Summarization + +This project implements a **TextRank-based approach** to extract summaries from large textual data, such as articles. The summarization algorithm ranks sentences based on their relevance and importance, using concepts derived from the PageRank algorithm applied to text. + +## Table of Contents + +1. [Features](#features) +2. [Installation](#installation) +3. [Usage](#usage) +4. [How It Works](#how-it-works) +5. [Project Structure](#project-structure) +6. [Dependencies](#dependencies) +7. [License](#license) + +--- + +## Features + +- Preprocesses text to clean and remove stopwords. +- Utilizes **GloVe word embeddings** for sentence vectorization. +- Applies the **TextRank algorithm** to rank and select important sentences. +- Automatically downloads GloVe embeddings if not present locally. +- Outputs a summary of the most relevant sentences from the input text. + +## Installation + +1. Clone the repository: + ```bash + git clone + ``` +2. Install the required Python libraries: + + ```bash + pip install -r requirements.txt + ``` + +3. Download necessary NLTK data for tokenization and stopword removal: + ```python + import nltk + nltk.download('punkt') + nltk.download('stopwords') + ``` + +## Usage + +1. Prepare your CSV file with a column `article_text` containing the text articles you want to summarize. + +2. Run the script with your desired input: + ```bash + python text_summarizer.py + ``` + +### Example: + +- Ensure the input CSV file is in the directory: + + ```bash + Text Summarizer/sample.csv + ``` + +- The script will output the summary of the most important sentences from the input text. + +### Command-line Parameters + +You can modify the following paths and settings inside the script: + +- `input_csv`: Path to your input CSV file. +- `glove_dir`: Directory for storing GloVe embeddings. +- `glove_file`: Path to the GloVe embeddings file. +- `top_n_sentences`: The number of sentences you want in the summary (default is 10). + +## How It Works + +### 1. Text Preprocessing + +- Sentences are tokenized, and each sentence is cleaned by: + - Removing punctuation, numbers, and special characters. + - Converting text to lowercase. + - Removing stopwords using the NLTK library. + +### 2. Sentence Vectorization + +- The script uses **GloVe embeddings** to convert words in each sentence into a vector representation. Sentence vectors are the average of all word vectors in a sentence. +- If the embeddings are not present, the script automatically downloads them. + +### 3. Building Similarity Matrix + +- A similarity matrix is built by calculating the **cosine similarity** between sentence vectors. This matrix forms the basis for ranking sentences. + +### 4. Sentence Ranking + +- The **PageRank algorithm** is applied to the similarity matrix. Sentences are ranked based on their scores, where higher-ranked sentences are deemed more important for summarization. + +### 5. Output Summary + +- Based on the rankings, the top `n` sentences are selected as the summary. These sentences are printed as the output of the script. + +## Project Structure + +``` +. +├── Text Summarizer/ +│ ├── sample.csv # Example CSV input file with articles +│ ├── text_summarizer.py # Main script for summarization +│ ├── glove/ # Directory for storing GloVe embeddings +│ └── text_summarizer.log # Log file +``` + +## Dependencies + +- **Python 3.x** +- **Libraries**: + - `numpy` + - `pandas` + - `nltk` + - `sklearn` + - `networkx` + - `requests` + - `tqdm` + +All dependencies can be installed via: + +```bash +pip install -r requirements.txt +``` + +### GloVe Embeddings + +- The script uses **GloVe embeddings** from Stanford NLP to generate sentence vectors. + - By default, the **100-dimensional GloVe vectors** (`glove.6B.100d.txt`) are used. + - Download link: [GloVe 6B embeddings](http://nlp.uoregon.edu/download/embeddings/glove.6B.100d.txt) + +## Short Summary + +TextRank Text Summarization + +This script implements a TextRank-based approach for text summarization. +The input is a CSV file containing text articles, and the output is a summary +of the text. + +Steps: + +1. Preprocesses the text by removing punctuation, numbers, special characters, and stopwords. +2. Generates sentence vectors using GloVe word embeddings. +3. Builds a similarity matrix using cosine similarity between sentence vectors. +4. Applies the PageRank algorithm to rank sentences. +5. Outputs a summary of the most important sentences. + +Dependencies: + +- numpy +- pandas +- nltk +- sklearn +- networkx +- GloVe word embeddings (automatically downloaded if not present) + +Author: [Himanshu Mahajan](https://github.com/himanshumahajan138) + +Date: 19-10-2024 + + +## License + +This project is licensed under the MIT License. + +--- diff --git a/Text Summarizer/requirements.txt b/Text Summarizer/requirements.txt new file mode 100644 index 0000000..8ec6c39 --- /dev/null +++ b/Text Summarizer/requirements.txt @@ -0,0 +1,7 @@ +networkx==3.3 +nltk==3.9.1 +numpy==2.1.2 +pandas==2.2.3 +Requests==2.32.3 +scikit_learn==1.5.2 +tqdm==4.66.5 diff --git a/Text Summarizer/runtime.txt b/Text Summarizer/runtime.txt new file mode 100644 index 0000000..f023023 --- /dev/null +++ b/Text Summarizer/runtime.txt @@ -0,0 +1 @@ +python-3.10.7 \ No newline at end of file diff --git a/Text Summarizer/sample.csv b/Text Summarizer/sample.csv new file mode 100644 index 0000000..28e3121 --- /dev/null +++ b/Text Summarizer/sample.csv @@ -0,0 +1,9 @@ +article_id,article_text,source +1,"Maria Sharapova has basically no friends as tennis players on the WTA Tour. The Russian player has no problems in openly speaking about it and in a recent interview she said: 'I don't really hide any feelings too much. I think everyone knows this is my job here. When I'm on the courts or when I'm on the court playing, I'm a competitor and I want to beat every single person whether they're in the locker room or across the net.So I'm not the one to strike up a conversation about the weather and know that in the next few minutes I have to go and try to win a tennis match. I'm a pretty competitive girl. I say my hellos, but I'm not sending any players flowers as well. Uhm, I'm not really friendly or close to many players. I have not a lot of friends away from the courts.' When she said she is not really close to a lot of players, is that something strategic that she is doing? Is it different on the men's tour than the women's tour? 'No, not at all. I think just because you're in the same sport doesn't mean that you have to be friends with everyone just because you're categorized, you're a tennis player, so you're going to get along with tennis players. I think every person has different interests. I have friends that have completely different jobs and interests, and I've met them in very different parts of my life. I think everyone just thinks because we're tennis players we should be the greatest of friends. But ultimately tennis is just a very small part of what we do. There are so many other things that we're interested in, that we do.'",https://www.tennisworldusa.org/tennis/news/Maria_Sharapova/62220/i-do-not-have-friends-in-tennis-says-maria-sharapova/ +2,"BASEL, Switzerland (AP), Roger Federer advanced to the 14th Swiss Indoors final of his career by beating seventh-seeded Daniil Medvedev 6-1, 6-4 on Saturday. Seeking a ninth title at his hometown event, and a 99th overall, Federer will play 93th-ranked Marius Copil on Sunday. Federer dominated the 20th-ranked Medvedev and had his first match-point chance to break serve again at 5-1. He then dropped his serve to love, and let another match point slip in Medvedev's next service game by netting a backhand. He clinched on his fourth chance when Medvedev netted from the baseline. Copil upset expectations of a Federer final against Alexander Zverev in a 6-3, 6-7 (6), 6-4 win over the fifth-ranked German in the earlier semifinal. The Romanian aims for a first title after arriving at Basel without a career win over a top-10 opponent. Copil has two after also beating No. 6 Marin Cilic in the second round. Copil fired 26 aces past Zverev and never dropped serve, clinching after 2 1/2 hours with a forehand volley winner to break Zverev for the second time in the semifinal. He came through two rounds of qualifying last weekend to reach the Basel main draw, including beating Zverev's older brother, Mischa. Federer had an easier time than in his only previous match against Medvedev, a three-setter at Shanghai two weeks ago.",http://www.tennis.com/pro-game/2018/10/copil-stuns-5th-ranked-zverev-to-reach-swiss-indoors-final/77721/ +3,"Roger Federer has revealed that organisers of the re-launched and condensed Davis Cup gave him three days to decide if he would commit to the controversial competition. Speaking at the Swiss Indoors tournament where he will play in Sundays final against Romanian qualifier Marius Copil, the world number three said that given the impossibly short time frame to make a decision, he opted out of any commitment. ""They only left me three days to decide"", Federer said. ""I didn't to have time to consult with all the people I had to consult. ""I could not make a decision in that time, so I told them to do what they wanted."" The 20-time Grand Slam champion has voiced doubts about the wisdom of the one-week format to be introduced by organisers Kosmos, who have promised the International Tennis Federation up to $3 billion in prize money over the next quarter-century. The competition is set to feature 18 countries in the November 18-24 finals in Madrid next year, and will replace the classic home-and-away ties played four times per year for decades. Kosmos is headed by Barcelona footballer Gerard Pique, who is hoping fellow Spaniard Rafael Nadal will play in the upcoming event. Novak Djokovic has said he will give precedence to the ATP's intended re-launch of the defunct World Team Cup in January 2020, at various Australian venues. Major players feel that a big event in late November combined with one in January before the Australian Open will mean too much tennis and too little rest. Federer said earlier this month in Shanghai in that his chances of playing the Davis Cup were all but non-existent. ""I highly doubt it, of course. We will see what happens,"" he said. ""I do not think this was designed for me, anyhow. This was designed for the future generation of players."" Argentina and Britain received wild cards to the new-look event, and will compete along with the four 2018 semi-finalists and the 12 teams who win qualifying rounds next February. ""I don't like being under that kind of pressure,"" Federer said of the deadline Kosmos handed him.",https://scroll.in/field/899938/tennis-roger-federer-ignored-deadline-set-by-new-davis-cup +4,"Kei Nishikori will try to end his long losing streak in ATP finals and Kevin Anderson will go for his second title of the year at the Erste Bank Open on Sunday. The fifth-seeded Nishikori reached his third final of 2018 after beating Mikhail Kukushkin of Kazakhstan 6-4, 6-3 in the semifinals. A winner of 11 ATP events, Nishikori hasn't triumphed since winning in Memphis in February 2016. He has lost eight straight finals since. The second-seeded Anderson defeated Fernando Verdasco 6-3, 3-6, 6-4. Anderson has a shot at a fifth career title and second of the year after winning in New York in February. Nishikori leads Anderson 4-2 on career matchups, but the South African won their only previous meeting this year. With a victory on Sunday, Anderson will qualify for the ATP Finals. Currently in ninth place, Nishikori with a win could move to within 125 points of the cut for the eight-man event in London next month. Nishikori held serve throughout against Kukushkin, who came through qualifying. He used his first break point to close out the first set before going up 3-0 in the second and wrapping up the win on his first match point. Against Verdasco, Anderson hit nine of his 19 aces in the opening set. The Spaniard broke Anderson twice in the second but didn't get another chance on the South African's serve in the final set.",http://www.tennis.com/pro-game/2018/10/nishikori-beats-kukushkin-in-vienna-for-3rd-final-of-season/77719/ +5,"Federer, 37, first broke through on tour over two decades ago and he has since gone on to enjoy a glittering career. The 20-time Grand Slam winner is chasing his 99th ATP title at the Swiss Indoors this week and he faces Jan-Lennard Struff in the second round on Thursday (6pm BST). Davenport enjoyed most of her success in the late 1990s and her third and final major tournament win came at the 2000 Australian Open. But she claims the mentality of professional tennis players slowly began to change after the new millennium. ""It seems pretty friendly right now,"" said Davenport. ""I think there is a really nice environment and a great atmosphere, especially between some of the veteran players helping some of the younger players out. ""It's a very pleasant atmosphere, I'd have to say, around the locker rooms. ""I felt like the best weeks that I had to get to know players when I was playing were the Fed Cup weeks or the Olympic weeks, not necessarily during the tournaments. ""And even though maybe we had smaller teams, I still think we kept to ourselves quite a bit. ""Not always, but I really feel like in the mid-2000 years there was a huge shift of the attitudes of the top players and being more friendly and being more giving, and a lot of that had to do with players like Roger coming up. ""I just felt like it really kind of changed where people were a little bit, definitely in the 90s, a lot more quiet, into themselves, and then it started to become better."" Meanwhile, Federer is hoping he can improve his service game as he hunts his ninth Swiss Indoors title this week. ""I didn't serve very well [against first-round opponent Filip Kranjovic,"" Federer said. ""I think I was misfiring the corners, I was not hitting the lines enough. ""Clearly you make your life more difficult, but still I was up 6-2, 3-1, break points, so things could have ended very quickly today, even though I didn't have the best serve percentage stats. ""But maybe that's exactly what caught up to me eventually. It's just getting used to it. This is where the first rounds can be tricky.""",https://www.express.co.uk/sport/tennis/1036101/Roger-Federer-Swiss-Indoors-Jan-Lennard-Struff-Lindsay-Davenport +6,"Nadal has not played tennis since he was forced to retire from the US Open semi-finals against Juan Martin Del Porto with a knee injury. The world No 1 has been forced to miss Spain's Davis Cup clash with France and the Asian hard court season. But with the ATP World Tour Finals due to begin next month, Nadal is ready to prove his fitness before the season-ending event at the 02 Arena. Nadal flew to Paris on Friday and footage from the Paris Masters official Twitter account shows the Spaniard smiling as he strides onto court for practice. The Paris Masters draw has been made and Nadal will start his campaign on Tuesday or Wednesday against either Fernando Verdasco or Jeremy Chardy. Nadal could then play defending champion Jack Sock in the third round before a potential quarter-final with either Borna Coric or Dominic Thiem. Nadal's appearance in Paris is a big boost to the tournament organisers who could see Roger Federer withdraw. Federer is in action at the Swiss Indoors in Basel and if he reaches the final, he could pull out of Paris in a bid to stay fresh for London. But as it stands, Federer is in the draw and is scheduled to face either former world No 3 Milos Raonic or Jo-Wilfried Tsonga in the second round. Federer's projected route to the Paris final could also lead to matches against Kevin Anderson and Novak Djokovic. Djokovic could play Marco Cecchinato in the second round. British No 1 Kyle Edmund is the 12th seed in Paris and will get underway in round two against either Karen Khachanov or Filip Krajinovic.",https://www.express.co.uk/sport/tennis/1037119/Rafael-Nadal-World-No-1-Paris-Masters-Federer-Djokovic +7,"Tennis giveth, and tennis taketh away. The end of the season is finally in sight, and with so many players defending,or losing,huge chunks of points in Singapore, Zhuhai and London, podcast co-hosts Nina Pantic and Irina Falconi discuss the art of defending points (02:14). It's no secret that Jack Sock has struggled on the singles court this year (his record is 7-19). He could lose 1,400 points in the next few weeks, but instead of focusing on the negative, it can all be about perspective (06:28). Let's also not forget his two Grand Slam doubles triumphs this season. Two players, Stefanos Tsitsipas and Kyle Edmund, won their first career ATP titles last week (13:26). It's a big deal because you never forget your first. Irina looks back at her WTA title win in Bogota in 2016, and tells an unforgettable story about her semifinal drama (14:04). In Singapore, one of the biggest storylines (aside from the matches, of course) has been the on-court coaching debate. Nina and Irina give their opinions on what coaching should look like in the future, on both tours (18:55).",http://www.tennis.com/pro-game/2018/10/tenniscom-podcast-irina-falconi-jack-sock-rafael-nadal-singapore/77698/ +8,"Federer won the Swiss Indoors last week by beating Romanian qualifier Marius Copil in the final. The 37-year-old claimed his 99th ATP title and is hunting the century in the French capital this week. Federer has been handed a difficult draw where could could come across Kevin Anderson, Novak Djokovic and Rafael Nadal in the latter rounds. But first the 20-time Grand Slam winner wants to train on the Paris Masters court this afternoon before deciding whether to appear for his opening match against either Milos Raonic or Jo-Wilfried Tsonga. ""On Monday, I am free and will look how I feel,"" Federer said after winning the Swiss Indoors. ""On Tuesday I will fly to Paris and train in the afternoon to be ready for my first match on Wednesday night. ""I felt good all week and better every day. ""We also had the impression that at this stage it might be better to play matches than to train. ""And as long as I fear no injury, I play."" Federer's success in Basel last week was the ninth time he has won his hometown tournament. And he was delighted to be watched on by all of his family and friends as he purchased 60 tickets for the final for those dearest to him. ""My children, my parents, my sister and my team are all there,"" Federer added. ""It is always very emotional for me to thank my team. And sometimes it tilts with the emotions, sometimes I just stumble. ""It means the world to me. It makes me incredibly happy to win my home tournament and make people happy here. ""I do not know if it's maybe my last title, so today I try a lot more to absorb that and enjoy the moments much more consciously. ""Maybe I should celebrate as if it were my last title. ""There are very touching moments: seeing the ball children, the standing ovations, all the familiar faces in the audience. Because it was not always easy in the last weeks.""",https://www.express.co.uk/sport/tennis/1038186/Roger-Federer-set-for-crunch-Paris-Masters-decision-today diff --git a/Text Summarizer/text_summarizer.py b/Text Summarizer/text_summarizer.py new file mode 100644 index 0000000..2a76ecb --- /dev/null +++ b/Text Summarizer/text_summarizer.py @@ -0,0 +1,275 @@ +""" +TextRank Text Summarization + +This script implements a TextRank-based approach for text summarization. +The input is a CSV file containing text articles, and the output is a summary +of the text. + +Steps: +1. Preprocesses the text by removing punctuation, numbers, special characters, and stopwords. +2. Generates sentence vectors using GloVe word embeddings. +3. Builds a similarity matrix using cosine similarity between sentence vectors. +4. Applies the PageRank algorithm to rank sentences. +5. Outputs a summary of the most important sentences. + +Dependencies: +- numpy +- pandas +- nltk +- sklearn +- networkx +- GloVe word embeddings (automatically downloaded if not present) + +Author: Himanshu Mahajan (GitHub: himanshumahajan138) +Date: 19-10-2024 +""" + +import os +import requests +from tqdm import tqdm +import numpy as np +import pandas as pd +import nltk +from nltk.tokenize import sent_tokenize +from nltk.corpus import stopwords +from sklearn.metrics.pairwise import cosine_similarity +import networkx as nx +import logging + +# Configure logging +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(levelname)s - %(message)s", + handlers=[ + logging.FileHandler("Text Summarizer/text_summarizer.log"), + logging.StreamHandler(), + ], +) + +# Download necessary NLTK data (if not already available) +nltk.download("punkt") # Sentence tokenizer +nltk.download("stopwords") # Stopwords list + + +# Function to preprocess and clean sentences +def preprocess_sentences(sentences): + """ + Cleans and preprocesses sentences by removing non-alphabetic characters, + converting to lowercase, and removing stopwords. + + Args: + sentences (list): List of sentences. + + Returns: + list: Cleaned and preprocessed sentences. + """ + logging.info("Preprocessing sentences...") + # Remove punctuation, numbers, and special characters + clean_sentences = pd.Series(sentences).str.replace("[^a-zA-Z]", " ", regex=True) + + # Convert to lowercase + clean_sentences = [s.lower() for s in clean_sentences] + + # Remove stopwords + stop_words = stopwords.words("english") + clean_sentences = [ + " ".join([word for word in sentence.split() if word not in stop_words]) + for sentence in clean_sentences + ] + + logging.info("Preprocessing completed.") + return clean_sentences + + +# Function to generate sentence vectors using GloVe embeddings +def generate_sentence_vectors(sentences, word_embeddings, embedding_dim=100): + """ + Converts sentences into vectors by averaging the GloVe word embeddings of each word in the sentence. + + Args: + sentences (list): List of sentences. + word_embeddings (dict): GloVe word embeddings. + embedding_dim (int): Dimensionality of GloVe vectors. + + Returns: + list: List of sentence vectors. + """ + logging.info("Generating sentence vectors...") + sentence_vectors = [] + for sentence in sentences: + if len(sentence) != 0: + words = sentence.split() + sentence_vector = sum( + [ + word_embeddings.get(word, np.zeros((embedding_dim,))) + for word in words + ] + ) / (len(words) + 0.001) + else: + sentence_vector = np.zeros((embedding_dim,)) + sentence_vectors.append(sentence_vector) + + logging.info("Sentence vectors generated.") + return sentence_vectors + + +# Function to build similarity matrix +def build_similarity_matrix(sentence_vectors): + """ + Builds a similarity matrix using cosine similarity between sentence vectors. + + Args: + sentence_vectors (list): List of sentence vectors. + + Returns: + np.ndarray: Similarity matrix. + """ + logging.info("Building similarity matrix...") + sim_mat = np.zeros([len(sentence_vectors), len(sentence_vectors)]) + + for i in range(len(sentence_vectors)): + for j in range(len(sentence_vectors)): + if i != j: + sim_mat[i][j] = cosine_similarity( + sentence_vectors[i].reshape(1, -1), + sentence_vectors[j].reshape(1, -1), + )[0, 0] + + logging.info("Similarity matrix built.") + return sim_mat + + +# Function to rank sentences using TextRank algorithm +def rank_sentences(similarity_matrix, sentences, top_n=10): + """ + Ranks sentences based on the PageRank algorithm applied to the similarity matrix. + + Args: + similarity_matrix (np.ndarray): Similarity matrix. + sentences (list): List of original sentences. + top_n (int): Number of top-ranked sentences to return. + + Returns: + list: Top-ranked sentences. + """ + logging.info(f"Ranking top {top_n} sentences...") + nx_graph = nx.from_numpy_array(similarity_matrix) + scores = nx.pagerank(nx_graph) + + ranked_sentences = sorted( + ((scores[i], sentence) for i, sentence in enumerate(sentences)), reverse=True + ) + + logging.info("Sentences ranked.") + return [ranked_sentences[i][1] for i in range(top_n)] + + +# Function to download and extract GloVe embeddings +def download_glove(glove_url, glove_file, glove_dir): + """ + Downloads and extracts GloVe embeddings if not already present. + + Args: + glove_url (str): URL to the GloVe embeddings zip file. + glove_zip (str): Path to the GloVe zip file. + glove_dir (str): Directory where the GloVe files will be extracted. + """ + if not os.path.exists(glove_file): + os.makedirs(glove_dir, exist_ok=True) + logging.info("GloVe embeddings not found, downloading...") + + # Stream the request to handle large files + with requests.get(glove_url, stream=True) as response: + response.raise_for_status() + total_size = int(response.headers.get("content-length", 0)) + block_size = 1024 # 1 Kibibyte + + # Use tqdm to show progress bar + with tqdm( + total=total_size, unit="B", unit_scale=True, desc=glove_file + ) as progress_bar: + with open(glove_file, "wb") as file: + for data in response.iter_content(block_size): + file.write(data) + progress_bar.update(len(data)) + + logging.info("Download complete. Extracting files...") + + else: + logging.info("GloVe embeddings already present.") + + +# Main function to summarize text using TextRank +def summarize_text(input_csv, glove_file, top_n=10): + """ + Summarizes the text from a CSV file using the TextRank algorithm. + + Args: + input_csv (str): Path to the input CSV file. + glove_file (str): Path to the GloVe embeddings file. + top_n (int): Number of sentences to include in the summary. + + Returns: + list: Summary sentences. + """ + logging.info(f"Starting text summarization for {input_csv}...") + + # Read the CSV file + df = pd.read_csv(input_csv) + + # Tokenize articles into sentences + logging.info("Tokenizing articles into sentences...") + sentences = [sent_tokenize(article) for article in df["article_text"]] + sentences = [ + sentence for sublist in sentences for sentence in sublist + ] # Flatten the list + + # Preprocess sentences + clean_sentences = preprocess_sentences(sentences) + + # Load GloVe embeddings + logging.info("Loading GloVe embeddings...") + word_embeddings = {} + with open(glove_file, "r", encoding="utf-8") as f: + for line in f: + values = line.split() + word = values[0] + coefs = np.asarray(values[1:], dtype="float32") + word_embeddings[word] = coefs + + # Generate sentence vectors + sentence_vectors = generate_sentence_vectors(clean_sentences, word_embeddings) + + # Build similarity matrix + sim_mat = build_similarity_matrix(sentence_vectors) + + # Rank sentences + summary = rank_sentences(sim_mat, sentences, top_n=top_n) + + logging.info(f"Text summarization completed for {input_csv}.") + return summary + + +if __name__ == "__main__": + # Define paths and parameters + input_csv = os.getcwd() + "/Text Summarizer/sample.csv" # Path to input CSV file + glove_dir = "Text Summarizer/glove" # Directory where GloVe files will be stored + + glove_file = os.path.join( + os.getcwd(), glove_dir, "glove.6B.100d.txt" + ) # Path to GloVe embeddings file + + glove_url = "http://nlp.uoregon.edu/download/embeddings/glove.6B.100d.txt" # URL for GloVe embeddings + + top_n_sentences = 10 # Number of sentences in the summary + + # Download and extract GloVe embeddings + download_glove(glove_url, glove_file, glove_dir) + + # Generate summary + summary = summarize_text(input_csv, glove_file, top_n_sentences) + + # Print summary + print("Summary:") + for sentence in summary: + print(sentence + "\n") From ab12cddd1b62be361d0317be8a0976c1073c61c0 Mon Sep 17 00:00:00 2001 From: MeuHubPython Date: Sat, 19 Oct 2024 12:23:13 -0300 Subject: [PATCH 14/38] adding stop and pause features and input validation. --- Pomodoro Timer/README.md | 1 + Pomodoro Timer/main.py | 53 +++++++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/Pomodoro Timer/README.md b/Pomodoro Timer/README.md index 3560f56..243b0fe 100644 --- a/Pomodoro Timer/README.md +++ b/Pomodoro Timer/README.md @@ -5,6 +5,7 @@ A simple, customizable command line pomodoro timer built in Python. ## Features - Customizable work, short and long breaks intervals: Define your own durations for each cycle. +- Pause whenever you want: Pause the timer when you want to take a break. - Cycles: Run Multiple cycles of work and break intervals - Console output: Show work and break intervals in the console. diff --git a/Pomodoro Timer/main.py b/Pomodoro Timer/main.py index d08d7c5..d882414 100644 --- a/Pomodoro Timer/main.py +++ b/Pomodoro Timer/main.py @@ -4,28 +4,69 @@ def countdown(minutes, label): total_seconds = minutes * 60 while total_seconds: - minutes, seconds = divmod(total_seconds, 60) - timer = f"{minutes:02d}:{seconds:02d}" + mins, secs = divmod(total_seconds, 60) + timer = f"{mins:02d}:{secs:02d}" print(f"{label} Timer: {timer}", end="\r") time.sleep(1) total_seconds -= 1 print(f"\n{label} finished!") +def handle_pause_stop(): + while True: + user_input = input( + "\nPress 'p' to pause, 's' to stop, or 'Enter' to continue: " + ).lower() + if user_input == "p": + print("Timer paused. Press 'Enter' to resume.") + input() + elif user_input == "s": + print("Timer stopped.") + return True # Return True to signal that the timer should stop + else: + return False # Return False to continue with the timer + + def pomodoro_timer(work_min, short_break_min, long_break_min, cycles): for i in range(cycles): print(f"\nCycle {i+1} of {cycles}") countdown(work_min, "Work") if i < cycles - 1: + print("\nStarting short break...") + if handle_pause_stop(): + return countdown(short_break_min, "Short Break") else: + print("\nStarting long break...") + if handle_pause_stop(): + return countdown(long_break_min, "Long Break") + if not repeat_or_end(): + return + + +def repeat_or_end(): + user_input = input( + "\nCycle finished. Would you like to repeat the cycle? (y/n): " + ).lower() + return user_input == "y" + + +def get_valid_input(prompt): + while True: + try: + value = int(input(prompt)) + if value <= 0: + raise ValueError + return value + except ValueError: + print("Invalid input. Please enter a positive integer.") if __name__ == "__main__": - work_minutes = int(input("Enter work interval in minutes: ")) - short_break_minutes = int(input("Enter short break interval in minutes: ")) - long_break_minutes = int(input("Enter long break interval in minutes: ")) - cycles = int(input("Enter the number of cycles: ")) + work_minutes = get_valid_input("Enter work interval in minutes: ") + short_break_minutes = get_valid_input("Enter short break interval in minutes: ") + long_break_minutes = get_valid_input("Enter long break interval in minutes: ") + cycles = get_valid_input("Enter the number of cycles: ") pomodoro_timer(work_minutes, short_break_minutes, long_break_minutes, cycles) From f6cf5b0b2334a8013dd0ba820168eedb0b6026e5 Mon Sep 17 00:00:00 2001 From: Sai Rithwik Bejadi Date: Sat, 19 Oct 2024 23:09:58 +0530 Subject: [PATCH 15/38] To-Do List --- To Do List/main.py | 58 ++++++++++++++++++++++++++++++++++++++ To Do List/requirement.txt | 2 ++ To Do List/runtime.txt | 1 + 3 files changed, 61 insertions(+) create mode 100644 To Do List/main.py create mode 100644 To Do List/requirement.txt create mode 100644 To Do List/runtime.txt diff --git a/To Do List/main.py b/To Do List/main.py new file mode 100644 index 0000000..e841815 --- /dev/null +++ b/To Do List/main.py @@ -0,0 +1,58 @@ +from tkinter import * +import sqlite3 + +root = Tk() +root.title("To-Do List App") +root.geometry("400x400") + +conn = sqlite3.connect('todolist.db') +c = conn.cursor() + +# Create table +c.execute('''CREATE TABLE IF NOT EXISTS tasks + (id INTEGER PRIMARY KEY, task TEXT NOT NULL)''') + +def add_task(): + task = task_entry.get() + if task: + c.execute("INSERT INTO tasks (task) VALUES (?)", (task,)) + conn.commit() + task_entry.delete(0, END) + populate_tasks() + +def delete_task(): + task_id = task_list.get(ACTIVE).split('.')[0] + c.execute("DELETE FROM tasks WHERE id=?", (task_id,)) + conn.commit() + populate_tasks() + +def populate_tasks(): + task_list.delete(0, END) + c.execute("SELECT * FROM tasks") + tasks = c.fetchall() + for task in tasks: + task_list.insert(END, f"{task[0]}. {task[1]}") + +# Task entry +task_entry = Entry(root, width=50) +task_entry.pack(pady=10) + +# Add task button +add_task_button = Button(root, text="Add Task", command=add_task) +add_task_button.pack(pady=5) + +# Task list +task_list = Listbox(root, width=50, height=15) +task_list.pack(pady=10) + +# Delete task button +delete_task_button = Button(root, text="Delete Task", command=delete_task) +delete_task_button.pack(pady=5) + +# Populate tasks on startup +populate_tasks() + +# Run the main loop +root.mainloop() + +conn.close() diff --git a/To Do List/requirement.txt b/To Do List/requirement.txt new file mode 100644 index 0000000..86045b1 --- /dev/null +++ b/To Do List/requirement.txt @@ -0,0 +1,2 @@ +tk +sqlite3 diff --git a/To Do List/runtime.txt b/To Do List/runtime.txt new file mode 100644 index 0000000..a48890e --- /dev/null +++ b/To Do List/runtime.txt @@ -0,0 +1 @@ +python-3.8.10 From a108ed60fe22d76da2247865736704e596433b6f Mon Sep 17 00:00:00 2001 From: Sai Rithwik Bejadi Date: Sat, 19 Oct 2024 23:12:31 +0530 Subject: [PATCH 16/38] Readme --- To Do List/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 To Do List/README.md diff --git a/To Do List/README.md b/To Do List/README.md new file mode 100644 index 0000000..2791484 --- /dev/null +++ b/To Do List/README.md @@ -0,0 +1,22 @@ +# To-Do List App + +This is a simple To-Do List app built with Python using `tkinter` for the user interface and `sqlite3` for data storage. + +## Features + +- Add tasks +- View tasks +- Delete tasks +- Save tasks to database + +## Requirements + +- Python 3.8.10 +- `tkinter` +- `sqlite3` + +## Installation + +1. Clone the repository: + ```bash + git clone From 656351c75ef668f09e7527161c07b2aefd6cf753 Mon Sep 17 00:00:00 2001 From: harsh1501 Date: Sun, 20 Oct 2024 00:25:43 +0530 Subject: [PATCH 17/38] added a runtine.txt requirements.txt and made the changes as requested --- To Do App/requirements.txt | 2 ++ To Do App/runtime.txt | 1 + 2 files changed, 3 insertions(+) create mode 100644 To Do App/requirements.txt create mode 100644 To Do App/runtime.txt diff --git a/To Do App/requirements.txt b/To Do App/requirements.txt new file mode 100644 index 0000000..7b0416d --- /dev/null +++ b/To Do App/requirements.txt @@ -0,0 +1,2 @@ +tkinter==8.6 +sqlite3==3.45.3 diff --git a/To Do App/runtime.txt b/To Do App/runtime.txt new file mode 100644 index 0000000..89cfa9b --- /dev/null +++ b/To Do App/runtime.txt @@ -0,0 +1 @@ +Python 3.12.4 \ No newline at end of file From 972c4060b7158187e35e67e49ad96a530ee00716 Mon Sep 17 00:00:00 2001 From: harsh1501 Date: Sun, 20 Oct 2024 01:25:52 +0530 Subject: [PATCH 18/38] Removed the capcut file --- CapCut.lnk | Bin 1374 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 CapCut.lnk diff --git a/CapCut.lnk b/CapCut.lnk deleted file mode 100644 index 61d7b90e105bd611d5380bba224ab9a21bad4b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1374 zcmah|ZAg<*6h5z75dBEYrih^=h=eYu`7z0yzGH4}SaVtvUd6FZ9e!+VGaV&KUt}Z_ zVM#wys8FM@Z=xiOkRnQi^oJud`{9oW_hWxTBYN)LoGpaz%Q^SlbI*OwvvbZ2L?k4} zKod=IO_~Yp>5zfzWBxY_enHct}TAj_BSWxPp)LWnEtrBINW@!ysvWlZR^yt(<<6Vamd5o1p9WN=z7ZFDdSQ)OhBUpB?`i5Y@{oMZ)B z8=?}aCJIlqxWrB`(V;LR%ff^quAXHK|E;ESw@eU$<|2_g!IDTuRT0c;a71l9L?uy( z)f|z|ZH8D&_VDk3Ne)1yX{1p2&N7!bsSSa#xUa`f3K&H&V%0u zOF43MLx@r!?T}Om>jK-0A#AYa{G;(UkOi<8$IDA1nKc|li43watjSv)g#EhLS zUdxclb@E`ZcI{%%kvn(A?4RAu_pUsi9hIvC2@~0CWk2G+_WbWYO(2X3jr0LcVLEF1 zcFC-nG!%<3f9<-OIn+MGn$O224F;QY6NoDy1&};$< zY$a@6wKHRr1@V-Iw>k-@+oaklv!#l|J8!_GW!g#*LE$ JKIUIve*kVzH}?Pl From aafe5639cc121c4c869f2804fd628b3b5aa7df87 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 20 Oct 2024 17:29:10 +0000 Subject: [PATCH 19/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index 02fb74e..784002f 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -34,6 +34,7 @@ * [Telegram Bot](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Telegram%20Bot) * [Text To Speech](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20To%20Speech) * [Text to Morse Code](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20to%20Morse%20Code) +* [To Do App](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/To%20Do%20App) * [Translator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Translator) * [URL Sortener](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/URL%20Sortener) * [Validate-Email](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Validate-Email) From 687b2efd29e2c0eb6e837bd817de2d24ec50c162 Mon Sep 17 00:00:00 2001 From: Aman Kumar <62813940+king04aman@users.noreply.github.com> Date: Mon, 21 Oct 2024 07:19:08 +0530 Subject: [PATCH 20/38] chore: update contributors [skip ci] --- CONTRIBUTORS.svg | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTORS.svg b/CONTRIBUTORS.svg index 267e3f6..608028b 100644 --- a/CONTRIBUTORS.svg +++ b/CONTRIBUTORS.svg @@ -6,25 +6,28 @@ + + + - + - + - + - + - + - + - + \ No newline at end of file From ea679de49ad71e6faf5ee9a9de1f1de1c7ffa129 Mon Sep 17 00:00:00 2001 From: aanchal625 <82753429+aanchal625@users.noreply.github.com> Date: Mon, 21 Oct 2024 21:59:33 +0530 Subject: [PATCH 21/38] My-Personal-Journal Completed --- My-Personal-Journal/README.md | 34 +++ My-Personal-Journal/app.py | 78 ++++++ My-Personal-Journal/database.py | 21 ++ My-Personal-Journal/journal_app.py | 55 ++++ My-Personal-Journal/requirements.txt | 8 + My-Personal-Journal/static/style.css | 234 ++++++++++++++++++ My-Personal-Journal/templates/add.html | 45 ++++ My-Personal-Journal/templates/index.html | 24 ++ My-Personal-Journal/templates/search.html | 16 ++ .../templates/search_results.html | 22 ++ My-Personal-Journal/templates/tags.html | 18 ++ My-Personal-Journal/ui.py | 162 ++++++++++++ 12 files changed, 717 insertions(+) create mode 100644 My-Personal-Journal/README.md create mode 100644 My-Personal-Journal/app.py create mode 100644 My-Personal-Journal/database.py create mode 100644 My-Personal-Journal/journal_app.py create mode 100644 My-Personal-Journal/requirements.txt create mode 100644 My-Personal-Journal/static/style.css create mode 100644 My-Personal-Journal/templates/add.html create mode 100644 My-Personal-Journal/templates/index.html create mode 100644 My-Personal-Journal/templates/search.html create mode 100644 My-Personal-Journal/templates/search_results.html create mode 100644 My-Personal-Journal/templates/tags.html create mode 100644 My-Personal-Journal/ui.py diff --git a/My-Personal-Journal/README.md b/My-Personal-Journal/README.md new file mode 100644 index 0000000..153fd47 --- /dev/null +++ b/My-Personal-Journal/README.md @@ -0,0 +1,34 @@ +# Personal Journal + +A simple web-based application for maintaining a personal journal. Users can create entries, tag them, and search through past entries by date or keywords. The application is built using Flask and SQLite for a lightweight and efficient experience. + +## Features + +- **Add New Entries**: Users can add journal entries with mood, content, and tags. +- **Search Entries**: Search through entries using keywords or specific dates. +- **Tag Management**: Create and view tags associated with each entry, and filter entries by tags. +- **User-Friendly Interface**: A clean and professional UI for easy navigation and use. + +## Technologies Used + +- Python +- Flask +- SQLite +- HTML/CSS + +## Installation + +1. **Clone the Repository**: + ```bash + git clone + cd your_project + +2. **Install Required Packages: Make sure you have Python installed (preferably Python 3). Install the required packages using pip**: + ```bash + pip install -r requirements.txt + +3. **Run the Application: Start the Flask application**: + ```bash + python app.py + +4. **Access the App: Open your web browser and navigate to http://127.0.0.1:8080 to access the application.** diff --git a/My-Personal-Journal/app.py b/My-Personal-Journal/app.py new file mode 100644 index 0000000..e5def9e --- /dev/null +++ b/My-Personal-Journal/app.py @@ -0,0 +1,78 @@ +from flask import Flask, render_template, request, redirect, url_for +from journal_app import add_entry, search_entries +from datetime import datetime +import sqlite3 + +app = Flask(__name__) + +# Route to show the home page +@app.route('/') +def index(): + return render_template('index.html') + +# Route to add a new journal entry +@app.route('/add', methods=['GET', 'POST']) +def add(): + if request.method == 'POST': + mood = request.form['mood'] + content = request.form['content'] + tags = request.form['tags'] + add_entry("user_1", mood, content, tags) + return redirect(url_for('index')) + return render_template('add.html') + +# Route to search journal entries + + +@app.route('/search', methods=['GET', 'POST']) +def search(): + if request.method == 'POST': + search_input = request.form['search_term'] + + # Try to parse the input as a date + try: + search_date = datetime.strptime(search_input, '%Y-%m-%d').date() + results = search_entries("user_1", date=search_date) + except ValueError: + # If parsing fails, treat it as a search term + results = search_entries("user_1", search_term=search_input) + + return render_template('search_results.html', results=results) + + return render_template('search.html') + + +# Route to list all unique tags +@app.route('/tags') +def list_tags(): + conn = sqlite3.connect('journal.db') + cursor = conn.cursor() + + # Fetch unique tags from all entries + cursor.execute("SELECT DISTINCT tags FROM journal_entries") + tags_data = cursor.fetchall() + conn.close() + + # Flatten the tags and remove duplicates + tags = set() + for row in tags_data: + if row[0]: + tags.update(tag.strip() for tag in row[0].split(',')) + + return render_template('tags.html', tags=sorted(tags)) + +# Route to show journal entries by tag +@app.route('/tags/') +def entries_by_tag(tag): + conn = sqlite3.connect('journal.db') + cursor = conn.cursor() + + # Search for entries that contain the selected tag + cursor.execute("SELECT * FROM journal_entries WHERE tags LIKE ?", ('%' + tag + '%',)) + results = cursor.fetchall() + conn.close() + + return render_template('search_results.html', results=results) + +if __name__ == '__main__': + app.run(debug=True, port=8080) diff --git a/My-Personal-Journal/database.py b/My-Personal-Journal/database.py new file mode 100644 index 0000000..ae7983b --- /dev/null +++ b/My-Personal-Journal/database.py @@ -0,0 +1,21 @@ +from sqlalchemy.orm import sessionmaker +from models import JournalEntry, Base +from sqlalchemy import create_engine + +engine = create_engine('sqlite:///journal.db') +Base.metadata.create_all(engine) +Session = sessionmaker(bind=engine) +session = Session() + +def add_entry(user_id, mood, content, tags): + entry = JournalEntry(user_id=user_id, mood=mood, content=content, tags=tags) + session.add(entry) + session.commit() + +def search_entries(user_id, search_term=None, date=None): + query = session.query(JournalEntry).filter(JournalEntry.user_id == user_id) + if search_term: + query = query.filter(JournalEntry.content.contains(search_term)) + if date: + query = query.filter(JournalEntry.date == date) + return query.all() diff --git a/My-Personal-Journal/journal_app.py b/My-Personal-Journal/journal_app.py new file mode 100644 index 0000000..3978159 --- /dev/null +++ b/My-Personal-Journal/journal_app.py @@ -0,0 +1,55 @@ +import sqlite3 +from datetime import datetime + +DB_NAME = "journal.db" + +def connect_db(): + return sqlite3.connect(DB_NAME) + +def create_table(): + with connect_db() as conn: + cursor = conn.cursor() + cursor.execute(''' + CREATE TABLE IF NOT EXISTS journal_entries ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id TEXT, + date TEXT, + mood TEXT, + content TEXT, + tags TEXT + ) + ''') + conn.commit() + +def add_entry(user_id, mood, content, tags): + with connect_db() as conn: + cursor = conn.cursor() + cursor.execute(''' + INSERT INTO journal_entries (user_id, date, mood, content, tags) + VALUES (?, ?, ?, ?, ?) + ''', (user_id, datetime.now().strftime('%Y-%m-%d %H:%M:%S'), mood, content, tags)) + conn.commit() + +def search_entries(user_id, search_term=None, date=None): + with connect_db() as conn: + cursor = conn.cursor() + + if search_term: + query = ''' + SELECT * FROM journal_entries + WHERE user_id = ? AND (content LIKE ? OR tags LIKE ?) + ''' + cursor.execute(query, (user_id, f'%{search_term}%', f'%{search_term}%')) + elif date: + query = ''' + SELECT * FROM journal_entries + WHERE user_id = ? AND date(date) = ? + ''' + cursor.execute(query, (user_id, date.strftime('%Y-%m-%d'))) + else: + return [] + + return cursor.fetchall() + +# Create the journal table at the start +create_table() diff --git a/My-Personal-Journal/requirements.txt b/My-Personal-Journal/requirements.txt new file mode 100644 index 0000000..d41f170 --- /dev/null +++ b/My-Personal-Journal/requirements.txt @@ -0,0 +1,8 @@ +flask +sqlalchemy +# sqlite3 +bcrypt +pandas +matplotlib +# tkinter +flask \ No newline at end of file diff --git a/My-Personal-Journal/static/style.css b/My-Personal-Journal/static/style.css new file mode 100644 index 0000000..9c75f8d --- /dev/null +++ b/My-Personal-Journal/static/style.css @@ -0,0 +1,234 @@ +/* General Styles */ +body { + font-family: 'Arial', sans-serif; + margin: 0; + padding: 0; + background-color: #f4f4f9; + color: #333; +} + +h1, h2, h3, h4, h5, h6 { + color: #2c3e50; + text-align: center; +} + +/* Header */ +header { + background: #2980b9; + color: white; + padding: 20px 0; +} + +/* Main Content */ +.container { + max-width: 1100px; + margin: 20px auto; + padding: 20px; + background: white; + border-radius: 8px; + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + text-align: center; /* Center text within the container */ +} + +/* Button Styles */ +.button-container { + display: flex; + justify-content: center; /* Center the buttons */ + flex-direction: column; /* Stack buttons vertically */ + gap: 20px; /* Space between buttons */ + margin-top: 30px; /* Add margin to the top */ +} + +.button { + display: inline-block; + padding: 15px 30px; + background-color: #2980b9; + color: white; + border-radius: 4px; + text-decoration: none; + font-size: 1.2rem; + transition: background-color 0.3s ease; +} + +.button:hover { + background-color: #3498db; +} + +/* Footer */ +footer { + text-align: center; + margin-top: 20px; + padding: 20px; + background-color: #2980b9; + color: white; +} + +p { + line-height: 1.6; + font-size: 1rem; +} + +a { + color: #3498db; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +/* Header */ +header { + background: #2980b9; + color: white; + padding: 20px 0; + text-align: center; +} + +/* Main Content */ +.container { + max-width: 1100px; + margin: 20px auto; + padding: 20px; + background: white; + border-radius: 8px; + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); +} + +h1 { + font-size: 2rem; + margin-bottom: 20px; +} + +/* Form Styles */ +.form-group { + margin-bottom: 20px; /* Space between form groups */ + text-align: left; /* Align labels and inputs to the left */ +} + +label { + display: block; /* Ensure labels are on separate lines */ + margin-bottom: 5px; /* Space between label and input */ +} + +/* Form Styles */ +form { + display: flex; + flex-direction: column; + gap: 10px; +} + +form input[type="text"], +form textarea { + padding: 10px; + font-size: 1rem; + border: 1px solid #ddd; + border-radius: 4px; +} + +form textarea { + resize: vertical; +} + +form input[type="submit"] { + background-color: #2980b9; + color: white; + border: none; + padding: 10px; + display:flex; + font-size: 1rem; + cursor: pointer; + border-radius: 4px; +} + +form input[type="submit"]:hover { + background-color: #3498db; +} + +/* Tag List */ +ul { + list-style: none; + padding: 0; + display: flex; + justify-content: center; /* Centers the tags horizontally */ + flex-wrap: wrap; /* Allows the tags to wrap if they exceed the width */ + gap: 10px; +} + +ul li { + display: inline-block; + margin-right: 10px; +} + +ul li a { + display: inline-block; + padding: 10px 20px; + background-color: #2980b9; + color: white; + border-radius: 4px; + transition: background-color 0.3s ease; +} + +ul li a:hover { + background-color: #3498db; +} + +/* Search Results */ +.search-results { + margin-top: 20px; +} + +.search-results p { + padding: 10px; + background: #ecf0f1; + border-left: 5px solid #2980b9; + margin-bottom: 10px; +} + +hr { + border: 0; + height: 1px; + background: #ddd; + margin: 20px 0; +} + +/* Footer */ +footer { + text-align: center; + margin-top: 20px; + padding: 20px; + background-color: #2980b9; + color: white; +} + +input[type="text"], +textarea, +select { + width: 100%; /* Take full width of the container */ + padding: 10px; /* Add padding for comfort */ + border: 1px solid #ccc; /* Border style */ + border-radius: 4px; /* Rounded corners */ + box-sizing: border-box; /* Include padding in width */ +} + +textarea { + height: 100px; /* Set a height for the textarea */ +} +/* Search Results Styles */ +.results { + margin-top: 30px; /* Space above search results */ + text-align: left; /* Align results to the left */ +} + +.results ul { + list-style-type: none; /* Remove default list styles */ + padding: 0; /* Remove padding */ +} + +.results li { + background-color: #f4f4f9; /* Light background for entries */ + border: 1px solid #ccc; /* Border for each entry */ + border-radius: 4px; /* Rounded corners */ + padding: 10px; /* Padding for comfort */ + margin-bottom: 15px; /* Space between entries */ +} \ No newline at end of file diff --git a/My-Personal-Journal/templates/add.html b/My-Personal-Journal/templates/add.html new file mode 100644 index 0000000..a7a7afe --- /dev/null +++ b/My-Personal-Journal/templates/add.html @@ -0,0 +1,45 @@ + + + + + + Add New Entry + + + +
+

Add New Journal Entry

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+

© 2024 Personal Journal

+
+ + diff --git a/My-Personal-Journal/templates/index.html b/My-Personal-Journal/templates/index.html new file mode 100644 index 0000000..99c420f --- /dev/null +++ b/My-Personal-Journal/templates/index.html @@ -0,0 +1,24 @@ + + + + + + Personal Journal + + + +
+

Welcome to Your Personal Journal

+
+ +
+

© 2024 Personal Journal

+
+ + diff --git a/My-Personal-Journal/templates/search.html b/My-Personal-Journal/templates/search.html new file mode 100644 index 0000000..850b1fa --- /dev/null +++ b/My-Personal-Journal/templates/search.html @@ -0,0 +1,16 @@ + + + + Search Journal Entries + + + + +
+

Search Journal Entries

+
+ Search by keyword or date (YYYY-MM-DD):
+ +
+ + diff --git a/My-Personal-Journal/templates/search_results.html b/My-Personal-Journal/templates/search_results.html new file mode 100644 index 0000000..dbb709d --- /dev/null +++ b/My-Personal-Journal/templates/search_results.html @@ -0,0 +1,22 @@ + + + + Search Results + + + + +

Journal Entries

+ +
+ {% for result in results %} +

Date: {{ result[2] }}, Mood: {{ result[3] }}, Tags: {{ result[5] }}

+

{{ result[4] }}

+
+ {% else %} +

No entries found.

+ {% endfor %} +
+ + + diff --git a/My-Personal-Journal/templates/tags.html b/My-Personal-Journal/templates/tags.html new file mode 100644 index 0000000..7b3f80a --- /dev/null +++ b/My-Personal-Journal/templates/tags.html @@ -0,0 +1,18 @@ + + + + Tags + + + + +

Tags

+
    + {% for tag in tags %} +
  • {{ tag }}
  • + {% else %} +
  • No tags found.
  • + {% endfor %} +
+ + diff --git a/My-Personal-Journal/ui.py b/My-Personal-Journal/ui.py new file mode 100644 index 0000000..16ac9dd --- /dev/null +++ b/My-Personal-Journal/ui.py @@ -0,0 +1,162 @@ +# from main import add_entry, search_entries +# import datetime + +# def display_menu(): +# print("\n=== My Personal Journal ===") +# print("1. Create New Journal Entry") +# print("2. Search Journal Entries") +# print("3. Exit") + +# def get_mood(): +# mood = None +# while mood not in ["happy", "sad", "neutral"]: +# mood = input("How are you feeling today? (happy, sad, neutral): ").lower() +# return mood + +# def get_tags(): +# tags = input("Add tags (comma-separated, e.g., work, personal): ") +# return tags + +# def create_new_entry(user_id): +# mood = get_mood() +# content = input("Write your journal entry: ") +# tags = get_tags() +# add_entry(user_id, mood, content, tags) +# print("Your entry has been saved!") + +# def search_journal_entries(user_id): +# print("\nSearch Entries") +# print("1. Search by keyword") +# print("2. Search by date") +# choice = input("Choose a search option: ") + +# if choice == '1': +# search_term = input("Enter a keyword to search for: ") +# results = search_entries(user_id, search_term=search_term) +# elif choice == '2': +# date_str = input("Enter a date (YYYY-MM-DD) to search: ") +# try: +# date = datetime.datetime.strptime(date_str, '%Y-%m-%d') +# except ValueError: +# print("Invalid date format. Please use YYYY-MM-DD.") +# return +# results = search_entries(user_id, date=date) +# else: +# print("Invalid option.") +# return + +# if results: +# for entry in results: +# print(f"\nDate: {entry[2]}") +# print(f"Mood: {entry[3]}") +# print(f"Tags: {entry[5]}") +# print(f"Entry: {entry[4]}") +# print("-" * 40) +# else: +# print("No entries found for your search criteria.") + +# def main_ui(): +# user_id = input("Enter your user ID to start: ") + +# while True: +# display_menu() +# choice = input("Select an option (1-3): ") + +# if choice == '1': +# create_new_entry(user_id) +# elif choice == '2': +# search_journal_entries(user_id) +# elif choice == '3': +# print("Goodbye!") +# break +# else: +# print("Invalid choice. Please try again.") + +# if __name__ == "__main__": +# main_ui() +import tkinter as tk +from tkinter import messagebox +from journal_app import add_entry, search_entries +from datetime import datetime + +class JournalApp(tk.Tk): + def __init__(self): + super().__init__() + + self.title("Personal Journal") + self.geometry("400x400") + + self.label = tk.Label(self, text="Personal Journal", font=("Helvetica", 16)) + self.label.pack(pady=10) + + self.add_button = tk.Button(self, text="Add New Entry", command=self.add_entry) + self.add_button.pack(pady=5) + + self.search_button = tk.Button(self, text="Search Entries", command=self.search_entries) + self.search_button.pack(pady=5) + + def add_entry(self): + self.new_window = tk.Toplevel(self) + self.new_window.title("Add New Entry") + + mood_label = tk.Label(self.new_window, text="Mood (happy, sad, neutral):") + mood_label.pack(pady=5) + self.mood_entry = tk.Entry(self.new_window) + self.mood_entry.pack(pady=5) + + content_label = tk.Label(self.new_window, text="Write your journal entry:") + content_label.pack(pady=5) + self.content_entry = tk.Text(self.new_window, height=5, width=30) + self.content_entry.pack(pady=5) + + tags_label = tk.Label(self.new_window, text="Tags (comma-separated):") + tags_label.pack(pady=5) + self.tags_entry = tk.Entry(self.new_window) + self.tags_entry.pack(pady=5) + + submit_button = tk.Button(self.new_window, text="Submit", command=self.save_entry) + submit_button.pack(pady=10) + + def save_entry(self): + mood = self.mood_entry.get() + content = self.content_entry.get("1.0", tk.END) + tags = self.tags_entry.get() + + if mood and content: + add_entry("user_1", mood, content, tags) + messagebox.showinfo("Success", "Journal entry saved!") + self.new_window.destroy() + else: + messagebox.showwarning("Input Error", "Please fill in all fields.") + + def search_entries(self): + self.search_window = tk.Toplevel(self) + self.search_window.title("Search Entries") + + search_label = tk.Label(self.search_window, text="Search by keyword or date (YYYY-MM-DD):") + search_label.pack(pady=5) + self.search_entry = tk.Entry(self.search_window) + self.search_entry.pack(pady=5) + + search_button = tk.Button(self.search_window, text="Search", command=self.perform_search) + search_button.pack(pady=10) + + def perform_search(self): + search_term = self.search_entry.get() + results = search_entries("user_1", search_term=search_term) + + if results: + result_window = tk.Toplevel(self) + result_window.title("Search Results") + + for result in results: + result_label = tk.Label(result_window, text=f"Date: {result[2]}, Mood: {result[3]}, Tags: {result[5]}") + result_label.pack() + content_label = tk.Label(result_window, text=f"Entry: {result[4]}") + content_label.pack(pady=5) + else: + messagebox.showinfo("No Results", "No journal entries found.") + +if __name__ == "__main__": + app = JournalApp() + app.mainloop() From b44ebf6b3bb428cdb865bb0cf878ed312092cd2c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 21 Oct 2024 17:45:56 +0000 Subject: [PATCH 22/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index 784002f..dc9d10c 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -34,6 +34,7 @@ * [Telegram Bot](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Telegram%20Bot) * [Text To Speech](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20To%20Speech) * [Text to Morse Code](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20to%20Morse%20Code) +* [Tic-Tac-Toc using AI (min-max)](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Tic-Tac-Toc%20using%20AI%20(min-max)) * [To Do App](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/To%20Do%20App) * [Translator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Translator) * [URL Sortener](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/URL%20Sortener) From 4e52a827a4ae5a07faf1e3dde9569f602fe66a39 Mon Sep 17 00:00:00 2001 From: Himanshu Mahajan <83700343+himanshumahajan138@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:27:30 +0530 Subject: [PATCH 23/38] Update README.md --- Text Summarizer/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Text Summarizer/README.md b/Text Summarizer/README.md index 8d7f00c..ceff2a6 100644 --- a/Text Summarizer/README.md +++ b/Text Summarizer/README.md @@ -1,7 +1,3 @@ -Here's a professional README documentation for the provided TextRank Text Summarization script: - ---- - # TextRank-based Text Summarization This project implements a **TextRank-based approach** to extract summaries from large textual data, such as articles. The summarization algorithm ranks sentences based on their relevance and importance, using concepts derived from the PageRank algorithm applied to text. From b4ecb7c81fa4432e27f5c555389f37c5b38f903a Mon Sep 17 00:00:00 2001 From: Himanshu Mahajan <83700343+himanshumahajan138@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:29:07 +0530 Subject: [PATCH 24/38] Update README.md --- Text Summarizer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Text Summarizer/README.md b/Text Summarizer/README.md index ceff2a6..15754e0 100644 --- a/Text Summarizer/README.md +++ b/Text Summarizer/README.md @@ -26,7 +26,7 @@ This project implements a **TextRank-based approach** to extract summaries from 1. Clone the repository: ```bash - git clone + git clone https://github.com/king04aman/All-In-One-Python-Projects.git ``` 2. Install the required Python libraries: From fd791489c2234358aa31d52ec903a032aba33b75 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 21 Oct 2024 18:01:36 +0000 Subject: [PATCH 25/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index dc9d10c..21caf66 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -32,6 +32,7 @@ * [Speech To Text](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Speech%20To%20Text) * [Spell Checker](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Spell%20Checker) * [Telegram Bot](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Telegram%20Bot) +* [Text Summarizer](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20Summarizer) * [Text To Speech](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20To%20Speech) * [Text to Morse Code](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20to%20Morse%20Code) * [Tic-Tac-Toc using AI (min-max)](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Tic-Tac-Toc%20using%20AI%20(min-max)) From 56505910ac8a193bc4347c34a46f07e3c8653dcf Mon Sep 17 00:00:00 2001 From: Aman Kumar <62813940+king04aman@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:54:37 +0530 Subject: [PATCH 26/38] fix: contributors img loading --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4626b4f..270a8d7 100644 --- a/README.md +++ b/README.md @@ -63,11 +63,15 @@ These instructions will get you a copy of the project up and running on your loc Thanks go to these **Wonderful Contributors** ✨✨: - - - Contributors - - + + + + +
+ + + +

From 2477fc9289e2630f4c689d815a951c4870130355 Mon Sep 17 00:00:00 2001 From: Aman Kumar <62813940+king04aman@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:55:02 +0530 Subject: [PATCH 27/38] Delete CONTRIBUTORS.svg --- CONTRIBUTORS.svg | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 CONTRIBUTORS.svg diff --git a/CONTRIBUTORS.svg b/CONTRIBUTORS.svg deleted file mode 100644 index 608028b..0000000 --- a/CONTRIBUTORS.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From a5a97ef7a6e51f1fb887a5957a55992f7232abd5 Mon Sep 17 00:00:00 2001 From: Aman Kumar <62813940+king04aman@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:55:40 +0530 Subject: [PATCH 28/38] Delete contributors workflow --- .github/workflows/contributors.yml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .github/workflows/contributors.yml diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml deleted file mode 100644 index e0333ed..0000000 --- a/.github/workflows/contributors.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Contributors - -on: - schedule: - - cron: '0 0 * * *' - -jobs: - contributors: - runs-on: ubuntu-latest - steps: - - uses: wow-actions/contributors-list@v1 - with: - GITHUB_TOKEN: ${{ secrets.ACTION_TOKEN }} - round: true - svgPath: CONTRIBUTORS.svg From 7b47319e115bff8789715c7ea4a1e68db2e1e9e9 Mon Sep 17 00:00:00 2001 From: Aman Kumar <62813940+king04aman@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:56:55 +0530 Subject: [PATCH 29/38] enhance welcome workflow --- .github/workflows/welcome.yml | 84 ++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/.github/workflows/welcome.yml b/.github/workflows/welcome.yml index d020de8..f72cb0d 100644 --- a/.github/workflows/welcome.yml +++ b/.github/workflows/welcome.yml @@ -1,40 +1,80 @@ -name: New Contributor Welcome +name: Welcome Comments permissions: actions: write + attestations: write checks: write contents: write + deployments: write + id-token: write issues: write + discussions: write + packages: write + pages: write pull-requests: write + repository-projects: write + security-events: write + statuses: write on: - pull_request: - types: [opened, closed] issues: - types: [opened] + types: [opened, closed] + pull_request_target: + types: [opened, closed] jobs: - greet_new_contributor: + welcomer: runs-on: ubuntu-latest steps: - - uses: bubkoo/welcome-action@v1 + - name: Auto Welcome on Issues or PRs + uses: actions/github-script@v6 with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FIRST_ISSUE_REACTIONS: "+1, hooray, rocket, heart" - FIRST_ISSUE: > - 👋 Greetings @{{ author }}! - - We're thrilled to see you opening your first issue! Your input is invaluable to us. Don’t forget to adhere to our issue template for the best experience. - - FIRST_PR: > - 👋 Welcome aboard, @{{ author }}! + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const author = context.payload.sender.login; + const commentBody = (message) => `👋 @${author} 👋\n\n${message}`; - We're delighted to have your first pull request! Please take a moment to check our contributing guidelines to ensure a smooth process. + if (context.eventName === 'issues') { + const issue = context.payload.issue; - FIRST_PR_MERGED: > - 🎉 Kudos @{{ author }}! + if (context.payload.action === 'opened') { + const message = `We're thrilled to see you opening an issue! Your input is valuable to us. Don’t forget to fill out our issue template for the best experience. We will look into it soon.`; + github.rest.issues.createComment({ + issue_number: issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: commentBody(message), + }); + } else if (context.payload.action === 'closed') { + const message = `Thanks for closing the issue! We appreciate your updates.`; + github.rest.issues.createComment({ + issue_number: issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: commentBody(message), + }); + } + } else if (context.eventName === 'pull_request_target') { + const pr = context.payload.pull_request; - You've just merged your first pull request! We're excited to have you in our community. Keep up the fantastic contributions! - STAR_MESSAGE: If you enjoy this project, please consider ⭐ starring ⭐ this repository! - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if (context.payload.action === 'opened') { + const message = `We're delighted to have your pull request! Please take a moment to check our contributing guidelines and ensure you've filled out the PR template for a smooth process. We will review it soon.`; + github.rest.issues.createComment({ + issue_number: pr.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: commentBody(message), + }); + } else if (context.payload.action === 'closed') { + const message = pr.merged + ? `🎉 You've just merged your pull request! We're excited to have you in our community. Keep up the fantastic contributions to the project!` + : `Thanks for closing the pull request! Your contributions are valuable to us.`; + + github.rest.issues.createComment({ + issue_number: pr.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: commentBody(message), + }); + } + } From 9dbbb35706f7883e9174fb7556babb93fb0a2064 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Oct 2024 16:40:06 +0000 Subject: [PATCH 30/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index 21caf66..be0dd08 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -22,6 +22,7 @@ * [Notepad](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Notepad) * [Password Generator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Password%20Generator) * [Plagiarism-Checker](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Plagiarism-Checker) +* [Pomodoro Timer](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Pomodoro%20Timer) * [QR Code Generator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/QR%20Code%20Generator) * [Random Movie Selector](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Random%20Movie%20Selector) * [Random Quotes Generator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Random%20Quotes%20Generator) From 9e5ff78eaf890976831de1d8537d313ae747dfe2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Oct 2024 17:07:16 +0000 Subject: [PATCH 31/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index be0dd08..4fc301e 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -20,6 +20,7 @@ * [MobileNumber Tracker](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/MobileNumber%20Tracker) * [Movie Scraper](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Movie%20Scraper) * [Notepad](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Notepad) +* [OCR Image-to-Text Conversion](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/OCR%20Image-to-Text%20Conversion) * [Password Generator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Password%20Generator) * [Plagiarism-Checker](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Plagiarism-Checker) * [Pomodoro Timer](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Pomodoro%20Timer) From 7aa5b80fd14894b9436ddc3a58846c470082ad17 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Oct 2024 17:08:03 +0000 Subject: [PATCH 32/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index 4fc301e..47ed617 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -16,6 +16,7 @@ * [Image Compression](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Image%20Compression) * [ImageSize Reducer](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/ImageSize%20Reducer) * [Img-Steganograpy](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Img-Steganograpy) +* [Mental Health chatbot](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Mental%20Health%20chatbot) * [Merge PDFs](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Merge%20PDFs) * [MobileNumber Tracker](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/MobileNumber%20Tracker) * [Movie Scraper](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Movie%20Scraper) From 6ac43f3880a8b69210f8354e8dbe2fc59b5d9f2d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Oct 2024 17:08:29 +0000 Subject: [PATCH 33/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index 47ed617..94fb8f2 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -40,6 +40,7 @@ * [Text to Morse Code](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20to%20Morse%20Code) * [Tic-Tac-Toc using AI (min-max)](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Tic-Tac-Toc%20using%20AI%20(min-max)) * [To Do App](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/To%20Do%20App) +* [To Do List](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/To%20Do%20List) * [Translator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Translator) * [URL Sortener](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/URL%20Sortener) * [Validate-Email](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Validate-Email) From a8b0517ac46b8b29255a2caa4621990b3091c416 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Oct 2024 17:12:02 +0000 Subject: [PATCH 34/38] Update project list --- PROJECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PROJECTS.md b/PROJECTS.md index 94fb8f2..ca3b8c0 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -20,6 +20,7 @@ * [Merge PDFs](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Merge%20PDFs) * [MobileNumber Tracker](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/MobileNumber%20Tracker) * [Movie Scraper](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Movie%20Scraper) +* [My-Personal-Journal](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/My-Personal-Journal) * [Notepad](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Notepad) * [OCR Image-to-Text Conversion](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/OCR%20Image-to-Text%20Conversion) * [Password Generator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Password%20Generator) From 733085c3a0a89abea90dd93602dde04f525e55fb Mon Sep 17 00:00:00 2001 From: Aman Kumar Date: Tue, 22 Oct 2024 23:10:35 +0530 Subject: [PATCH 35/38] refactor: mv enhanced ToDo App -> ToDoList/usr-name/ToDo App --- .../RithwikBejadi/To Do App}/README.md | 0 .../RithwikBejadi/To Do App}/To_Do_AppTkInter.py | 0 .../RithwikBejadi/To Do App}/requirements.txt | 0 .../RithwikBejadi/To Do App}/runtime.txt | 0 .../RithwikBejadi/To Do App}/tasks.db | Bin 5 files changed, 0 insertions(+), 0 deletions(-) rename {To Do App => To Do List/RithwikBejadi/To Do App}/README.md (100%) rename {To Do App => To Do List/RithwikBejadi/To Do App}/To_Do_AppTkInter.py (100%) rename {To Do App => To Do List/RithwikBejadi/To Do App}/requirements.txt (100%) rename {To Do App => To Do List/RithwikBejadi/To Do App}/runtime.txt (100%) rename {To Do App => To Do List/RithwikBejadi/To Do App}/tasks.db (100%) diff --git a/To Do App/README.md b/To Do List/RithwikBejadi/To Do App/README.md similarity index 100% rename from To Do App/README.md rename to To Do List/RithwikBejadi/To Do App/README.md diff --git a/To Do App/To_Do_AppTkInter.py b/To Do List/RithwikBejadi/To Do App/To_Do_AppTkInter.py similarity index 100% rename from To Do App/To_Do_AppTkInter.py rename to To Do List/RithwikBejadi/To Do App/To_Do_AppTkInter.py diff --git a/To Do App/requirements.txt b/To Do List/RithwikBejadi/To Do App/requirements.txt similarity index 100% rename from To Do App/requirements.txt rename to To Do List/RithwikBejadi/To Do App/requirements.txt diff --git a/To Do App/runtime.txt b/To Do List/RithwikBejadi/To Do App/runtime.txt similarity index 100% rename from To Do App/runtime.txt rename to To Do List/RithwikBejadi/To Do App/runtime.txt diff --git a/To Do App/tasks.db b/To Do List/RithwikBejadi/To Do App/tasks.db similarity index 100% rename from To Do App/tasks.db rename to To Do List/RithwikBejadi/To Do App/tasks.db From cbf65e3d8300835b575150a50a4db10d7b8dae2a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 22 Oct 2024 17:41:19 +0000 Subject: [PATCH 36/38] Update project list --- PROJECTS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/PROJECTS.md b/PROJECTS.md index ca3b8c0..5d9d38c 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -40,7 +40,6 @@ * [Text To Speech](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20To%20Speech) * [Text to Morse Code](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Text%20to%20Morse%20Code) * [Tic-Tac-Toc using AI (min-max)](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Tic-Tac-Toc%20using%20AI%20(min-max)) -* [To Do App](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/To%20Do%20App) * [To Do List](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/To%20Do%20List) * [Translator](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/Translator) * [URL Sortener](https://github.com/king04aman/All-In-One-Python-Projects/tree/main/URL%20Sortener) From 50ad2c4746eac974b8f7a1e342b9a4e95434ff4c Mon Sep 17 00:00:00 2001 From: Makwana Raj <151895608+raj-mistry-01@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:27:23 +0530 Subject: [PATCH 37/38] Voice Assistant Added --- .../raj_mistry01/Voice Assistant/Readme.md | 144 +++++++ .../raj_mistry01/Voice Assistant/main.py | 354 ++++++++++++++++++ .../Voice Assistant/requirements.txt | 15 + 3 files changed, 513 insertions(+) create mode 100644 Simple Assistant/raj_mistry01/Voice Assistant/Readme.md create mode 100644 Simple Assistant/raj_mistry01/Voice Assistant/main.py create mode 100644 Simple Assistant/raj_mistry01/Voice Assistant/requirements.txt diff --git a/Simple Assistant/raj_mistry01/Voice Assistant/Readme.md b/Simple Assistant/raj_mistry01/Voice Assistant/Readme.md new file mode 100644 index 0000000..92b4a02 --- /dev/null +++ b/Simple Assistant/raj_mistry01/Voice Assistant/Readme.md @@ -0,0 +1,144 @@ +# Jarvis - A Personal Voice Assistant 🗣️💻 + +This **Jarvis Personal Assistant** is a Python-based virtual assistant that can execute commands, automate tasks, and provide information at your request. It can help you manage files, open applications, search Wikipedia, forecast weather, and much more—all through voice commands. + +## 🚀 Features + +1. **Voice & Text Interaction** + - Provides **voice recognition** using Google Speech Recognition API. + - Users can **switch to text mode** if speech recognition fails. + +2. **Application Management** + - Open or close **Notepad** and **Command Prompt**. + - Manage system **battery levels** with alerts and suggestions. + +3. **Information Retrieval** + - Get **Wikipedia summaries** for any topic. + - **Weather forecasts** by city or location-based. + - Check your **IP address** using an online API. + +4. **Entertainment & Media** + - Search for **movie details** via IMDb, including cast, plot, and ratings. + - Open **YouTube** and automate subscriptions. + +5. **System Control** + - Adjust **volume controls**: Increase, decrease, or mute. + - Minimize or maximize windows using **keyboard automation**. + - Track **internet speed** with Speedtest integration. + +6. **Utility Features** + - Control **Webcam** access and capture videos. + - Perform calculations using **Wolfram Alpha**. + - Automatically **open websites** using Chrome. + - Monitor **system processes** and terminate them on command. + +--- + +## 🔧 Setup Instructions + +1. **Clone the Repository** + ```bash + git clone https://github.com/yourusername/jarvis-assistant.git + cd jarvis-assistant + ``` + +2. **Install Dependencies** + Install all necessary Python packages using: + ```bash + pip install -r requirements.txt + ``` + +3. **Add Paths for Applications** + Set the paths for: + - **Chrome browser**: `"C:/Program Files/Google/Chrome/Application/chrome.exe"` + - **Notepad**: `"C:/Windows/System32/notepad.exe"` + - **Visual Studio Code** (optional): Adjust the path as per your installation. + +4. **Get API Keys** + - **OpenWeather API**: [Sign up here](https://openweathermap.org/) and replace `apiKey` in the code. + - **Wolfram Alpha API**: Get an API key [here](https://products.wolframalpha.com/api/). + +--- + +## 🧑‍💻 Usage Instructions + +1. **Launch the Assistant** + Run the script: + ```bash + python jarvis.py + ``` + +2. **Speak Commands**: + - "Open Notepad" – Launches Notepad. + - "What is the weather report?" – Gives the weather of your current location. + - "Search for Titanic on Wikipedia" – Provides a brief Wikipedia summary. + - "Close Command Prompt" – Terminates the Command Prompt if running. + - "What's my IP address?" – Provides your public IP address. + +3. **Text Mode** + If the voice input isn't recognized, type your queries when prompted. + +4. **Pause or Stop Listening**: + - Say **"Stop listening"**: Pauses the assistant. + - Resume by pressing **Ctrl + Alt + K**. + - Say **"No query, thanks"** to exit the assistant. + +--- + +## 🌦️ Example Queries + +- **"How are you, Jarvis?"** + → Jarvis responds and continues the conversation. + +- **"Open Command Prompt"** + → Opens the Command Prompt window. + +- **"Mute the volume"** + → Mutes system volume. + +--- + +## 🎯 Known Issues and Limitations + +- Some queries require accurate phrasing. +- Voice recognition may fail in noisy environments. +- Web automation depends on having Chrome installed. +- Weather reports return temperature in **Kelvin** by default (can be adjusted). + +--- + +## 💡 Future Improvements + +- Add **Gmail** integration to send emails. +- Support for **natural conversations** with chat history. +- **Alarm feature** implementation. + +--- + +## 🤖 Contribution + +Feel free to submit pull requests or report bugs/issues. Contributions are welcome to make this assistant smarter and more responsive! + +--- + + +## 🛠️ Prerequisites + +- **Python 3.7+** +- Required Packages (install via `pip`): + ```bash + pip install -r requirements.txt + +--- +## 🛠️ Api Credits + + Wolfram Api + OpenWheather Api + + +- **Python 3.7+** +- Required Packages (install via `pip`): + ```bash + pip install -r requirements.txt + +Enjoy using **Jarvis Personal Assistant**! 😊 diff --git a/Simple Assistant/raj_mistry01/Voice Assistant/main.py b/Simple Assistant/raj_mistry01/Voice Assistant/main.py new file mode 100644 index 0000000..35659e0 --- /dev/null +++ b/Simple Assistant/raj_mistry01/Voice Assistant/main.py @@ -0,0 +1,354 @@ +import pyttsx3 +import wmi +import speech_recognition as sr +import datetime +import wolframalpha +import subprocess as sp +import time +import pyautogui +import webbrowser as web +import random +import imdb +import psutil +import requests +import wikipedia +import pywhatkit +import smtplib +import sys +import keyboard +import speedtest +import cv2 +import os +import numpy as np +engine = pyttsx3.init('sapi5') +voices = engine.getProperty("voices") +engine.setProperty('voices',voices[0].id) +runnigprocesslist = [] +f = wmi.WMI() +flag = 0 +def speak(audio) : + print("Jarvis : ",end="") + engine.say(audio) + print(audio) + engine.runAndWait() +def takecommand() : + r = sr.Recognizer() + with sr.Microphone() as source : + print("Listening ...") + r.adjust_for_ambient_noise(source) + r.pause_threshold =1 + audio = r.listen(source,phrase_time_limit=5) + try : + print("Recongnizing ..") + text = r.recognize_google(audio,language = "en-in") + print("User said : "+text) + except Exception as e : + print("Say that again : ") + return "none" + return text +def startlistening(): + print("Started Listening : ") + +def pauseListening() : + print("Paused Listening :") + +def weatherforecast(city) : + apiKey = "apiKey" + res = requests.get(f"openWeatherApiEndpoint").json() + weather_ = res["weather"][0]["main"] + temp = res["main"]["temp"] + feels_like = res["main"]["feels_like"] + return weather_,temp,feels_like + +def wish() : + hour = int(datetime.datetime.now().hour) + if hour >= 0 and hour <= 12 : + speak("Good morning :") + elif hour > 12 and hour <= 18 : + speak("Good afternoon :") + else : + speak("Good evening : ") + speak("I am jarvis ,sir how can I assist you?") +# def sendEmail(to,content) : +# server = smtplib.SMTP("smtp.gmail.com",587) +# server.ehlo() +# server.starttls() +# server.login("emailId","yourpswd") +# server.sendmail("emailId","toemail") +# server.close() +if __name__ == "__main__" : + wish() + def main() : + global runnigprocesslist + tries = 0 + query = "" + flag_ = 0 + flagForText = 0 + while True: + if tries < 3 : + if flag_ == 0 : + query = takecommand().lower() + tries += 1 + else : + if flagForText == 1: + query = input("(Prees V + Enter to turn voice chat again)Enter your query in text : ") + if query == "V" : + flag_ = 0 + flagForText = 0 + pass + else : + pass + else : + flag_ = 0 + pass + if "stop listening" in query : + pauseListening() + speak("Press ctrl+alt+k to continue listening.") + break + elif "open notepad" in query : + tries = 0 + path = "" # path to notepad + speak("Opening NOtepad sir.") + os.startfile(path) + elif "close notepad" in query : + tries = 0 + for process in f.Win32_Process() : + runnigprocesslist.append(process.Name) + if "Notepad.exe" in runnigprocesslist : + speak("Closing the notepad.") + os.system("taskkill /f /im notepad.exe") + flag = 1 + runnigprocesslist = [] + else : + speak("Notepad is not opened.") + elif "stop listening" in query : + tries = 0 + speak("Press ctrl+alt+p to pause the listening") + elif "how are you jarvis" in query : + tries = 0 + speak("I am fine sir , What about you ?? Sir.") + query = takecommand().lower() + if "not feeling good" or "sad" or "bad day" in query : + speak("What happend sir ,Please Tell me , May I help you ?") + query = takecommand().lower() + if "disease" in query : + query = query.replace(query,"drreddys.com",1) + path = "" # path to chrome + web.register("chrome",None,web.BackgroundBrowser(path)) + web.get("chrome").open_new(query) + else : + pass + elif "good" or "feeling happy" in query : + speak("Ok sir , It seems to be nice to hear.") + elif "open command prompt" in query : + tries = 0 + speak("Opening the command propmpt.") + os.system("start cmd") + elif "close command prompt" in query : + tries = 0 + for process in f.Win32_Process() : + runnigprocesslist.append(process.Name) + if "cmd.exe" in runnigprocesslist : + speak("Closing the command propmt.") + os.system("taskkill /f /im cmd.exe") + flag = 1 + runnigprocesslist = [] + else : + speak("CMD is not opened.") + pass + elif "clear the chat" in query : + tries = 0 + os.system("cls") + elif "are you forget to wish me" in query or "Wish me again" in query : + tries = 0 + wish() + elif "open Webcamera" in query : + tries = 0 + cap = cv2.VideoCapture(0) + while True : + ret , img = cap.read() + cv2.imshow("webcam",img) + k = cv2.waitKey(50) + if k == 27 : + break + cap.release() + cv2.destroyAllWindows() + elif "open camera" in query : + tries = 0 + speak("Opening Camera sir") + sp.run("start microsoft.windows.camera:",shell= True) + elif "close camera" in query : + tries = 0 + for process in f.Win32_Process() : + runnigprocesslist.append(process.Name) + if "WindowsCamera.exe" in runnigprocesslist : + speak("Closing the camera.") + flag = 1 + os.system("taskkill /f /im WindowsCamera.exe") + runnigprocesslist = [] + else : + speak("Camera is not opened.") + elif "calculate" in query : + # api = "apiKey" + client = wolframalpha.Client(api) + query = takecommand().lower() + ind = query.split().index("calculate") + text = query.split()[ind+1:] + result = client.query(" ".join(text)) + try : + ans = next(result.results).text + speak("The answer is " + ans) + except StopIteration : + speak("I could not find it , Please say it again.") + elif "ip address" in query : + tries = 0 + ip = requests.get("apiKeyOfipyfyConfig").json() + speak("Your Ip address is : " + ip["ip"]) + elif "wikipedia" in query : + tries = 0 + speak("Searching in the wikipedia") + query = query.replace("wikipedia","") + results = wikipedia.summary(query,sentences=2) + speak("According to wikipedia ") + speak(results) + print(results) + elif "open visual code" in query : + tries = 0 + path = "" # path to Vscode.exe + os.startfile(path) + elif "weather report" in query : + tries = 0 + ipAdd = requests.get("apiKeyOfipyfyConfig").json() + ipnum = ipAdd["ip"] + city = requests.get(f"apiKeyOfipyfyConfigEndpoint").text + weather , temp , feels_like = weatherforecast(city) + speak(f"The weather report talks about {weather}.") + speak(f"The temparature is {temp} kelvin.") + speak(f"It feels like {feels_like} kelvin.") + elif "weather of my city" in query : + tries = 0 + speak("Sir tell me your city name : ") + city = input("Enter the name of your city : ") + speak(f"Getting the weather of {city} : ") + weather , temp , feels_like = weatherforecast(city) + speak(f"The weather report talks about {weather}.") + speak(f"The temparature is {temp} kelvin.") + speak(f"It feels like {feels_like} kelvin.") + elif ".com" in query: + tries = 0 + path = "" # path to chrome + web.register("chrome",None,web.BackgroundBrowser(path)) + web.get("chrome").open_new(query) + elif "movie" in query : + movieDb = imdb.IMDb() + speak("Input the name of movie in text") + movieName = input("Enter the name : ") + movies = movieDb.search_movie(movieName) + speak("Searching for... " + movieName) + speak("I found these") + for movie in movies : + title = movie["title"] + year = movie["year"] + info = movie.getID() + movieInfo = movieDb.get_movie(info) + rating = movieInfo["rating"] + cast = movieInfo["cast"] + actor = cast[0:5] + plot = movieInfo.get('plot outline','plot summary not available') + speak(f"{title} movie in {year} has an imdb rating of {rating}.") + speak(f"It has a cast of {actor} . The plot of the movie is {plot}. ") + # elif "send message" in query: + # tries = 0 + # pywhatkit.sendwhatmsg("tosendPhoneNum","Hi raj",2,25) + # elif "email" in query : + # tries = 0 + # try : + # speak("What should i say") + # content = takecommand().lower() + # to = "toEmailId" + # sendEmail(to,content) + # except Exception as e : + # print(e) + elif "how much battery is left" in query or "power is left" in query or "battery" in query : + tries = 0 + battery = psutil.sensors_battery() + percentage = battery.percent + speak(f"Sir your computer system has left {percentage}% battery power.") + if percentage <= 15 : + speak("Sir you should plug in charger.") + elif percentage >=15 and percentage <= 35 : + speak("Sir it is enough power to run on , but it is advisable to turn on battery saver made.") + speak("Sir Would you like to turn on battery saver mode?") + query = takecommand().lower() + if "yes" in query : + pyautogui.press("win+A") + else : + pass + elif percentage >= 35 and percentage <= 60 : + speak("Sir you should we have enough battery power.") + elif "turn on chat mode" in query or "chat mode" in query or "chat" in query: + tries = 0 + flag_ = 1 + flagForText = 1 + elif "subscribe the coder" in query or "subscribe" in query: + tries = 0 + speak("Whoever using this my created basic voice assistant jarvis , I am thankful , Subscribe to my channel") + speak("Firstly go to Youtube") + path = "pathtoChrome``" # path to chrome + web.register("chrome",None,web.BackgroundBrowser(path)) + web.get("chrome").open_new("https://www.youtube.com/") + speak("Click on the search bar") + pyautogui.moveTo(517,78,1) + pyautogui.click(x=517,y=78,clicks=1,interval=0,button='left') + speak("raj_mistry01 is username.") + pyautogui.typewrite("https://www.youtube.com/@raj_mistry01",0.1) + time.sleep(1) + speak("Press Enter") + pyautogui.press("enter") + speak("Here you will subscribe the channel.") + pyautogui.moveTo(718,602,1) + speak("Click here to subcribe") + pyautogui.click(x=718,y=602,clicks=1,interval=0,button='left') + speak("Thank you for the subscribing Me🙏") + elif "volume up" in query : + tries = 0 + pyautogui.press("volumeup") + elif "volume down" in query : + tries = 0 + pyautogui.press("volumedown") + elif "mute the volume" in query : + tries = 0 + pyautogui.press("volumemute") + elif "turn on the volume" in query : + tries = 0 + pyautogui.press("volumemute") + elif "minimise the window" in query: + tries = 0 + pyautogui.moveTo(1774,32,2) + pyautogui.click(1774,32) + elif "maximize the window" in query : + tries = 0 + pyautogui.moveTo(763,1054,2) + pyautogui.click(763,1054) + elif "internet speed" in query : + tries = 0 + st = speedtest.Speedtest() + download = st.download() + up = st.upload() + speak(f"Sir we have {download} bits downloading speed per second and {up} bits downloading speed per second.") + elif "no query thanks" in query : + tries = 0 + speak("Thanks for using me sir , have a good day.") + sys.exit() + elif "alarm" in query or "set alarm" in query : + pass + speak("Sir do you have any other work : ") + else : + speak("Sir I am unable to recognize the speech.") + speak("Sir it is better to write query in text.") + query = input("Enter the query : ") + query = query.lower() + tries = 0 + flag_ = 1 + flagForText = 0 +main() \ No newline at end of file diff --git a/Simple Assistant/raj_mistry01/Voice Assistant/requirements.txt b/Simple Assistant/raj_mistry01/Voice Assistant/requirements.txt new file mode 100644 index 0000000..2556a85 --- /dev/null +++ b/Simple Assistant/raj_mistry01/Voice Assistant/requirements.txt @@ -0,0 +1,15 @@ +pyttsx3 +wmi +SpeechRecognition +wolframalpha +numpy +pyautogui +requests +wikipedia-api +pywhatkit +smtplib3 +psutil +keyboard +speedtest-cli +opencv-python +imdbpy \ No newline at end of file From 911c129cfc38f4b2842d35ae524e9304aae3cc4e Mon Sep 17 00:00:00 2001 From: Makwana Raj <151895608+raj-mistry-01@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:36:14 +0530 Subject: [PATCH 38/38] Updated Folder Structure --- Simple Assistant/raj_mistry01/{Voice Assistant => }/Readme.md | 0 Simple Assistant/raj_mistry01/{Voice Assistant => }/main.py | 0 .../raj_mistry01/{Voice Assistant => }/requirements.txt | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Simple Assistant/raj_mistry01/{Voice Assistant => }/Readme.md (100%) rename Simple Assistant/raj_mistry01/{Voice Assistant => }/main.py (100%) rename Simple Assistant/raj_mistry01/{Voice Assistant => }/requirements.txt (100%) diff --git a/Simple Assistant/raj_mistry01/Voice Assistant/Readme.md b/Simple Assistant/raj_mistry01/Readme.md similarity index 100% rename from Simple Assistant/raj_mistry01/Voice Assistant/Readme.md rename to Simple Assistant/raj_mistry01/Readme.md diff --git a/Simple Assistant/raj_mistry01/Voice Assistant/main.py b/Simple Assistant/raj_mistry01/main.py similarity index 100% rename from Simple Assistant/raj_mistry01/Voice Assistant/main.py rename to Simple Assistant/raj_mistry01/main.py diff --git a/Simple Assistant/raj_mistry01/Voice Assistant/requirements.txt b/Simple Assistant/raj_mistry01/requirements.txt similarity index 100% rename from Simple Assistant/raj_mistry01/Voice Assistant/requirements.txt rename to Simple Assistant/raj_mistry01/requirements.txt