From 8094374a97cfeafe549b94bb192e0be7ad476845 Mon Sep 17 00:00:00 2001 From: DEEPANSHU BAGHEL <92099428+deepanshubaghel@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:10:51 +0530 Subject: [PATCH 01/73] Bouncing ball simulator Added --- Bouncing ball simulator/README.md | 16 ++++++ Bouncing ball simulator/background-img.jpg | Bin 0 -> 20864 bytes Bouncing ball simulator/ball.png | Bin 0 -> 1533 bytes Bouncing ball simulator/ball_bounce.py | 56 +++++++++++++++++++++ Bouncing ball simulator/requirements.txt | 1 + 5 files changed, 73 insertions(+) create mode 100644 Bouncing ball simulator/README.md create mode 100644 Bouncing ball simulator/background-img.jpg create mode 100644 Bouncing ball simulator/ball.png create mode 100644 Bouncing ball simulator/ball_bounce.py create mode 100644 Bouncing ball simulator/requirements.txt diff --git a/Bouncing ball simulator/README.md b/Bouncing ball simulator/README.md new file mode 100644 index 0000000..1267860 --- /dev/null +++ b/Bouncing ball simulator/README.md @@ -0,0 +1,16 @@ +# Bouncing ball simulator +This script shows the simulation of few balls bouncing in a container under gravity. +They also collide with the bottom part and the walls of the container. + +### Prerequisites +The script runs in python3. +pygame module is needed + +pip3 install requirements.txt + +### How to run the script +Navigate to the folder where the source code is written. +Open a terminal and execute the command: + +python3 ball_bounce.py + diff --git a/Bouncing ball simulator/background-img.jpg b/Bouncing ball simulator/background-img.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c6c7c16f6492c686b6efa859732bc1e9d98d5af5 GIT binary patch literal 20864 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�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 literal 0 HcmV?d00001 diff --git a/Bouncing ball simulator/ball_bounce.py b/Bouncing ball simulator/ball_bounce.py new file mode 100644 index 0000000..21bced2 --- /dev/null +++ b/Bouncing ball simulator/ball_bounce.py @@ -0,0 +1,56 @@ +#This program shows the simulation of 5 balls bouncing under gravitational acceleration. +#It is also accompanied by eleastic collission with walls of the container. +#It is fun to watch. +import pygame,time,random + +pygame.init() + +#setting screen size of pygame window to 800 by 600 pixels +screen=pygame.display.set_mode((800,600)) +background=pygame.image.load('background-img.jpg') + +#Adding title +pygame.display.set_caption('Ball Bounce Simulation') + +class ball: + ball_image=pygame.image.load('ball.png') + g=1 + def __init__(self): + self.velocityX=4 + self.velocityY=4 + self.X=random.randint(0,768) + self.Y=random.randint(0,350) + + def render_ball(self): + screen.blit(ball.ball_image, (self.X,self.Y)) + def move_ball(self): + #changing y component of velocity due to downward acceleration + self.velocityY+=ball.g + #changing position based on velocity + self.X+=self.velocityX + self.Y+=self.velocityY + #collission with the walls lead to change in velocity + if self.X<0 or self.X>768: + self.velocityX*=-1 + if self.Y<0 and self.velocityY<0: + self.velocityY*=-1 + self.Y=0 + if self.Y>568 and self.velocityY>0: + self.velocityY*=-1 + self.Y=568 +#list of balls created as objects +Ball_List=[ball(),ball(), ball(), ball(), ball()] + +#The main program loop +running=True +while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running=False + + time.sleep(0.02) + screen.blit(background, (0,0)) + for ball_item in Ball_List: + ball_item.render_ball() + ball_item.move_ball() + pygame.display.update() \ No newline at end of file diff --git a/Bouncing ball simulator/requirements.txt b/Bouncing ball simulator/requirements.txt new file mode 100644 index 0000000..639e89a --- /dev/null +++ b/Bouncing ball simulator/requirements.txt @@ -0,0 +1 @@ +pygame==2.0.2 \ No newline at end of file From 64bce3054dff0ca762009cb91d76314f49165e56 Mon Sep 17 00:00:00 2001 From: Aryan Date: Wed, 16 Oct 2024 17:35:47 +0530 Subject: [PATCH 02/73] Add files via upload --- expense_tracker.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 expense_tracker.py diff --git a/expense_tracker.py b/expense_tracker.py new file mode 100644 index 0000000..5c5d210 --- /dev/null +++ b/expense_tracker.py @@ -0,0 +1,88 @@ +import os +import json +from datetime import datetime + +# File to store expense data +EXPENSE_FILE = "expenses.json" +expense_data = [] + +def load_expenses(): + global expense_data + if os.path.exists(EXPENSE_FILE): + with open(EXPENSE_FILE, "r") as file: + expense_data = json.load(file) + print("Loaded expense data.") + else: + print("No expense data to load.") + +def save_expenses_to_file(): + with open(EXPENSE_FILE, "w") as file: + json.dump(expense_data, file, indent=4) + +def show_expenses(): + if expense_data: + print("Expense History:") + for entry in expense_data: + date = entry['date'] + amount = entry['amount'] + category = entry['category'] + description = entry['description'] + print(f"{date}: {amount} | Category: {category} | Description: {description}") + else: + print("No expense entries available!") + +def submit_expense(): + amount = float(input("Enter the expense amount: ")) + category = input("Enter the category of the expense (e.g., food, transport, bills): ") + description = input("Enter a brief description of the expense: ") + + entry = { + "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "amount": amount, + "category": category, + "description": description + } + + expense_data.append(entry) + print("Expense logged!") + save_expenses_to_file() + +def analyze_expenses(): + if expense_data: + category_totals = {} + for entry in expense_data: + category = entry['category'] + amount = entry['amount'] + category_totals[category] = category_totals.get(category, 0) + amount + + print("Expense Analysis:") + for category, total in category_totals.items(): + print(f"{category}: ${total:.2f}") + else: + print("No expenses to analyze!") + +def expense_tracker_system(): + load_expenses() + while True: + print("\nExpense Tracker System") + print("1. Log Expense") + print("2. Show Expense History") + print("3. Analyze Expenses") + print("4. Exit") + + choice = input("Please select an option (1-4): ") + + if choice == "1": + submit_expense() + elif choice == "2": + show_expenses() + elif choice == "3": + analyze_expenses() + elif choice == "4": + print("Exiting expense tracker system.") + break + else: + print("Invalid choice, please try again.") + +if __name__ == "__main__": + expense_tracker_system() From f5c5ac08e69f2d91ec0a71a0b143156213bfb78b Mon Sep 17 00:00:00 2001 From: Ravikrishna J <139262612+call-meRavi-SHORT-CODE@users.noreply.github.com> Date: Fri, 18 Oct 2024 20:37:55 +0530 Subject: [PATCH 03/73] google_meet_sheadule --- google_meet_sheadule.py | 123 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 google_meet_sheadule.py diff --git a/google_meet_sheadule.py b/google_meet_sheadule.py new file mode 100644 index 0000000..31cfdbc --- /dev/null +++ b/google_meet_sheadule.py @@ -0,0 +1,123 @@ +import os +import google.generativeai as genai +from googleapiclient.discovery import build +from google_auth_oauthlib.flow import InstalledAppFlow +from google.auth.transport.requests import Request +from googleapiclient.errors import HttpError +import pickle +import pyttsx3 as p +import re +from speak import speak + + + +# Set up Google API credentials +os.environ['GOOGLE_API_KEY'] = "your_own_Gemini_api_key" +GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY') +genai.configure(api_key=GOOGLE_API_KEY) + +model = genai.GenerativeModel('gemini-pro') + +# Define the scopes required for Google Calendar API +SCOPES = ['https://www.googleapis.com/auth/calendar'] +CREDENTIALS_FILE = 'credentials.json' # Path to your OAuth 2.0 credentials file +TOKEN_FILE = 'token.pickle' # File to store the OAuth 2.0 token + +def authenticate(): + creds = None + if os.path.exists(TOKEN_FILE): + with open(TOKEN_FILE, 'rb') as token: + creds = pickle.load(token) + if not creds or not creds.valid: + if creds and creds.expired and creds.refresh_token: + creds.refresh(Request()) + else: + flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE, SCOPES) + creds = flow.run_local_server(port=0) + with open(TOKEN_FILE, 'wb') as token: + pickle.dump(creds, token) + return creds + + +def create_google_meet_event(meeting_name, description, start_time_formatted, end_time_formatted, invitation_emails): + creds = authenticate() + service = build('calendar', 'v3', credentials=creds) + + event = { + 'summary': meeting_name, + 'description': description, + 'start': { + 'dateTime': start_time_formatted, + 'timeZone': 'Asia/Kolkata', + }, + 'end': { + 'dateTime': end_time_formatted, + 'timeZone': 'Asia/Kolkata', + }, + 'attendees': [{'email': email} for email in invitation_emails], + 'conferenceData': { + 'createRequest': { + 'requestId': 'sample123', + 'conferenceSolutionKey': {'type': 'hangoutsMeet'}, + }, + }, + } + + try: + event = service.events().insert( + calendarId='primary', + body=event, + conferenceDataVersion=1 + ).execute() + print(f'Event created: {event.get("htmlLink")}') + return event['id'] + except HttpError as error: + print(f'An error occurred: {error}') + print(f'Response content: {error.content}') + + + +def process_user_input(user_input): + # Generate response using Gemini + response = model.generate_content(f"Extract the following information from the given user input: Meeting Name: The title or name of the meeting. Description: A brief description or purpose of the meeting.Start Time: The start time of the meeting.End Time: The end time of the meeting. and convert the start time and end time to this format start time'2024-08-12T01:00:00+05:30' end time= '2024-08-12T02:00:00+05:30' Invitation Emails: Email addresses of the individuals who should receive the invitation from {user_input}") + text = response.text + + print(response.text) + + # Extract details using regex (simplified for demonstration) + meeting_name_match = re.search(r'Meeting Name:\s*(.*)', text) + meeting_name = meeting_name_match.group(1).strip() if meeting_name_match else "No meeting name provided" + + # Extracting Description + description_match = re.search(r'Description:\s*(.*)', text) + description = description_match.group(1).strip() if description_match else "No description provided" + + # Extracting Start Time + start_time_formatted = '2024-08-12T01:00:00+05:30' + end_time_formatted= '2024-08-12T02:00:00+05:30' + + # Extracting Invitation Emails + emails_matches = re.findall(r'[\w\.-]+@[\w\.-]+', text) + invitation_emails = [email.strip() for email in emails_matches] + + + + + + + return meeting_name,description,start_time_formatted,end_time_formatted,invitation_emails + +if __name__ == "__main__": + user_input = "Create a Google Meet and schedule a meeting for hackathon at 11:30 PM to 12:00 AM and send the invitation to ravikrishnajayaprakash.aiml2023@citchennai.net and sample@gmail.com" + meeting_name,description,start_time_formatted,end_time_formatted,invitation_emails = process_user_input(user_input) + + # Create the event + event_id = create_google_meet_event(meeting_name,description,start_time_formatted,end_time_formatted,invitation_emails) + + # Speak confirmation + speak(f'Event created successfully. You can join the meeting using the link: {event_id}') + +* + + + \ No newline at end of file From 83e550f78cd036b2a636ce6820a310078b56f29f Mon Sep 17 00:00:00 2001 From: Ashwin Kushwaha <113463013+kushwxha@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:51:57 +0530 Subject: [PATCH 04/73] Update README.md Added contributors profile in readme file --- README.md | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 271 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 415ef27..a6edd4a 100644 --- a/README.md +++ b/README.md @@ -220,11 +220,281 @@ We are grateful to all the contributors who have helped improve this project. Yo
Vuppu Chinmay + + + + Kritika75 +
+ Kritika Singh +
+ + + + + + 23wh1a0513 +
+ 23wh1a0513 +
+ + + + djv554 +
+ Deanne Vaz +
+ + + + wizaye +
+ Vijayendher Gatla +
+ + + + harshbhardwaj000 +
+ Harsh Bhardwaj +
+ + + + nishant4500 +
+ Nishant Dwivedi +
+ + + + + + pavitraag +
+ Pavitraa G +
+ + + + Dsmita03 +
+ Debasmita Sarkar +
+ + + + jitendra-ky +
+ jitendra Kumar +
+ + + + Yogitha128 +
+ Yogitha128 +
+ + + + samyak-aditya +
+ Samyak Aditya +
+ + + + + + ganjivamshiii +
+ ganjivamshiii +
+ + + + Aasthaa10 +
+ Aastha Kumari +
+ + + + Aryan-9488 +
+ Aryan +
+ + + + NamanVer02 +
+ Naman Verma +
+ + + + Aasthajiit +
+ Aasthajiit +
+ + + + + + Shaistaattar42 +
+ Shaistaattar +
+ + + + jaidh01 +
+ Jai Dhingra +
- + + deepanshubaghel +
+ Deepanshu Baghel +
+ + + + pratikwayal01 +
+ Pratik Wayal +
+ + + + ShrishtiSingh26 +
+ Shrishti +
+ + + + + + Deeptig9138 +
+ Deepti Gupta +
+ + + + say-het +
+ Het Modi +
+ + + + kushwxha +
+ Ashwin Kushwaha +
+ + + + Herostomo +
+ Kshitij Vijay Hedau +
+ + + + AnujSaha0111 +
+ Anuj Saha +
+ + + + + + omkarmakar +
+ Om Karmakar +
+ + + + Codewithmeowmeow +
+ codewithvibha +
+ + + + imDarshanGK +
+ Darshan G K +
+ + + + sanchitc05 +
+ Sanchit Chauhan +
+ + + + from13 +
+ from13 +
+ + + + + + Amulya-B28 +
+ Amulya-B28 +
+ + + + 23WH1A0507 +
23WH1A0507
+ + + + sejals23 +
+ Sejal +
+ + + + shwetzz14 +
+ Shweta Patil +
+ + + + Maryam0330 +
+ Maryam Panjri +
+ + + + + + ragini-gp +
+ Ragini Gupta +
From 0eecc0866dce7c97fd3604aceec3f18cb0b6b065 Mon Sep 17 00:00:00 2001 From: AnanteshG Date: Fri, 18 Oct 2024 22:34:15 +0530 Subject: [PATCH 05/73] Organized github --- 2048_game.py => Python Games/2048_game.py | 0 .../20_questions_game.py | 0 Banner.png => Python Games/Banner.png | Bin Detective.py => Python Games/Detective.py | 1308 ++++++++--------- Find_a_way.py => Python Games/Find_a_way.py | 0 Guesser.py => Python Games/Guesser.py | 0 .../Interactive Storytelling | 0 NewLogin => Python Games/NewLogin | 0 Quiz_Game => Python Games/Quiz_Game | 0 Recipes => Python Games/Recipes | 0 .../Rhythm_of_Knowledge | 0 .../Rock Paper Scissors game | 0 .../Rock_Paper_Scissors_Game.py | 0 Tic Tac Toc => Python Games/Tic Tac Toc | 0 Tutor.py => Python Games/Tutor.py | 400 ++--- akinator.py => Python Games/akinator.py | 0 chess.py => Python Games/chess.py | 0 eeg_game.py => Python Games/eeg_game.py | 0 game.py => Python Games/game.py | 0 jokes.py => Python Games/jokes.py | 286 ++-- .../login_credentials | 0 mood.py => Python Games/mood.py | 0 .../rock_paper_scissor_game.py | 0 song_data.py => Python Games/song_data.py | 16 +- song_quiz.py => Python Games/song_quiz.py | 0 sound_wave.png => Python Games/sound_wave.png | Bin sudoku.py => Python Games/sudoku.py | 0 .../user_output.mp3 | Bin voiceAssistant => Python Games/voiceAssistant | 0 .../workout_planner.py | 0 .../AES encryption.py | 0 .../Customized_voice_responses.py | 434 +++--- .../Emotion Detection.py | 0 .../Gesture Recognition using CNN.py | 0 .../Memory_assistance.py | 556 +++---- ...ulti-Device Sync in a virtual assistant.py | 0 .../Task Scheduling & Time Management.py | 0 .../Task_Scheduler | 0 Task_Script => Python Snippets/Task_Script | 0 .../TempConvereter.py | 0 .../Time_capsule.py | 378 ++--- .../Voice-Controlled Email and Messaging.py | 0 .../Voice-Controlled_Convenience.py | 0 app.py => Python Snippets/app.py | 0 .../auto_update_requirements.py | 0 book_recc.py => Python Snippets/book_recc.py | 0 .../budget_planner.py | 0 cli_setup.py => Python Snippets/cli_setup.py | 0 .../email_sender.py | 0 .../enhanced_text_to_speech.py | 0 .../enhanced_weather-info.py | 0 .../enhanced_weather.py | 0 .../face_detection.py | 0 .../face_detector.py | 0 feedback.py => Python Snippets/feedback.py | 0 .../gemini_info.py | 148 +- .../gui_assistant.py | 0 health.py => Python Snippets/health.py | 0 .../health_assistant.py | 0 imdb.py => Python Snippets/imdb.py | 0 .../language_practice_partner.py | 254 ++-- .../language_translator.py | 188 +-- .../linearEquations.py | 0 .../main_assistant.py | 0 .../mainutilities.py | 0 .../memory_game.py | 0 .../memorygame.py | 0 .../mood_tracker.py | 0 .../new_weather_info.py | 0 news_info.py => Python Snippets/news_info.py | 142 +- open_app.py => Python Snippets/open_app.py | 12 +- .../open_files.py | 0 .../phone_numbers.py | 0 qrcodes.py => Python Snippets/qrcodes.py | 0 .../quote_of_the_day.py | 0 .../real_time_shopping_list.py | 0 reminderr.py => Python Snippets/reminderr.py | 0 .../sentiment_analysis.py | 0 stocks.py => Python Snippets/stocks.py | 0 sun_scan.py => Python Snippets/sun_scan.py | 0 .../sustainabilty_tracker.py | 332 ++--- sync.py => Python Snippets/sync.py | 0 .../task_automation.py | 0 .../telegram_bot.py | 0 .../test_email.py | 0 .../test_weather.py | 0 .../text_summarization.py | 178 +-- .../text_to_speech.py | 52 +- .../time_module.py | 0 .../trivia_night.py | 0 .../unit_convertor.py | 184 +-- .../update_req.py | 0 .../updated-voice_recognition.py | 0 .../updatednews_info.py | 0 .../virtual_assistant.py | 0 voice.py => Python Snippets/voice.py | 166 +-- .../voice_recognition.py | 86 +- .../weather_info.py | 120 +- .../website_data.py | 28 +- .../websocket_server.py | 30 +- .../wikipedia_info.py | 162 +- 101 files changed, 2730 insertions(+), 2730 deletions(-) rename 2048_game.py => Python Games/2048_game.py (100%) rename 20_questions_game.py => Python Games/20_questions_game.py (100%) rename Banner.png => Python Games/Banner.png (100%) rename Detective.py => Python Games/Detective.py (97%) rename Find_a_way.py => Python Games/Find_a_way.py (100%) rename Guesser.py => Python Games/Guesser.py (100%) rename Interactive Storytelling => Python Games/Interactive Storytelling (100%) rename NewLogin => Python Games/NewLogin (100%) rename Quiz_Game => Python Games/Quiz_Game (100%) rename Recipes => Python Games/Recipes (100%) rename Rhythm_of_Knowledge => Python Games/Rhythm_of_Knowledge (100%) rename Rock Paper Scissors game => Python Games/Rock Paper Scissors game (100%) rename Rock_Paper_Scissors_Game.py => Python Games/Rock_Paper_Scissors_Game.py (100%) rename Tic Tac Toc => Python Games/Tic Tac Toc (100%) rename Tutor.py => Python Games/Tutor.py (97%) rename akinator.py => Python Games/akinator.py (100%) rename chess.py => Python Games/chess.py (100%) rename eeg_game.py => Python Games/eeg_game.py (100%) rename game.py => Python Games/game.py (100%) rename jokes.py => Python Games/jokes.py (96%) rename login_credentials => Python Games/login_credentials (100%) rename mood.py => Python Games/mood.py (100%) rename rock_paper_scissor_game.py => Python Games/rock_paper_scissor_game.py (100%) rename song_data.py => Python Games/song_data.py (96%) rename song_quiz.py => Python Games/song_quiz.py (100%) rename sound_wave.png => Python Games/sound_wave.png (100%) rename sudoku.py => Python Games/sudoku.py (100%) rename user_output.mp3 => Python Games/user_output.mp3 (100%) rename voiceAssistant => Python Games/voiceAssistant (100%) rename workout_planner.py => Python Games/workout_planner.py (100%) rename AES encryption.py => Python Snippets/AES encryption.py (100%) rename Customized_voice_responses.py => Python Snippets/Customized_voice_responses.py (97%) rename Emotion Detection.py => Python Snippets/Emotion Detection.py (100%) rename Gesture Recognition using CNN.py => Python Snippets/Gesture Recognition using CNN.py (100%) rename Memory_assistance.py => Python Snippets/Memory_assistance.py (97%) rename Multi-Device Sync in a virtual assistant.py => Python Snippets/Multi-Device Sync in a virtual assistant.py (100%) rename Task Scheduling & Time Management.py => Python Snippets/Task Scheduling & Time Management.py (100%) rename Task_Scheduler => Python Snippets/Task_Scheduler (100%) rename Task_Script => Python Snippets/Task_Script (100%) rename TempConvereter.py => Python Snippets/TempConvereter.py (100%) rename Time_capsule.py => Python Snippets/Time_capsule.py (97%) rename Voice-Controlled Email and Messaging.py => Python Snippets/Voice-Controlled Email and Messaging.py (100%) rename Voice-Controlled_Convenience.py => Python Snippets/Voice-Controlled_Convenience.py (100%) rename app.py => Python Snippets/app.py (100%) rename auto_update_requirements.py => Python Snippets/auto_update_requirements.py (100%) rename book_recc.py => Python Snippets/book_recc.py (100%) rename budget_planner.py => Python Snippets/budget_planner.py (100%) rename cli_setup.py => Python Snippets/cli_setup.py (100%) rename email_sender.py => Python Snippets/email_sender.py (100%) rename enhanced_text_to_speech.py => Python Snippets/enhanced_text_to_speech.py (100%) rename enhanced_weather-info.py => Python Snippets/enhanced_weather-info.py (100%) rename enhanced_weather.py => Python Snippets/enhanced_weather.py (100%) rename face_detection.py => Python Snippets/face_detection.py (100%) rename face_detector.py => Python Snippets/face_detector.py (100%) rename feedback.py => Python Snippets/feedback.py (100%) rename gemini_info.py => Python Snippets/gemini_info.py (96%) rename gui_assistant.py => Python Snippets/gui_assistant.py (100%) rename health.py => Python Snippets/health.py (100%) rename health_assistant.py => Python Snippets/health_assistant.py (100%) rename imdb.py => Python Snippets/imdb.py (100%) rename language_practice_partner.py => Python Snippets/language_practice_partner.py (97%) rename language_translator.py => Python Snippets/language_translator.py (97%) rename linearEquations.py => Python Snippets/linearEquations.py (100%) rename main_assistant.py => Python Snippets/main_assistant.py (100%) rename mainutilities.py => Python Snippets/mainutilities.py (100%) rename memory_game.py => Python Snippets/memory_game.py (100%) rename memorygame.py => Python Snippets/memorygame.py (100%) rename mood_tracker.py => Python Snippets/mood_tracker.py (100%) rename new_weather_info.py => Python Snippets/new_weather_info.py (100%) rename news_info.py => Python Snippets/news_info.py (96%) rename open_app.py => Python Snippets/open_app.py (95%) rename open_files.py => Python Snippets/open_files.py (100%) rename phone_numbers.py => Python Snippets/phone_numbers.py (100%) rename qrcodes.py => Python Snippets/qrcodes.py (100%) rename quote_of_the_day.py => Python Snippets/quote_of_the_day.py (100%) rename real_time_shopping_list.py => Python Snippets/real_time_shopping_list.py (100%) rename reminderr.py => Python Snippets/reminderr.py (100%) rename sentiment_analysis.py => Python Snippets/sentiment_analysis.py (100%) rename stocks.py => Python Snippets/stocks.py (100%) rename sun_scan.py => Python Snippets/sun_scan.py (100%) rename sustainabilty_tracker.py => Python Snippets/sustainabilty_tracker.py (97%) rename sync.py => Python Snippets/sync.py (100%) rename task_automation.py => Python Snippets/task_automation.py (100%) rename telegram_bot.py => Python Snippets/telegram_bot.py (100%) rename test_email.py => Python Snippets/test_email.py (100%) rename test_weather.py => Python Snippets/test_weather.py (100%) rename text_summarization.py => Python Snippets/text_summarization.py (96%) rename text_to_speech.py => Python Snippets/text_to_speech.py (96%) rename time_module.py => Python Snippets/time_module.py (100%) rename trivia_night.py => Python Snippets/trivia_night.py (100%) rename unit_convertor.py => Python Snippets/unit_convertor.py (97%) rename update_req.py => Python Snippets/update_req.py (100%) rename updated-voice_recognition.py => Python Snippets/updated-voice_recognition.py (100%) rename updatednews_info.py => Python Snippets/updatednews_info.py (100%) rename virtual_assistant.py => Python Snippets/virtual_assistant.py (100%) rename voice.py => Python Snippets/voice.py (97%) rename voice_recognition.py => Python Snippets/voice_recognition.py (96%) rename weather_info.py => Python Snippets/weather_info.py (97%) rename website_data.py => Python Snippets/website_data.py (96%) rename websocket_server.py => Python Snippets/websocket_server.py (96%) rename wikipedia_info.py => Python Snippets/wikipedia_info.py (97%) diff --git a/2048_game.py b/Python Games/2048_game.py similarity index 100% rename from 2048_game.py rename to Python Games/2048_game.py diff --git a/20_questions_game.py b/Python Games/20_questions_game.py similarity index 100% rename from 20_questions_game.py rename to Python Games/20_questions_game.py diff --git a/Banner.png b/Python Games/Banner.png similarity index 100% rename from Banner.png rename to Python Games/Banner.png diff --git a/Detective.py b/Python Games/Detective.py similarity index 97% rename from Detective.py rename to Python Games/Detective.py index c60bcfd..74d50ed 100644 --- a/Detective.py +++ b/Python Games/Detective.py @@ -1,654 +1,654 @@ -import speech_recognition as sr -import pyttsx3 -import random - -# Initialize the recognizer and the text-to-speech engine -recognizer = sr.Recognizer() -tts_engine = pyttsx3.init() - -# Define crime cases with clues, suspects, and character profiles -cases = { - "Case 1": { - "scenario": "A valuable painting was stolen from the art gallery.", - "clues": [ - {"type": "evidence", "text": "The security guard heard a strange noise at 3 AM."}, - {"type": "evidence", "text": "The thief left behind a footprint."}, - {"type": "witness", "text": "A witness saw a man in a red jacket near the gallery."} - ], - "suspects": { - "The Security Guard": { - "motive": "He wanted to steal the painting and sell it on the black market.", - "alibi": "He was at his post the whole time." - }, - "The Known Art Thief": { - "motive": "He has a history of stealing valuable art.", - "alibi": "He claims he was in a different city." - }, - "The Visitor in a Red Jacket": { - "motive": "He wanted to impress a wealthy friend.", - "alibi": "He says he left the gallery before the theft." - } - }, - "solution": "The Visitor in a Red Jacket." - }, - "Case 2": { - "scenario": "A bank was robbed in broad daylight.", - "clues": [ - {"type": "evidence", "text": "The robber wore a blue mask."}, - {"type": "evidence", "text": "A getaway car was seen speeding away."}, - {"type": "witness", "text": "One of the bank tellers recognized the robber."} - ], - "suspects": { - "The Bank Manager": { - "motive": "He wanted to pay off debts.", - "alibi": "He was in his office at the time." - }, - "The Former Employee": { - "motive": "He was fired and wanted revenge.", - "alibi": "He was at a bar nearby." - }, - "The Street Vendor": { - "motive": "He needed money for his family.", - "alibi": "He was serving customers." - } - }, - "solution": "The Former Employee." - }, - "Case 3": { - "scenario": "A murder took place at a party.", - "clues": [ - {"type": "evidence", "text": "The victim was last seen arguing with someone."}, - {"type": "evidence", "text": "There were fingerprints on the wine glass."}, - {"type": "witness", "text": "A guest heard a loud crash before the scream."} - ], - "suspects": { - "The Host of the Party": { - "motive": "He was jealous of the victim's success.", - "alibi": "He claims he was in the kitchen preparing snacks." - }, - "The Victim's Friend": { - "motive": "They had a falling out recently.", - "alibi": "She was in the bathroom during the incident." - }, - "A Mysterious Guest": { - "motive": "He was looking for a rare item the victim had.", - "alibi": "He says he was outside on a phone call." - } - }, - "solution": "The Host of the Party." - }, - "Case 4": { - "scenario": "A rare jewel was stolen during a gala.", - "clues": [ - {"type": "evidence", "text": "A server saw someone slip away with a bag."}, - {"type": "evidence", "text": "There were security cameras, but they were turned off."}, - {"type": "witness", "text": "A guest reported a suspicious person near the exit."} - ], - "suspects": { - "The Server": { - "motive": "He wanted to sell the jewel to pay off debts.", - "alibi": "He was busy serving drinks." - }, - "The Gala Organizer": { - "motive": "She wanted the insurance money.", - "alibi": "She was talking to guests." - }, - "A Guest in a Black Suit": { - "motive": "He had a secret connection to the jewel's owner.", - "alibi": "He claims he was on the dance floor." - } - }, - "solution": "The Gala Organizer." - }, - "Case 5": { - "scenario": "A scientist was poisoned in his lab.", - "clues": [ - {"type": "evidence", "text": "The lab was locked from the inside."}, - {"type": "evidence", "text": "A vial of poison was found missing."}, - {"type": "witness", "text": "The victim had been arguing with a colleague."} - ], - "suspects": { - "The Colleague": { - "motive": "He wanted to take credit for the victim's research.", - "alibi": "He was in a different lab at the time." - }, - "The Lab Assistant": { - "motive": "She was unhappy with her job and wanted revenge.", - "alibi": "She claims she was cleaning equipment." - }, - "A Rival Scientist": { - "motive": "He was jealous of the victim's success.", - "alibi": "He says he was at a conference." - } - }, - "solution": "The Colleague." - }, - "Case 6": { - "scenario": "A famous chef was found dead in his kitchen.", - "clues": [ - {"type": "evidence", "text": "There were traces of poison in his last meal."}, - {"type": "evidence", "text": "A knife was missing from the kitchen."}, - {"type": "witness", "text": "A staff member heard shouting just before the body was found."} - ], - "suspects": { - "The Sous Chef": { - "motive": "He wanted to take over the restaurant.", - "alibi": "He was preparing another dish." - }, - "The Restaurant Owner": { - "motive": "He was losing money and wanted to cash in on insurance.", - "alibi": "He was meeting a supplier." - }, - "A Food Critic": { - "motive": "He had a personal grudge against the chef.", - "alibi": "He was outside smoking." - } - }, - "solution": "The Sous Chef." - }, - "Case 7": { - "scenario": "A politician's campaign office was vandalized.", - "clues": [ - {"type": "evidence", "text": "The words 'Liar' were spray-painted on the wall."}, - {"type": "evidence", "text": "A broken window was found at the back."}, - {"type": "witness", "text": "A neighbor saw a hooded figure fleeing the scene."} - ], - "suspects": { - "A Rival Politician": { - "motive": "He wanted to sabotage the campaign.", - "alibi": "He was attending a fundraiser." - }, - "An Angry Voter": { - "motive": "He was upset over a recent policy change.", - "alibi": "He claims he was at home." - }, - "A Campaign Intern": { - "motive": "He disagreed with the politician's approach.", - "alibi": "He was out running errands." - } - }, - "solution": "The Rival Politician." - }, - "Case 8": { - "scenario": "A tech company was hacked, and sensitive data was leaked.", - "clues": [ - {"type": "evidence", "text": "The hack originated from inside the company."}, - {"type": "evidence", "text": "An employee's computer was accessed without authorization."}, - {"type": "witness", "text": "A janitor saw someone in the office late at night."} - ], - "suspects": { - "The IT Manager": { - "motive": "He wanted to sell the data to a competitor.", - "alibi": "He was at a meeting." - }, - "A Junior Developer": { - "motive": "She was frustrated with her job and wanted revenge.", - "alibi": "She claims she was working late on a project." - }, - "The CEO": { - "motive": "He wanted to cover up a financial scandal.", - "alibi": "He was traveling on business." - } - }, - "solution": "The Junior Developer." - }, - "Case 9": { - "scenario": "A high-profile journalist was found dead in her apartment.", - "clues": [ - {"type": "evidence", "text": "There were signs of a struggle in the living room."}, - {"type": "evidence", "text": "A threatening note was found on her desk."}, - {"type": "witness", "text": "A neighbor heard loud noises coming from her apartment."} - ], - "suspects": { - "An Ex-Partner": { - "motive": "He was jealous of her success.", - "alibi": "He was at a friend's house." - }, - "A Colleague": { - "motive": "They were in competition for a major story.", - "alibi": "He was at a press conference." - }, - "A Stalker": { - "motive": "He was obsessed with her work.", - "alibi": "He claims he was at a bar." - } - }, - "solution": "The Ex-Partner." - }, - "Case 10": { - "scenario": "A beloved teacher was found poisoned in the staff room.", - "clues": [ - {"type": "evidence", "text": "A bottle of poison was found in the teacher's desk."}, - {"type": "evidence", "text": "There were no signs of forced entry."}, - {"type": "witness", "text": "A student saw a suspicious figure leaving the staff room."} - ], - "suspects": { - "A Fellow Teacher": { - "motive": "She was envious of the teacher's popularity.", - "alibi": "She was in a meeting during lunch." - }, - "A Parent": { - "motive": "He was unhappy with a recent grade his child received.", - "alibi": "He claims he was at work." - }, - "A Student": { - "motive": "He had a grudge due to a disciplinary action.", - "alibi": "He says he was in the library." - } - }, - "solution": "A Fellow Teacher." - }, - "Case 11": { - "scenario": "A famous singer's jewelry collection was stolen.", - "clues": [ - {"type": "evidence", "text": "The alarm system was disabled before the theft."}, - {"type": "evidence", "text": "A window was found ajar."}, - {"type": "witness", "text": "A neighbor saw a suspicious car parked outside."} - ], - "suspects": { - "The Assistant": { - "motive": "She wanted to start her own career.", - "alibi": "She claims she was at a rehearsal." - }, - "An Ex-Boyfriend": { - "motive": "He was bitter after their breakup.", - "alibi": "He was at a friend's house." - }, - "A Fan": { - "motive": "He was obsessed with the singer.", - "alibi": "He says he was at a concert." - } - }, - "solution": "The Assistant." - }, - "Case 12": { - "scenario": "A scientist's lab notebook was stolen just before a big presentation.", - "clues": [ - {"type": "evidence", "text": "There was a struggle in the lab."}, - {"type": "evidence", "text": "A note with a threat was found in the drawer."}, - {"type": "witness", "text": "A student saw someone leaving with a bag."} - ], - "suspects": { - "A Rival Researcher": { - "motive": "He wanted to sabotage the presentation.", - "alibi": "He claims he was at a conference." - }, - "A Lab Intern": { - "motive": "She wanted to impress a professor.", - "alibi": "She was working on her project." - }, - "The Professor": { - "motive": "He wanted to keep his research undisputed.", - "alibi": "He was grading papers." - } - }, - "solution": "A Rival Researcher." - }, - "Case 13": { - "scenario": "A popular game developer was found dead in his office.", - "clues": [ - {"type": "evidence", "text": "The office was locked from the inside."}, - {"type": "evidence", "text": "A gaming trophy was broken."}, - {"type": "witness", "text": "A coworker heard loud noises before the body was found."} - ], - "suspects": { - "A Co-Developer": { - "motive": "He wanted to take credit for the project.", - "alibi": "He claims he was at lunch." - }, - "An Angry Fan": { - "motive": "He was upset about a game delay.", - "alibi": "He was at home." - }, - "The Assistant": { - "motive": "She was tired of being overlooked.", - "alibi": "She was organizing files." - } - }, - "solution": "A Co-Developer." - }, - "Case 14": { - "scenario": "A prominent lawyer was found poisoned at a dinner party.", - "clues": [ - {"type": "evidence", "text": "The poison was in his wine glass."}, - {"type": "evidence", "text": "A broken glass was found on the floor."}, - {"type": "witness", "text": "A guest heard an argument shortly before the victim collapsed."} - ], - "suspects": { - "A Rival Lawyer": { - "motive": "He wanted to eliminate competition.", - "alibi": "He claims he was in the restroom." - }, - "A Client": { - "motive": "He was unhappy with the lawyer's representation.", - "alibi": "He says he was outside." - }, - "A Family Member": { - "motive": "They had a longstanding feud.", - "alibi": "She was talking to other guests." - } - }, - "solution": "A Rival Lawyer." - }, - "Case 15": { - "scenario": "A famous author was found dead in her study.", - "clues": [ - {"type": "evidence", "text": "A manuscript was missing."}, - {"type": "evidence", "text": "There were signs of forced entry."}, - {"type": "witness", "text": "A neighbor saw a stranger leaving the house."} - ], - "suspects": { - "A Literary Agent": { - "motive": "He wanted to control the author's work.", - "alibi": "He was at a meeting." - }, - "A Jealous Writer": { - "motive": "He was envious of her success.", - "alibi": "He claims he was at a bar." - }, - "A Family Member": { - "motive": "They wanted the inheritance.", - "alibi": "He was out running errands." - } - }, - "solution": "A Jealous Writer." - }, - "Case 16": { - "scenario": "A renowned architect was found dead in his office.", - "clues": [ - {"type": "evidence", "text": "A blueprint for a new project was missing."}, - {"type": "evidence", "text": "There was a strange odor in the air."}, - {"type": "witness", "text": "A security guard saw someone leave the building late at night."} - ], - "suspects": { - "A Business Partner": { - "motive": "He wanted full control of the firm.", - "alibi": "He claims he was out of town." - }, - "An Assistant": { - "motive": "She was tired of being underappreciated.", - "alibi": "She was working overtime." - }, - "A Rival Architect": { - "motive": "He wanted to ruin the architect's reputation.", - "alibi": "He was attending a seminar." - } - }, - "solution": "A Business Partner." - }, - "Case 17": { - "scenario": "A social media influencer was blackmailed.", - "clues": [ - {"type": "evidence", "text": "Threatening messages were found on her phone."}, - {"type": "evidence", "text": "A security video showed someone entering her home."}, - {"type": "witness", "text": "A neighbor heard a loud argument."} - ], - "suspects": { - "A Former Friend": { - "motive": "She was jealous of the influencer's success.", - "alibi": "She claims she was at a party." - }, - "A Stalker": { - "motive": "He was obsessed with her online persona.", - "alibi": "He says he was at home." - }, - "An Ex-Manager": { - "motive": "He wanted revenge after being fired.", - "alibi": "He was traveling." - } - }, - "solution": "A Former Friend." - }, - "Case 18": { - "scenario": "A successful entrepreneur was found dead in his mansion.", - "clues": [ - {"type": "evidence", "text": "A broken vase was found near the body."}, - {"type": "evidence", "text": "His bank accounts were accessed just before his death."}, - {"type": "witness", "text": "A gardener saw someone leave the mansion."} - ], - "suspects": { - "A Business Rival": { - "motive": "He wanted to eliminate competition.", - "alibi": "He was at a conference." - }, - "A Family Member": { - "motive": "She wanted to inherit the fortune.", - "alibi": "She was at a charity event." - }, - "A Housekeeper": { - "motive": "She was unhappy with her pay.", - "alibi": "She was cleaning the garage." - } - }, - "solution": "A Business Rival." - }, - "Case 19": { - "scenario": "A famous actor was found dead on set.", - "clues": [ - {"type": "evidence", "text": "The prop gun was found loaded."}, - {"type": "evidence", "text": "There was a note threatening the actor."}, - {"type": "witness", "text": "A crew member heard a loud bang."} - ], - "suspects": { - "The Director": { - "motive": "He wanted to boost the drama of the film.", - "alibi": "He was reviewing footage." - }, - "A Co-Star": { - "motive": "She was envious of the actor's fame.", - "alibi": "She claims she was in her trailer." - }, - "A Stunt Double": { - "motive": "He wanted the lead role.", - "alibi": "He says he was in the gym." - } - }, - "solution": "The Co-Star." - }, - "Case 20": { - "scenario": "A startup's confidential project was leaked.", - "clues": [ - {"type": "evidence", "text": "An employee's computer was accessed without permission."}, - {"type": "evidence", "text": "A file with sensitive information was missing."}, - {"type": "witness", "text": "A delivery person saw someone acting suspiciously."} - ], - "suspects": { - "The Lead Developer": { - "motive": "He wanted to sell the information to a rival company.", - "alibi": "He was at a team meeting." - }, - "An Intern": { - "motive": "She was hoping to impress a recruiter.", - "alibi": "She claims she was fetching coffee." - }, - "The CEO": { - "motive": "He wanted to cover up a previous mistake.", - "alibi": "He was in a different office." - } - }, - "solution": "The Intern." - }, - "Case 21": { - "scenario": "A championship trophy was stolen before the game.", - "clues": [ - {"type": "evidence", "text": "The trophy case was broken into."}, - {"type": "evidence", "text": "A security guard saw a player near the case."}, - {"type": "witness", "text": "A fan reported seeing someone acting suspiciously."} - ], - "suspects": { - "A Rival Team Player": { - "motive": "He wanted to sabotage the competition.", - "alibi": "He claims he was practicing." - }, - "The Team Coach": { - "motive": "He wanted to distract the team.", - "alibi": "He was in a meeting." - }, - "A Die-Hard Fan": { - "motive": "He wanted to keep the trophy safe.", - "alibi": "He says he was at home." - } - }, - "solution": "A Rival Team Player." - }, - "Case 22": { - "scenario": "A museum exhibit was vandalized overnight.", - "clues": [ - {"type": "evidence", "text": "Security footage was tampered with."}, - {"type": "evidence", "text": "There were paint stains found on the floor."}, - {"type": "witness", "text": "A night guard heard noises."} - ], - "suspects": { - "A Rival Artist": { - "motive": "He was jealous of the exhibit's success.", - "alibi": "He claims he was at a gallery opening." - }, - "A Museum Curator": { - "motive": "He wanted to change the exhibit.", - "alibi": "He was at home." - }, - "A Teenager": { - "motive": "He wanted to impress his friends.", - "alibi": "He says he was out skateboarding." - } - }, - "solution": "A Rival Artist." - }, - "Case 23": { - "scenario": "A car was found abandoned after a hit-and-run.", - "clues": [ - {"type": "evidence", "text": "The car's license plate was traced to a local dealer."}, - {"type": "evidence", "text": "Paint residue matched a nearby vehicle."}, - {"type": "witness", "text": "A pedestrian saw the accident."} - ], - "suspects": { - "A Local Mechanic": { - "motive": "He wanted to cover up his own accident.", - "alibi": "He was working on another car." - }, - "A Distracted Driver": { - "motive": "He was using his phone at the time.", - "alibi": "He claims he was at the grocery store." - }, - "A Teenager": { - "motive": "He was running late for an event.", - "alibi": "He says he was on a date." - } - }, - "solution": "A Distracted Driver." - }, - "Case 24": { - "scenario": "A local charity's funds were embezzled.", - "clues": [ - {"type": "evidence", "text": "Bank statements showed unauthorized withdrawals."}, - {"type": "evidence", "text": "A computer log was deleted."}, - {"type": "witness", "text": "An employee saw someone in the office late at night."} - ], - "suspects": { - "The Treasurer": { - "motive": "He wanted to pay off personal debts.", - "alibi": "He claims he was at a fundraiser." - }, - "A Volunteer": { - "motive": "She was unhappy with her role.", - "alibi": "She was at home." - }, - "The Charity Director": { - "motive": "He wanted to cover up his own mismanagement.", - "alibi": "He was traveling for business." - } - }, - "solution": "The Treasurer." - }, - "Case 25": { - "scenario": "A community leader was found dead during a town hall meeting.", - "clues": [ - {"type": "evidence", "text": "There were signs of a struggle in the meeting room."}, - {"type": "evidence", "text": "A broken chair was found nearby."}, - {"type": "witness", "text": "A participant heard shouting before the meeting started."} - ], - "suspects": { - "A Local Businessman": { - "motive": "He was angry over a recent decision against his interests.", - "alibi": "He claims he was speaking with constituents." - }, - "A Fellow Community Leader": { - "motive": "She was envious of his popularity.", - "alibi": "She was giving a presentation." - }, - "A Distraught Citizen": { - "motive": "He was unhappy with local policies.", - "alibi": "He was in the back of the room." - } - }, - "solution": "A Local Businessman." - } -} - -def speak(text): - tts_engine.say(text) - tts_engine.runAndWait() - -def listen(): - with sr.Microphone() as source: - print("Listening...") - audio = recognizer.listen(source) - try: - text = recognizer.recognize_google(audio) - print(f"You said: {text}") - return text.lower() - except sr.UnknownValueError: - speak("Sorry, I did not understand that.") - return "" - except sr.RequestError: - speak("Could not request results; check your internet connection.") - return "" - -def present_case(case_name): - case = cases[case_name] - speak(f"Welcome to {case_name}.") - speak(case["scenario"]) - - for clue in case["clues"]: - speak(f"Clue: {clue['text']}") - - speak("Would you like to know about the suspects, ask for a hint, or make an accusation?") - - points = 0 - while True: - choice = listen() - if "suspects" in choice: - speak("Here are the suspects:") - for suspect, details in case["suspects"].items(): - speak(f"{suspect}: {details['motive']}") - speak(f"Alibi: {details['alibi']}") - speak("Would you like to make an accusation or ask for a hint?") - elif "hint" in choice: - hint = random.choice(case["clues"]) - speak(f"Hint: {hint['text']}") - points += 1 # Earn points for asking hints - speak("You earned a point for asking a hint!") - elif "accusation" in choice: - speak("Who do you accuse?") - accusation = listen() - if accusation in case["suspects"]: - speak("You accused " + accusation + ".") - if accusation == case["solution"]: - speak("Congratulations! You solved the case!") - points += 5 # Earn points for solving the case - break - else: - speak("That's incorrect. Try again.") - else: - speak("That suspect is not in this case. Please name a valid suspect.") - else: - speak("I didn't catch that. Please choose to know about the suspects, ask for a hint, or make an accusation.") - -# Start the game -speak("Welcome to the Murder Mystery Game! Please say the name of the case you want to solve.") -case_names = list(cases.keys()) -case_choice = listen() -if case_choice in case_names: - present_case(case_choice) -else: - speak("That case is not available. Please choose a valid case.") +import speech_recognition as sr +import pyttsx3 +import random + +# Initialize the recognizer and the text-to-speech engine +recognizer = sr.Recognizer() +tts_engine = pyttsx3.init() + +# Define crime cases with clues, suspects, and character profiles +cases = { + "Case 1": { + "scenario": "A valuable painting was stolen from the art gallery.", + "clues": [ + {"type": "evidence", "text": "The security guard heard a strange noise at 3 AM."}, + {"type": "evidence", "text": "The thief left behind a footprint."}, + {"type": "witness", "text": "A witness saw a man in a red jacket near the gallery."} + ], + "suspects": { + "The Security Guard": { + "motive": "He wanted to steal the painting and sell it on the black market.", + "alibi": "He was at his post the whole time." + }, + "The Known Art Thief": { + "motive": "He has a history of stealing valuable art.", + "alibi": "He claims he was in a different city." + }, + "The Visitor in a Red Jacket": { + "motive": "He wanted to impress a wealthy friend.", + "alibi": "He says he left the gallery before the theft." + } + }, + "solution": "The Visitor in a Red Jacket." + }, + "Case 2": { + "scenario": "A bank was robbed in broad daylight.", + "clues": [ + {"type": "evidence", "text": "The robber wore a blue mask."}, + {"type": "evidence", "text": "A getaway car was seen speeding away."}, + {"type": "witness", "text": "One of the bank tellers recognized the robber."} + ], + "suspects": { + "The Bank Manager": { + "motive": "He wanted to pay off debts.", + "alibi": "He was in his office at the time." + }, + "The Former Employee": { + "motive": "He was fired and wanted revenge.", + "alibi": "He was at a bar nearby." + }, + "The Street Vendor": { + "motive": "He needed money for his family.", + "alibi": "He was serving customers." + } + }, + "solution": "The Former Employee." + }, + "Case 3": { + "scenario": "A murder took place at a party.", + "clues": [ + {"type": "evidence", "text": "The victim was last seen arguing with someone."}, + {"type": "evidence", "text": "There were fingerprints on the wine glass."}, + {"type": "witness", "text": "A guest heard a loud crash before the scream."} + ], + "suspects": { + "The Host of the Party": { + "motive": "He was jealous of the victim's success.", + "alibi": "He claims he was in the kitchen preparing snacks." + }, + "The Victim's Friend": { + "motive": "They had a falling out recently.", + "alibi": "She was in the bathroom during the incident." + }, + "A Mysterious Guest": { + "motive": "He was looking for a rare item the victim had.", + "alibi": "He says he was outside on a phone call." + } + }, + "solution": "The Host of the Party." + }, + "Case 4": { + "scenario": "A rare jewel was stolen during a gala.", + "clues": [ + {"type": "evidence", "text": "A server saw someone slip away with a bag."}, + {"type": "evidence", "text": "There were security cameras, but they were turned off."}, + {"type": "witness", "text": "A guest reported a suspicious person near the exit."} + ], + "suspects": { + "The Server": { + "motive": "He wanted to sell the jewel to pay off debts.", + "alibi": "He was busy serving drinks." + }, + "The Gala Organizer": { + "motive": "She wanted the insurance money.", + "alibi": "She was talking to guests." + }, + "A Guest in a Black Suit": { + "motive": "He had a secret connection to the jewel's owner.", + "alibi": "He claims he was on the dance floor." + } + }, + "solution": "The Gala Organizer." + }, + "Case 5": { + "scenario": "A scientist was poisoned in his lab.", + "clues": [ + {"type": "evidence", "text": "The lab was locked from the inside."}, + {"type": "evidence", "text": "A vial of poison was found missing."}, + {"type": "witness", "text": "The victim had been arguing with a colleague."} + ], + "suspects": { + "The Colleague": { + "motive": "He wanted to take credit for the victim's research.", + "alibi": "He was in a different lab at the time." + }, + "The Lab Assistant": { + "motive": "She was unhappy with her job and wanted revenge.", + "alibi": "She claims she was cleaning equipment." + }, + "A Rival Scientist": { + "motive": "He was jealous of the victim's success.", + "alibi": "He says he was at a conference." + } + }, + "solution": "The Colleague." + }, + "Case 6": { + "scenario": "A famous chef was found dead in his kitchen.", + "clues": [ + {"type": "evidence", "text": "There were traces of poison in his last meal."}, + {"type": "evidence", "text": "A knife was missing from the kitchen."}, + {"type": "witness", "text": "A staff member heard shouting just before the body was found."} + ], + "suspects": { + "The Sous Chef": { + "motive": "He wanted to take over the restaurant.", + "alibi": "He was preparing another dish." + }, + "The Restaurant Owner": { + "motive": "He was losing money and wanted to cash in on insurance.", + "alibi": "He was meeting a supplier." + }, + "A Food Critic": { + "motive": "He had a personal grudge against the chef.", + "alibi": "He was outside smoking." + } + }, + "solution": "The Sous Chef." + }, + "Case 7": { + "scenario": "A politician's campaign office was vandalized.", + "clues": [ + {"type": "evidence", "text": "The words 'Liar' were spray-painted on the wall."}, + {"type": "evidence", "text": "A broken window was found at the back."}, + {"type": "witness", "text": "A neighbor saw a hooded figure fleeing the scene."} + ], + "suspects": { + "A Rival Politician": { + "motive": "He wanted to sabotage the campaign.", + "alibi": "He was attending a fundraiser." + }, + "An Angry Voter": { + "motive": "He was upset over a recent policy change.", + "alibi": "He claims he was at home." + }, + "A Campaign Intern": { + "motive": "He disagreed with the politician's approach.", + "alibi": "He was out running errands." + } + }, + "solution": "The Rival Politician." + }, + "Case 8": { + "scenario": "A tech company was hacked, and sensitive data was leaked.", + "clues": [ + {"type": "evidence", "text": "The hack originated from inside the company."}, + {"type": "evidence", "text": "An employee's computer was accessed without authorization."}, + {"type": "witness", "text": "A janitor saw someone in the office late at night."} + ], + "suspects": { + "The IT Manager": { + "motive": "He wanted to sell the data to a competitor.", + "alibi": "He was at a meeting." + }, + "A Junior Developer": { + "motive": "She was frustrated with her job and wanted revenge.", + "alibi": "She claims she was working late on a project." + }, + "The CEO": { + "motive": "He wanted to cover up a financial scandal.", + "alibi": "He was traveling on business." + } + }, + "solution": "The Junior Developer." + }, + "Case 9": { + "scenario": "A high-profile journalist was found dead in her apartment.", + "clues": [ + {"type": "evidence", "text": "There were signs of a struggle in the living room."}, + {"type": "evidence", "text": "A threatening note was found on her desk."}, + {"type": "witness", "text": "A neighbor heard loud noises coming from her apartment."} + ], + "suspects": { + "An Ex-Partner": { + "motive": "He was jealous of her success.", + "alibi": "He was at a friend's house." + }, + "A Colleague": { + "motive": "They were in competition for a major story.", + "alibi": "He was at a press conference." + }, + "A Stalker": { + "motive": "He was obsessed with her work.", + "alibi": "He claims he was at a bar." + } + }, + "solution": "The Ex-Partner." + }, + "Case 10": { + "scenario": "A beloved teacher was found poisoned in the staff room.", + "clues": [ + {"type": "evidence", "text": "A bottle of poison was found in the teacher's desk."}, + {"type": "evidence", "text": "There were no signs of forced entry."}, + {"type": "witness", "text": "A student saw a suspicious figure leaving the staff room."} + ], + "suspects": { + "A Fellow Teacher": { + "motive": "She was envious of the teacher's popularity.", + "alibi": "She was in a meeting during lunch." + }, + "A Parent": { + "motive": "He was unhappy with a recent grade his child received.", + "alibi": "He claims he was at work." + }, + "A Student": { + "motive": "He had a grudge due to a disciplinary action.", + "alibi": "He says he was in the library." + } + }, + "solution": "A Fellow Teacher." + }, + "Case 11": { + "scenario": "A famous singer's jewelry collection was stolen.", + "clues": [ + {"type": "evidence", "text": "The alarm system was disabled before the theft."}, + {"type": "evidence", "text": "A window was found ajar."}, + {"type": "witness", "text": "A neighbor saw a suspicious car parked outside."} + ], + "suspects": { + "The Assistant": { + "motive": "She wanted to start her own career.", + "alibi": "She claims she was at a rehearsal." + }, + "An Ex-Boyfriend": { + "motive": "He was bitter after their breakup.", + "alibi": "He was at a friend's house." + }, + "A Fan": { + "motive": "He was obsessed with the singer.", + "alibi": "He says he was at a concert." + } + }, + "solution": "The Assistant." + }, + "Case 12": { + "scenario": "A scientist's lab notebook was stolen just before a big presentation.", + "clues": [ + {"type": "evidence", "text": "There was a struggle in the lab."}, + {"type": "evidence", "text": "A note with a threat was found in the drawer."}, + {"type": "witness", "text": "A student saw someone leaving with a bag."} + ], + "suspects": { + "A Rival Researcher": { + "motive": "He wanted to sabotage the presentation.", + "alibi": "He claims he was at a conference." + }, + "A Lab Intern": { + "motive": "She wanted to impress a professor.", + "alibi": "She was working on her project." + }, + "The Professor": { + "motive": "He wanted to keep his research undisputed.", + "alibi": "He was grading papers." + } + }, + "solution": "A Rival Researcher." + }, + "Case 13": { + "scenario": "A popular game developer was found dead in his office.", + "clues": [ + {"type": "evidence", "text": "The office was locked from the inside."}, + {"type": "evidence", "text": "A gaming trophy was broken."}, + {"type": "witness", "text": "A coworker heard loud noises before the body was found."} + ], + "suspects": { + "A Co-Developer": { + "motive": "He wanted to take credit for the project.", + "alibi": "He claims he was at lunch." + }, + "An Angry Fan": { + "motive": "He was upset about a game delay.", + "alibi": "He was at home." + }, + "The Assistant": { + "motive": "She was tired of being overlooked.", + "alibi": "She was organizing files." + } + }, + "solution": "A Co-Developer." + }, + "Case 14": { + "scenario": "A prominent lawyer was found poisoned at a dinner party.", + "clues": [ + {"type": "evidence", "text": "The poison was in his wine glass."}, + {"type": "evidence", "text": "A broken glass was found on the floor."}, + {"type": "witness", "text": "A guest heard an argument shortly before the victim collapsed."} + ], + "suspects": { + "A Rival Lawyer": { + "motive": "He wanted to eliminate competition.", + "alibi": "He claims he was in the restroom." + }, + "A Client": { + "motive": "He was unhappy with the lawyer's representation.", + "alibi": "He says he was outside." + }, + "A Family Member": { + "motive": "They had a longstanding feud.", + "alibi": "She was talking to other guests." + } + }, + "solution": "A Rival Lawyer." + }, + "Case 15": { + "scenario": "A famous author was found dead in her study.", + "clues": [ + {"type": "evidence", "text": "A manuscript was missing."}, + {"type": "evidence", "text": "There were signs of forced entry."}, + {"type": "witness", "text": "A neighbor saw a stranger leaving the house."} + ], + "suspects": { + "A Literary Agent": { + "motive": "He wanted to control the author's work.", + "alibi": "He was at a meeting." + }, + "A Jealous Writer": { + "motive": "He was envious of her success.", + "alibi": "He claims he was at a bar." + }, + "A Family Member": { + "motive": "They wanted the inheritance.", + "alibi": "He was out running errands." + } + }, + "solution": "A Jealous Writer." + }, + "Case 16": { + "scenario": "A renowned architect was found dead in his office.", + "clues": [ + {"type": "evidence", "text": "A blueprint for a new project was missing."}, + {"type": "evidence", "text": "There was a strange odor in the air."}, + {"type": "witness", "text": "A security guard saw someone leave the building late at night."} + ], + "suspects": { + "A Business Partner": { + "motive": "He wanted full control of the firm.", + "alibi": "He claims he was out of town." + }, + "An Assistant": { + "motive": "She was tired of being underappreciated.", + "alibi": "She was working overtime." + }, + "A Rival Architect": { + "motive": "He wanted to ruin the architect's reputation.", + "alibi": "He was attending a seminar." + } + }, + "solution": "A Business Partner." + }, + "Case 17": { + "scenario": "A social media influencer was blackmailed.", + "clues": [ + {"type": "evidence", "text": "Threatening messages were found on her phone."}, + {"type": "evidence", "text": "A security video showed someone entering her home."}, + {"type": "witness", "text": "A neighbor heard a loud argument."} + ], + "suspects": { + "A Former Friend": { + "motive": "She was jealous of the influencer's success.", + "alibi": "She claims she was at a party." + }, + "A Stalker": { + "motive": "He was obsessed with her online persona.", + "alibi": "He says he was at home." + }, + "An Ex-Manager": { + "motive": "He wanted revenge after being fired.", + "alibi": "He was traveling." + } + }, + "solution": "A Former Friend." + }, + "Case 18": { + "scenario": "A successful entrepreneur was found dead in his mansion.", + "clues": [ + {"type": "evidence", "text": "A broken vase was found near the body."}, + {"type": "evidence", "text": "His bank accounts were accessed just before his death."}, + {"type": "witness", "text": "A gardener saw someone leave the mansion."} + ], + "suspects": { + "A Business Rival": { + "motive": "He wanted to eliminate competition.", + "alibi": "He was at a conference." + }, + "A Family Member": { + "motive": "She wanted to inherit the fortune.", + "alibi": "She was at a charity event." + }, + "A Housekeeper": { + "motive": "She was unhappy with her pay.", + "alibi": "She was cleaning the garage." + } + }, + "solution": "A Business Rival." + }, + "Case 19": { + "scenario": "A famous actor was found dead on set.", + "clues": [ + {"type": "evidence", "text": "The prop gun was found loaded."}, + {"type": "evidence", "text": "There was a note threatening the actor."}, + {"type": "witness", "text": "A crew member heard a loud bang."} + ], + "suspects": { + "The Director": { + "motive": "He wanted to boost the drama of the film.", + "alibi": "He was reviewing footage." + }, + "A Co-Star": { + "motive": "She was envious of the actor's fame.", + "alibi": "She claims she was in her trailer." + }, + "A Stunt Double": { + "motive": "He wanted the lead role.", + "alibi": "He says he was in the gym." + } + }, + "solution": "The Co-Star." + }, + "Case 20": { + "scenario": "A startup's confidential project was leaked.", + "clues": [ + {"type": "evidence", "text": "An employee's computer was accessed without permission."}, + {"type": "evidence", "text": "A file with sensitive information was missing."}, + {"type": "witness", "text": "A delivery person saw someone acting suspiciously."} + ], + "suspects": { + "The Lead Developer": { + "motive": "He wanted to sell the information to a rival company.", + "alibi": "He was at a team meeting." + }, + "An Intern": { + "motive": "She was hoping to impress a recruiter.", + "alibi": "She claims she was fetching coffee." + }, + "The CEO": { + "motive": "He wanted to cover up a previous mistake.", + "alibi": "He was in a different office." + } + }, + "solution": "The Intern." + }, + "Case 21": { + "scenario": "A championship trophy was stolen before the game.", + "clues": [ + {"type": "evidence", "text": "The trophy case was broken into."}, + {"type": "evidence", "text": "A security guard saw a player near the case."}, + {"type": "witness", "text": "A fan reported seeing someone acting suspiciously."} + ], + "suspects": { + "A Rival Team Player": { + "motive": "He wanted to sabotage the competition.", + "alibi": "He claims he was practicing." + }, + "The Team Coach": { + "motive": "He wanted to distract the team.", + "alibi": "He was in a meeting." + }, + "A Die-Hard Fan": { + "motive": "He wanted to keep the trophy safe.", + "alibi": "He says he was at home." + } + }, + "solution": "A Rival Team Player." + }, + "Case 22": { + "scenario": "A museum exhibit was vandalized overnight.", + "clues": [ + {"type": "evidence", "text": "Security footage was tampered with."}, + {"type": "evidence", "text": "There were paint stains found on the floor."}, + {"type": "witness", "text": "A night guard heard noises."} + ], + "suspects": { + "A Rival Artist": { + "motive": "He was jealous of the exhibit's success.", + "alibi": "He claims he was at a gallery opening." + }, + "A Museum Curator": { + "motive": "He wanted to change the exhibit.", + "alibi": "He was at home." + }, + "A Teenager": { + "motive": "He wanted to impress his friends.", + "alibi": "He says he was out skateboarding." + } + }, + "solution": "A Rival Artist." + }, + "Case 23": { + "scenario": "A car was found abandoned after a hit-and-run.", + "clues": [ + {"type": "evidence", "text": "The car's license plate was traced to a local dealer."}, + {"type": "evidence", "text": "Paint residue matched a nearby vehicle."}, + {"type": "witness", "text": "A pedestrian saw the accident."} + ], + "suspects": { + "A Local Mechanic": { + "motive": "He wanted to cover up his own accident.", + "alibi": "He was working on another car." + }, + "A Distracted Driver": { + "motive": "He was using his phone at the time.", + "alibi": "He claims he was at the grocery store." + }, + "A Teenager": { + "motive": "He was running late for an event.", + "alibi": "He says he was on a date." + } + }, + "solution": "A Distracted Driver." + }, + "Case 24": { + "scenario": "A local charity's funds were embezzled.", + "clues": [ + {"type": "evidence", "text": "Bank statements showed unauthorized withdrawals."}, + {"type": "evidence", "text": "A computer log was deleted."}, + {"type": "witness", "text": "An employee saw someone in the office late at night."} + ], + "suspects": { + "The Treasurer": { + "motive": "He wanted to pay off personal debts.", + "alibi": "He claims he was at a fundraiser." + }, + "A Volunteer": { + "motive": "She was unhappy with her role.", + "alibi": "She was at home." + }, + "The Charity Director": { + "motive": "He wanted to cover up his own mismanagement.", + "alibi": "He was traveling for business." + } + }, + "solution": "The Treasurer." + }, + "Case 25": { + "scenario": "A community leader was found dead during a town hall meeting.", + "clues": [ + {"type": "evidence", "text": "There were signs of a struggle in the meeting room."}, + {"type": "evidence", "text": "A broken chair was found nearby."}, + {"type": "witness", "text": "A participant heard shouting before the meeting started."} + ], + "suspects": { + "A Local Businessman": { + "motive": "He was angry over a recent decision against his interests.", + "alibi": "He claims he was speaking with constituents." + }, + "A Fellow Community Leader": { + "motive": "She was envious of his popularity.", + "alibi": "She was giving a presentation." + }, + "A Distraught Citizen": { + "motive": "He was unhappy with local policies.", + "alibi": "He was in the back of the room." + } + }, + "solution": "A Local Businessman." + } +} + +def speak(text): + tts_engine.say(text) + tts_engine.runAndWait() + +def listen(): + with sr.Microphone() as source: + print("Listening...") + audio = recognizer.listen(source) + try: + text = recognizer.recognize_google(audio) + print(f"You said: {text}") + return text.lower() + except sr.UnknownValueError: + speak("Sorry, I did not understand that.") + return "" + except sr.RequestError: + speak("Could not request results; check your internet connection.") + return "" + +def present_case(case_name): + case = cases[case_name] + speak(f"Welcome to {case_name}.") + speak(case["scenario"]) + + for clue in case["clues"]: + speak(f"Clue: {clue['text']}") + + speak("Would you like to know about the suspects, ask for a hint, or make an accusation?") + + points = 0 + while True: + choice = listen() + if "suspects" in choice: + speak("Here are the suspects:") + for suspect, details in case["suspects"].items(): + speak(f"{suspect}: {details['motive']}") + speak(f"Alibi: {details['alibi']}") + speak("Would you like to make an accusation or ask for a hint?") + elif "hint" in choice: + hint = random.choice(case["clues"]) + speak(f"Hint: {hint['text']}") + points += 1 # Earn points for asking hints + speak("You earned a point for asking a hint!") + elif "accusation" in choice: + speak("Who do you accuse?") + accusation = listen() + if accusation in case["suspects"]: + speak("You accused " + accusation + ".") + if accusation == case["solution"]: + speak("Congratulations! You solved the case!") + points += 5 # Earn points for solving the case + break + else: + speak("That's incorrect. Try again.") + else: + speak("That suspect is not in this case. Please name a valid suspect.") + else: + speak("I didn't catch that. Please choose to know about the suspects, ask for a hint, or make an accusation.") + +# Start the game +speak("Welcome to the Murder Mystery Game! Please say the name of the case you want to solve.") +case_names = list(cases.keys()) +case_choice = listen() +if case_choice in case_names: + present_case(case_choice) +else: + speak("That case is not available. Please choose a valid case.") diff --git a/Find_a_way.py b/Python Games/Find_a_way.py similarity index 100% rename from Find_a_way.py rename to Python Games/Find_a_way.py diff --git a/Guesser.py b/Python Games/Guesser.py similarity index 100% rename from Guesser.py rename to Python Games/Guesser.py diff --git a/Interactive Storytelling b/Python Games/Interactive Storytelling similarity index 100% rename from Interactive Storytelling rename to Python Games/Interactive Storytelling diff --git a/NewLogin b/Python Games/NewLogin similarity index 100% rename from NewLogin rename to Python Games/NewLogin diff --git a/Quiz_Game b/Python Games/Quiz_Game similarity index 100% rename from Quiz_Game rename to Python Games/Quiz_Game diff --git a/Recipes b/Python Games/Recipes similarity index 100% rename from Recipes rename to Python Games/Recipes diff --git a/Rhythm_of_Knowledge b/Python Games/Rhythm_of_Knowledge similarity index 100% rename from Rhythm_of_Knowledge rename to Python Games/Rhythm_of_Knowledge diff --git a/Rock Paper Scissors game b/Python Games/Rock Paper Scissors game similarity index 100% rename from Rock Paper Scissors game rename to Python Games/Rock Paper Scissors game diff --git a/Rock_Paper_Scissors_Game.py b/Python Games/Rock_Paper_Scissors_Game.py similarity index 100% rename from Rock_Paper_Scissors_Game.py rename to Python Games/Rock_Paper_Scissors_Game.py diff --git a/Tic Tac Toc b/Python Games/Tic Tac Toc similarity index 100% rename from Tic Tac Toc rename to Python Games/Tic Tac Toc diff --git a/Tutor.py b/Python Games/Tutor.py similarity index 97% rename from Tutor.py rename to Python Games/Tutor.py index 3725f67..dafa4fb 100644 --- a/Tutor.py +++ b/Python Games/Tutor.py @@ -1,200 +1,200 @@ -import speech_recognition as sr -import pyttsx3 -import json -import random - -# Initialize the TTS engine -engine = pyttsx3.init() -engine.setProperty('rate', 150) - -# Initialize empty user data -user_data = {} - -# Function to speak text -def speak(text): - engine.say(text) - engine.runAndWait() - -# Function to capture voice input -def voice_to_text(): - recognizer = sr.Recognizer() - with sr.Microphone() as source: - print("Listening for your command...") - try: - audio = recognizer.listen(source, timeout=10) # Timeout after 10 seconds - command = recognizer.recognize_google(audio) - print(f"Captured voice command: {command}") - return command - except sr.UnknownValueError: - speak("I didn't catch that. Could you please repeat?") - return None - except sr.RequestError: - speak("The speech recognition service is unavailable at the moment.") - return None - -# Function to load user profiles -def load_user_data(): - global user_data - try: - with open("user_data.json", "r") as f: - user_data = json.load(f) - except FileNotFoundError: - print("No previous user data found.") - except json.JSONDecodeError: - print("Error reading user data. Starting with an empty user profile.") - -# Function to save user profiles -def save_user_data(): - with open("user_data.json", "w") as f: - json.dump(user_data, f) - -# Create a user profile if it doesn't exist -def create_user_profile(user_name): - if user_name not in user_data: - user_data[user_name] = {"quiz_scores": [], "preferred_language": "Spanish"} - -# Get the user's name -def get_user_name(): - speak("What is your name?") - user_name = voice_to_text() - if user_name: - return user_name.lower() - return "default_user" - -# Math tutoring function -def math_tutor(): - speak("What math problem would you like help with?") - user_input = voice_to_text() - - if user_input: - if "2 plus 2" in user_input.lower(): - speak("The answer to 2 plus 2 is 4.") - elif "quadratic formula" in user_input.lower(): - speak("The quadratic formula is negative b plus or minus the square root of b squared minus 4ac, all divided by 2a.") - else: - speak("I'm not sure of the answer. Would you like me to search online or provide a step-by-step explanation?") - else: - speak("I didn't understand your request. Could you please repeat?") - -# Language practice function -def language_practice(language="Spanish"): - supported_languages = ["spanish", "french"] - if language.lower() not in supported_languages: - speak(f"Sorry, I only support {', '.join(supported_languages)} at the moment.") - return - - speak(f"Let's practice {language}. Please say a sentence in {language}, and I'll correct it if needed.") - user_sentence = voice_to_text() - - if user_sentence: - if language.lower() == "spanish" and "estoy aprendiendo español" in user_sentence.lower(): - speak("Great! Your sentence is correct.") - elif language.lower() == "french" and "je parle français" in user_sentence.lower(): - speak("Great! Your sentence is correct.") - else: - speak(f"Sorry, I didn't understand that {language} sentence.") - else: - speak("Could you try that sentence again?") - -# Interactive quiz function with randomization -def quiz(user_name, subject="math"): - question_bank = { - "math": [ - {"question": "What is 5 times 6?", "answer": "30"}, - {"question": "What is the square root of 64?", "answer": "8"}, - {"question": "What is 9 minus 3?", "answer": "6"} - ], - "science": [ - {"question": "What is the chemical symbol for water?", "answer": "H2O"}, - {"question": "What planet is known as the Red Planet?", "answer": "Mars"}, - {"question": "What is the atomic number of hydrogen?", "answer": "1"} - ] - } - - # Ensure there are enough questions to sample from - if len(question_bank[subject]) < 2: - speak("Not enough questions available for this subject.") - return - - questions = random.sample(question_bank[subject], 2) # Select 2 random questions - - score = 0 - for q in questions: - speak(q["question"]) - user_answer = voice_to_text() - - if not user_answer: - speak("I didn't hear an answer. Could you try again?") - continue - - if q["answer"].lower() in user_answer.lower(): - speak("That's correct!") - score += 1 - else: - speak(f"Sorry, the correct answer is {q['answer']}.") - - user_data[user_name]["quiz_scores"].append({"subject": subject, "score": score}) - speak(f"Your final score is {score} out of {len(questions)}.") - -# Function to handle follow-up questions -def handle_follow_up(): - speak("Do you need help with anything else?") - response = voice_to_text() - if response and ("yes" in response.lower() or "sure" in response.lower()): - return True - else: - speak("Okay, have a great day!") - return False - -# Main function for the voice assistant -if __name__ == "__main__": - load_user_data() - user_name = get_user_name() - create_user_profile(user_name) - - speak(f"Hello {user_name.capitalize()}, how can I assist you today?") - - while True: - command = voice_to_text() - - if command is None: - continue # Retry if the command was not understood - - if "exit" in command.lower() or "stop" in command.lower(): - speak("Goodbye! Stay curious and keep learning!") - save_user_data() - break - - # Trigger math tutoring - elif "math" in command.lower() and "help" in command.lower(): - math_tutor() - - # Trigger language practice - elif "practice" in command.lower() and "language" in command.lower(): - preferred_language = user_data[user_name]["preferred_language"] - speak(f"Would you like to practice {preferred_language}, or a different language?") - language_choice = voice_to_text() - if "different" in language_choice.lower(): - speak("Which language would you like to practice?") - preferred_language = voice_to_text() - if preferred_language: - user_data[user_name]["preferred_language"] = preferred_language - language_practice(preferred_language) - - # Trigger quiz - elif "quiz" in command.lower(): - speak("Which subject would you like a quiz on? Math or Science?") - subject_choice = voice_to_text() - if "math" in subject_choice.lower(): - quiz(user_name, "math") - elif "science" in subject_choice.lower(): - quiz(user_name, "science") - else: - speak("I only have quizzes for math and science at the moment.") - - else: - speak("I didn't catch that. Please say a valid command, like 'math help' or 'start a quiz'.") - - if not handle_follow_up(): - save_user_data() - break +import speech_recognition as sr +import pyttsx3 +import json +import random + +# Initialize the TTS engine +engine = pyttsx3.init() +engine.setProperty('rate', 150) + +# Initialize empty user data +user_data = {} + +# Function to speak text +def speak(text): + engine.say(text) + engine.runAndWait() + +# Function to capture voice input +def voice_to_text(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening for your command...") + try: + audio = recognizer.listen(source, timeout=10) # Timeout after 10 seconds + command = recognizer.recognize_google(audio) + print(f"Captured voice command: {command}") + return command + except sr.UnknownValueError: + speak("I didn't catch that. Could you please repeat?") + return None + except sr.RequestError: + speak("The speech recognition service is unavailable at the moment.") + return None + +# Function to load user profiles +def load_user_data(): + global user_data + try: + with open("user_data.json", "r") as f: + user_data = json.load(f) + except FileNotFoundError: + print("No previous user data found.") + except json.JSONDecodeError: + print("Error reading user data. Starting with an empty user profile.") + +# Function to save user profiles +def save_user_data(): + with open("user_data.json", "w") as f: + json.dump(user_data, f) + +# Create a user profile if it doesn't exist +def create_user_profile(user_name): + if user_name not in user_data: + user_data[user_name] = {"quiz_scores": [], "preferred_language": "Spanish"} + +# Get the user's name +def get_user_name(): + speak("What is your name?") + user_name = voice_to_text() + if user_name: + return user_name.lower() + return "default_user" + +# Math tutoring function +def math_tutor(): + speak("What math problem would you like help with?") + user_input = voice_to_text() + + if user_input: + if "2 plus 2" in user_input.lower(): + speak("The answer to 2 plus 2 is 4.") + elif "quadratic formula" in user_input.lower(): + speak("The quadratic formula is negative b plus or minus the square root of b squared minus 4ac, all divided by 2a.") + else: + speak("I'm not sure of the answer. Would you like me to search online or provide a step-by-step explanation?") + else: + speak("I didn't understand your request. Could you please repeat?") + +# Language practice function +def language_practice(language="Spanish"): + supported_languages = ["spanish", "french"] + if language.lower() not in supported_languages: + speak(f"Sorry, I only support {', '.join(supported_languages)} at the moment.") + return + + speak(f"Let's practice {language}. Please say a sentence in {language}, and I'll correct it if needed.") + user_sentence = voice_to_text() + + if user_sentence: + if language.lower() == "spanish" and "estoy aprendiendo español" in user_sentence.lower(): + speak("Great! Your sentence is correct.") + elif language.lower() == "french" and "je parle français" in user_sentence.lower(): + speak("Great! Your sentence is correct.") + else: + speak(f"Sorry, I didn't understand that {language} sentence.") + else: + speak("Could you try that sentence again?") + +# Interactive quiz function with randomization +def quiz(user_name, subject="math"): + question_bank = { + "math": [ + {"question": "What is 5 times 6?", "answer": "30"}, + {"question": "What is the square root of 64?", "answer": "8"}, + {"question": "What is 9 minus 3?", "answer": "6"} + ], + "science": [ + {"question": "What is the chemical symbol for water?", "answer": "H2O"}, + {"question": "What planet is known as the Red Planet?", "answer": "Mars"}, + {"question": "What is the atomic number of hydrogen?", "answer": "1"} + ] + } + + # Ensure there are enough questions to sample from + if len(question_bank[subject]) < 2: + speak("Not enough questions available for this subject.") + return + + questions = random.sample(question_bank[subject], 2) # Select 2 random questions + + score = 0 + for q in questions: + speak(q["question"]) + user_answer = voice_to_text() + + if not user_answer: + speak("I didn't hear an answer. Could you try again?") + continue + + if q["answer"].lower() in user_answer.lower(): + speak("That's correct!") + score += 1 + else: + speak(f"Sorry, the correct answer is {q['answer']}.") + + user_data[user_name]["quiz_scores"].append({"subject": subject, "score": score}) + speak(f"Your final score is {score} out of {len(questions)}.") + +# Function to handle follow-up questions +def handle_follow_up(): + speak("Do you need help with anything else?") + response = voice_to_text() + if response and ("yes" in response.lower() or "sure" in response.lower()): + return True + else: + speak("Okay, have a great day!") + return False + +# Main function for the voice assistant +if __name__ == "__main__": + load_user_data() + user_name = get_user_name() + create_user_profile(user_name) + + speak(f"Hello {user_name.capitalize()}, how can I assist you today?") + + while True: + command = voice_to_text() + + if command is None: + continue # Retry if the command was not understood + + if "exit" in command.lower() or "stop" in command.lower(): + speak("Goodbye! Stay curious and keep learning!") + save_user_data() + break + + # Trigger math tutoring + elif "math" in command.lower() and "help" in command.lower(): + math_tutor() + + # Trigger language practice + elif "practice" in command.lower() and "language" in command.lower(): + preferred_language = user_data[user_name]["preferred_language"] + speak(f"Would you like to practice {preferred_language}, or a different language?") + language_choice = voice_to_text() + if "different" in language_choice.lower(): + speak("Which language would you like to practice?") + preferred_language = voice_to_text() + if preferred_language: + user_data[user_name]["preferred_language"] = preferred_language + language_practice(preferred_language) + + # Trigger quiz + elif "quiz" in command.lower(): + speak("Which subject would you like a quiz on? Math or Science?") + subject_choice = voice_to_text() + if "math" in subject_choice.lower(): + quiz(user_name, "math") + elif "science" in subject_choice.lower(): + quiz(user_name, "science") + else: + speak("I only have quizzes for math and science at the moment.") + + else: + speak("I didn't catch that. Please say a valid command, like 'math help' or 'start a quiz'.") + + if not handle_follow_up(): + save_user_data() + break diff --git a/akinator.py b/Python Games/akinator.py similarity index 100% rename from akinator.py rename to Python Games/akinator.py diff --git a/chess.py b/Python Games/chess.py similarity index 100% rename from chess.py rename to Python Games/chess.py diff --git a/eeg_game.py b/Python Games/eeg_game.py similarity index 100% rename from eeg_game.py rename to Python Games/eeg_game.py diff --git a/game.py b/Python Games/game.py similarity index 100% rename from game.py rename to Python Games/game.py diff --git a/jokes.py b/Python Games/jokes.py similarity index 96% rename from jokes.py rename to Python Games/jokes.py index 6cd6aeb..78f9676 100644 --- a/jokes.py +++ b/Python Games/jokes.py @@ -1,144 +1,144 @@ -import pyjokes -import pickle -import os - -favourites = [] -last_joke = "" - -FAVOURITES = "favourites.pkl" - -def load_favourites(): - global favourites - if os.path.exists(FAVOURITES): - with open(FAVOURITES, "rb") as file: - favourites = pickle.load(file) - print("Load the favourite jokes from previous visit") - show_favourites() - else: - print("No favourites jokes to load") - -def save_favourites_to_file(): - with open(FAVOURITES, "wb") as file: - pickle.dump(favourites, file) - -def clear_loaded_favourites(): - global favourites - if os.path.exists(FAVOURITES): - os.remove(FAVOURITES) - favourites = [] - print("Loaded jokes from previous visit cleared") - else: - print("No loaded jokes to clear") - -def tell_joke(category='neutral'): - global last_joke - try: - joke = pyjokes.get_joke(category=category) - last_joke = joke - print(joke) - except ValueError as error: - print(f"Error in fetching joke: {error}") - print("Falling back to a neutral joke") - last_joke = pyjokes.get_joke(category='neutral') - print(last_joke) - -def get_category_jokes(): - print("Choose a joke category:") - print("1. Neutral") - print("2. Chuck Norris") - print("3. Twister") - print("4. All") - choice = input("Enter your choice (1-4): ") - - if choice == "1": - return "neutral" - elif choice == "2" or choice == "3": - return "all" - elif choice == "4": - return "all" - else: - print("Oops! That's not on the list. Let's go to neutral for now!") - return "neutral" - - -def show_favourites(): - if favourites: - print("Your favourite jokes:") - for idx, joke in enumerate(favourites, 1): - print(f"{idx}. {joke}") - else: - print("No favorite jokes saved yet!") - -def save_favourites(joke): - favourites.append(joke) - print("The joke saved to favourites!!") - save_favourites_to_file() - -def clear_favourites(): - if favourites: - favourites.clear() - print("All favourites jokes are cleared") - else: - print("No favourites jokes to clear") - -def delete_favourite(): - show_favourites() - if favourites: - try: - choice = int(input("Enter the number of the joke you want to delete: ")) - 1 - if 0 <= choice < len(favourites): - removed_joke = favourites.pop(choice) - print(f"Deleted joke: {removed_joke}") - save_favourites_to_file() - else: - print("Invalid choice, no joke deleted.") - except ValueError: - print("Please enter a valid number.") - -def joke_voice_assistant(): - load_favourites() - while True: - print("\nWhat would you like to do?") - print("1. Tell me a new joke") - print("2. Repeat the previous joke") - print("3. Save the last joke to favourites") - print("4. Show favourite ones!") - print("5. Clear all the favourite jokes") - print("6. Delete a favourite jokes") - print("7. Show the favourite joke from previous visit") - print("8. Clear loaded jokes from previous visit") - print("9. Exit") - - choice = input("Please select option (1-9): ") - - if choice == "1": - category = get_category_jokes() - tell_joke(category) - elif choice == "2": - if last_joke: - print(f"Last joke: {last_joke}") - else: - print("No joke has been told.") - elif choice == "3": - if last_joke: - save_favourites(last_joke) - else: - print("No joke has been told.") - elif choice == "4": - show_favourites() - elif choice == "5": - clear_favourites() - elif choice == "6": - delete_favourite() - elif choice == "7": - load_favourites() - elif choice == "8": - clear_loaded_favourites() - elif choice == "9": - print("Bye, take care!!") - break - else: - print("Oops! That's not on the list, try again later") - -if __name__ == "__main__": +import pyjokes +import pickle +import os + +favourites = [] +last_joke = "" + +FAVOURITES = "favourites.pkl" + +def load_favourites(): + global favourites + if os.path.exists(FAVOURITES): + with open(FAVOURITES, "rb") as file: + favourites = pickle.load(file) + print("Load the favourite jokes from previous visit") + show_favourites() + else: + print("No favourites jokes to load") + +def save_favourites_to_file(): + with open(FAVOURITES, "wb") as file: + pickle.dump(favourites, file) + +def clear_loaded_favourites(): + global favourites + if os.path.exists(FAVOURITES): + os.remove(FAVOURITES) + favourites = [] + print("Loaded jokes from previous visit cleared") + else: + print("No loaded jokes to clear") + +def tell_joke(category='neutral'): + global last_joke + try: + joke = pyjokes.get_joke(category=category) + last_joke = joke + print(joke) + except ValueError as error: + print(f"Error in fetching joke: {error}") + print("Falling back to a neutral joke") + last_joke = pyjokes.get_joke(category='neutral') + print(last_joke) + +def get_category_jokes(): + print("Choose a joke category:") + print("1. Neutral") + print("2. Chuck Norris") + print("3. Twister") + print("4. All") + choice = input("Enter your choice (1-4): ") + + if choice == "1": + return "neutral" + elif choice == "2" or choice == "3": + return "all" + elif choice == "4": + return "all" + else: + print("Oops! That's not on the list. Let's go to neutral for now!") + return "neutral" + + +def show_favourites(): + if favourites: + print("Your favourite jokes:") + for idx, joke in enumerate(favourites, 1): + print(f"{idx}. {joke}") + else: + print("No favorite jokes saved yet!") + +def save_favourites(joke): + favourites.append(joke) + print("The joke saved to favourites!!") + save_favourites_to_file() + +def clear_favourites(): + if favourites: + favourites.clear() + print("All favourites jokes are cleared") + else: + print("No favourites jokes to clear") + +def delete_favourite(): + show_favourites() + if favourites: + try: + choice = int(input("Enter the number of the joke you want to delete: ")) - 1 + if 0 <= choice < len(favourites): + removed_joke = favourites.pop(choice) + print(f"Deleted joke: {removed_joke}") + save_favourites_to_file() + else: + print("Invalid choice, no joke deleted.") + except ValueError: + print("Please enter a valid number.") + +def joke_voice_assistant(): + load_favourites() + while True: + print("\nWhat would you like to do?") + print("1. Tell me a new joke") + print("2. Repeat the previous joke") + print("3. Save the last joke to favourites") + print("4. Show favourite ones!") + print("5. Clear all the favourite jokes") + print("6. Delete a favourite jokes") + print("7. Show the favourite joke from previous visit") + print("8. Clear loaded jokes from previous visit") + print("9. Exit") + + choice = input("Please select option (1-9): ") + + if choice == "1": + category = get_category_jokes() + tell_joke(category) + elif choice == "2": + if last_joke: + print(f"Last joke: {last_joke}") + else: + print("No joke has been told.") + elif choice == "3": + if last_joke: + save_favourites(last_joke) + else: + print("No joke has been told.") + elif choice == "4": + show_favourites() + elif choice == "5": + clear_favourites() + elif choice == "6": + delete_favourite() + elif choice == "7": + load_favourites() + elif choice == "8": + clear_loaded_favourites() + elif choice == "9": + print("Bye, take care!!") + break + else: + print("Oops! That's not on the list, try again later") + +if __name__ == "__main__": joke_voice_assistant() \ No newline at end of file diff --git a/login_credentials b/Python Games/login_credentials similarity index 100% rename from login_credentials rename to Python Games/login_credentials diff --git a/mood.py b/Python Games/mood.py similarity index 100% rename from mood.py rename to Python Games/mood.py diff --git a/rock_paper_scissor_game.py b/Python Games/rock_paper_scissor_game.py similarity index 100% rename from rock_paper_scissor_game.py rename to Python Games/rock_paper_scissor_game.py diff --git a/song_data.py b/Python Games/song_data.py similarity index 96% rename from song_data.py rename to Python Games/song_data.py index 6cbdaab..666bee6 100644 --- a/song_data.py +++ b/Python Games/song_data.py @@ -1,9 +1,9 @@ -# song_data.py - -# Dictionary to store song names and their YouTube links -SONGS = { - "khwab": "https://youtu.be/K1Uc52jzFIQ?si=omUolzwiR19uwuyL", - "song_name_2": "https://www.youtube.com/watch?v=example2", - # Add more songs as needed -} +# song_data.py + +# Dictionary to store song names and their YouTube links +SONGS = { + "khwab": "https://youtu.be/K1Uc52jzFIQ?si=omUolzwiR19uwuyL", + "song_name_2": "https://www.youtube.com/watch?v=example2", + # Add more songs as needed +} \ No newline at end of file diff --git a/song_quiz.py b/Python Games/song_quiz.py similarity index 100% rename from song_quiz.py rename to Python Games/song_quiz.py diff --git a/sound_wave.png b/Python Games/sound_wave.png similarity index 100% rename from sound_wave.png rename to Python Games/sound_wave.png diff --git a/sudoku.py b/Python Games/sudoku.py similarity index 100% rename from sudoku.py rename to Python Games/sudoku.py diff --git a/user_output.mp3 b/Python Games/user_output.mp3 similarity index 100% rename from user_output.mp3 rename to Python Games/user_output.mp3 diff --git a/voiceAssistant b/Python Games/voiceAssistant similarity index 100% rename from voiceAssistant rename to Python Games/voiceAssistant diff --git a/workout_planner.py b/Python Games/workout_planner.py similarity index 100% rename from workout_planner.py rename to Python Games/workout_planner.py diff --git a/AES encryption.py b/Python Snippets/AES encryption.py similarity index 100% rename from AES encryption.py rename to Python Snippets/AES encryption.py diff --git a/Customized_voice_responses.py b/Python Snippets/Customized_voice_responses.py similarity index 97% rename from Customized_voice_responses.py rename to Python Snippets/Customized_voice_responses.py index d3706cb..f7e44da 100644 --- a/Customized_voice_responses.py +++ b/Python Snippets/Customized_voice_responses.py @@ -1,217 +1,217 @@ -import speech_recognition as sr -import pyttsx3 -import json -import random -import datetime -import dateparser -import threading -import time -import asyncio - -# Initialize the TTS engine -engine = pyttsx3.init() -engine.setProperty('rate', 150) -user_data = {} -memory_data = {} - -# Define personality modes -personalities = { - "professional": {"humor": False, "formality": "high"}, - "casual": {"humor": True, "formality": "low"}, - "humorous": {"humor": True, "formality": "medium"}, - "formal": {"humor": False, "formality": "very_high"} -} - -current_personality = "professional" - -# Mood response based on time of day -def adjust_mood_based_on_time(): - current_hour = datetime.datetime.now().hour - if 5 <= current_hour < 12: - return "morning" - elif 12 <= current_hour < 18: - return "afternoon" - elif 18 <= current_hour < 22: - return "evening" - else: - return "night" - -# Asynchronous speak function with personality -async def speak_async(text, personality="professional"): - style = personalities.get(personality, personalities["professional"]) - - if style["humor"] and random.random() > 0.5: # Add humor randomly - text = f"{text} 😄 Just kidding!" - - if style["formality"] == "high": - text = f"Dear user, {text}" - - engine.say(text) - engine.runAndWait() - await asyncio.sleep(0.1) - -# Asynchronous voice recognition input -async def voice_to_text_async(): - recognizer = sr.Recognizer() - with sr.Microphone() as source: - print("Listening for your command...") - try: - audio = recognizer.listen(source, timeout=10) - command = recognizer.recognize_google(audio) - return command - except sr.UnknownValueError: - await speak_async("I didn't catch that. Could you please repeat?") - return None - except sr.RequestError: - await speak_async("The speech recognition service is unavailable at the moment.") - return None - -# Load and save user/memory data -def load_data(): - global user_data, memory_data - try: - with open("user_data.json", "r") as f: - user_data = json.load(f) - except FileNotFoundError: - print("No previous user data found.") - - try: - with open("memory_data.json", "r") as f: - memory_data = json.load(f) - except FileNotFoundError: - print("No previous memory data found.") - -def save_data(): - with open("user_data.json", "w") as f: - json.dump(user_data, f) - with open("memory_data.json", "w") as f: - json.dump(memory_data, f) - -# User Profile creation -def create_user_profile(user_name): - if user_name not in user_data: - user_data[user_name] = {"quiz_scores": [], "preferred_language": "Spanish"} - -# Get user name and personality -async def get_user_name_and_personality(): - await speak_async("What is your name?") - user_name = await voice_to_text_async() - - if not user_name: - user_name = "default_user" - user_name = user_name.lower() - - # Ask for preferred personality - await speak_async(f"Hello {user_name}, would you like me to be formal, casual, humorous, or professional?") - personality_choice = await voice_to_text_async() - personality_choice = personality_choice.lower() if personality_choice else "professional" - - if personality_choice in personalities: - global current_personality - current_personality = personality_choice - - return user_name - -# Reminder functions -async def add_reminder(user, note, time=None): - if user not in memory_data: - memory_data[user] = [] - - reminder = {"note": note, "reminder_time": time.isoformat() if time else None} - memory_data[user].append(reminder) - save_data() - - if time: - await speak_async(f"Reminder set for {note} at {time.strftime('%Y-%m-%d %H:%M:%S')}.", current_personality) - else: - await speak_async(f"Note saved: {note}", current_personality) - -async def list_active_reminders(user): - if user in memory_data: - active_reminders = [note for note in memory_data[user] if note.get("reminder_time")] - if active_reminders: - await speak_async("Here are your active reminders:", current_personality) - for reminder in active_reminders: - reminder_time = reminder.get("reminder_time") - await speak_async(f"Reminder: {reminder['note']} at {reminder_time}", current_personality) - else: - await speak_async("You have no active reminders.", current_personality) - else: - await speak_async("You have no saved reminders.", current_personality) - -# Contextual Memory Search -async def search_memory(user, keyword): - if user in memory_data: - results = [note for note in memory_data[user] if keyword.lower() in note["note"].lower()] - if results: - await speak_async(f"I found {len(results)} note(s) related to {keyword}:", current_personality) - for result in results: - await speak_async(result["note"], current_personality) - else: - await speak_async(f"No notes found containing {keyword}.", current_personality) - else: - await speak_async("No memory data available.", current_personality) - -# Math Tutor -async def math_tutor(): - await speak_async("What math problem would you like help with?", current_personality) - user_input = await voice_to_text_async() - - if user_input: - if "2 plus 2" in user_input.lower(): - await speak_async("The answer to 2 plus 2 is 4.", current_personality) - elif "quadratic formula" in user_input.lower(): - await speak_async("The quadratic formula is negative b plus or minus the square root of b squared minus 4ac, all divided by 2a.", current_personality) - else: - await speak_async("I'm not sure of the answer. Would you like me to search online or provide a step-by-step explanation?", current_personality) - else: - await speak_async("I didn't understand your request. Could you please repeat?", current_personality) - -# Main loop for the assistant -async def main(): - load_data() - user_name = await get_user_name_and_personality() - create_user_profile(user_name) - - await speak_async(f"Hello {user_name.capitalize()}, how can I assist you today?", current_personality) - - while True: - command = await voice_to_text_async() - - if command is None: - continue - - if "exit" in command.lower() or "stop" in command.lower(): - await speak_async("Goodbye! Stay curious and keep learning!", current_personality) - save_data() - break - - elif "math" in command.lower() and "help" in command.lower(): - await math_tutor() - - elif "remind" in command.lower(): - await speak_async("What should I remind you about?", current_personality) - reminder_note = await voice_to_text_async() - - await speak_async("When should I remind you?", current_personality) - reminder_time_input = await voice_to_text_async() - reminder_time = dateparser.parse(reminder_time_input) - - if reminder_note and reminder_time: - await add_reminder(user_name, reminder_note, reminder_time) - else: - await speak_async("I couldn't set the reminder. Please try again.", current_personality) - - elif "search" in command.lower() and "memory" in command.lower(): - await speak_async("What would you like me to search for?", current_personality) - keyword = await voice_to_text_async() - await search_memory(user_name, keyword) - - elif "list" in command.lower() and "reminder" in command.lower(): - await list_active_reminders(user_name) - - else: - await speak_async("I'm sorry, I didn't understand that command.", current_personality) - -if __name__ == "__main__": - asyncio.run(main()) +import speech_recognition as sr +import pyttsx3 +import json +import random +import datetime +import dateparser +import threading +import time +import asyncio + +# Initialize the TTS engine +engine = pyttsx3.init() +engine.setProperty('rate', 150) +user_data = {} +memory_data = {} + +# Define personality modes +personalities = { + "professional": {"humor": False, "formality": "high"}, + "casual": {"humor": True, "formality": "low"}, + "humorous": {"humor": True, "formality": "medium"}, + "formal": {"humor": False, "formality": "very_high"} +} + +current_personality = "professional" + +# Mood response based on time of day +def adjust_mood_based_on_time(): + current_hour = datetime.datetime.now().hour + if 5 <= current_hour < 12: + return "morning" + elif 12 <= current_hour < 18: + return "afternoon" + elif 18 <= current_hour < 22: + return "evening" + else: + return "night" + +# Asynchronous speak function with personality +async def speak_async(text, personality="professional"): + style = personalities.get(personality, personalities["professional"]) + + if style["humor"] and random.random() > 0.5: # Add humor randomly + text = f"{text} 😄 Just kidding!" + + if style["formality"] == "high": + text = f"Dear user, {text}" + + engine.say(text) + engine.runAndWait() + await asyncio.sleep(0.1) + +# Asynchronous voice recognition input +async def voice_to_text_async(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening for your command...") + try: + audio = recognizer.listen(source, timeout=10) + command = recognizer.recognize_google(audio) + return command + except sr.UnknownValueError: + await speak_async("I didn't catch that. Could you please repeat?") + return None + except sr.RequestError: + await speak_async("The speech recognition service is unavailable at the moment.") + return None + +# Load and save user/memory data +def load_data(): + global user_data, memory_data + try: + with open("user_data.json", "r") as f: + user_data = json.load(f) + except FileNotFoundError: + print("No previous user data found.") + + try: + with open("memory_data.json", "r") as f: + memory_data = json.load(f) + except FileNotFoundError: + print("No previous memory data found.") + +def save_data(): + with open("user_data.json", "w") as f: + json.dump(user_data, f) + with open("memory_data.json", "w") as f: + json.dump(memory_data, f) + +# User Profile creation +def create_user_profile(user_name): + if user_name not in user_data: + user_data[user_name] = {"quiz_scores": [], "preferred_language": "Spanish"} + +# Get user name and personality +async def get_user_name_and_personality(): + await speak_async("What is your name?") + user_name = await voice_to_text_async() + + if not user_name: + user_name = "default_user" + user_name = user_name.lower() + + # Ask for preferred personality + await speak_async(f"Hello {user_name}, would you like me to be formal, casual, humorous, or professional?") + personality_choice = await voice_to_text_async() + personality_choice = personality_choice.lower() if personality_choice else "professional" + + if personality_choice in personalities: + global current_personality + current_personality = personality_choice + + return user_name + +# Reminder functions +async def add_reminder(user, note, time=None): + if user not in memory_data: + memory_data[user] = [] + + reminder = {"note": note, "reminder_time": time.isoformat() if time else None} + memory_data[user].append(reminder) + save_data() + + if time: + await speak_async(f"Reminder set for {note} at {time.strftime('%Y-%m-%d %H:%M:%S')}.", current_personality) + else: + await speak_async(f"Note saved: {note}", current_personality) + +async def list_active_reminders(user): + if user in memory_data: + active_reminders = [note for note in memory_data[user] if note.get("reminder_time")] + if active_reminders: + await speak_async("Here are your active reminders:", current_personality) + for reminder in active_reminders: + reminder_time = reminder.get("reminder_time") + await speak_async(f"Reminder: {reminder['note']} at {reminder_time}", current_personality) + else: + await speak_async("You have no active reminders.", current_personality) + else: + await speak_async("You have no saved reminders.", current_personality) + +# Contextual Memory Search +async def search_memory(user, keyword): + if user in memory_data: + results = [note for note in memory_data[user] if keyword.lower() in note["note"].lower()] + if results: + await speak_async(f"I found {len(results)} note(s) related to {keyword}:", current_personality) + for result in results: + await speak_async(result["note"], current_personality) + else: + await speak_async(f"No notes found containing {keyword}.", current_personality) + else: + await speak_async("No memory data available.", current_personality) + +# Math Tutor +async def math_tutor(): + await speak_async("What math problem would you like help with?", current_personality) + user_input = await voice_to_text_async() + + if user_input: + if "2 plus 2" in user_input.lower(): + await speak_async("The answer to 2 plus 2 is 4.", current_personality) + elif "quadratic formula" in user_input.lower(): + await speak_async("The quadratic formula is negative b plus or minus the square root of b squared minus 4ac, all divided by 2a.", current_personality) + else: + await speak_async("I'm not sure of the answer. Would you like me to search online or provide a step-by-step explanation?", current_personality) + else: + await speak_async("I didn't understand your request. Could you please repeat?", current_personality) + +# Main loop for the assistant +async def main(): + load_data() + user_name = await get_user_name_and_personality() + create_user_profile(user_name) + + await speak_async(f"Hello {user_name.capitalize()}, how can I assist you today?", current_personality) + + while True: + command = await voice_to_text_async() + + if command is None: + continue + + if "exit" in command.lower() or "stop" in command.lower(): + await speak_async("Goodbye! Stay curious and keep learning!", current_personality) + save_data() + break + + elif "math" in command.lower() and "help" in command.lower(): + await math_tutor() + + elif "remind" in command.lower(): + await speak_async("What should I remind you about?", current_personality) + reminder_note = await voice_to_text_async() + + await speak_async("When should I remind you?", current_personality) + reminder_time_input = await voice_to_text_async() + reminder_time = dateparser.parse(reminder_time_input) + + if reminder_note and reminder_time: + await add_reminder(user_name, reminder_note, reminder_time) + else: + await speak_async("I couldn't set the reminder. Please try again.", current_personality) + + elif "search" in command.lower() and "memory" in command.lower(): + await speak_async("What would you like me to search for?", current_personality) + keyword = await voice_to_text_async() + await search_memory(user_name, keyword) + + elif "list" in command.lower() and "reminder" in command.lower(): + await list_active_reminders(user_name) + + else: + await speak_async("I'm sorry, I didn't understand that command.", current_personality) + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/Emotion Detection.py b/Python Snippets/Emotion Detection.py similarity index 100% rename from Emotion Detection.py rename to Python Snippets/Emotion Detection.py diff --git a/Gesture Recognition using CNN.py b/Python Snippets/Gesture Recognition using CNN.py similarity index 100% rename from Gesture Recognition using CNN.py rename to Python Snippets/Gesture Recognition using CNN.py diff --git a/Memory_assistance.py b/Python Snippets/Memory_assistance.py similarity index 97% rename from Memory_assistance.py rename to Python Snippets/Memory_assistance.py index 60ed6eb..4038845 100644 --- a/Memory_assistance.py +++ b/Python Snippets/Memory_assistance.py @@ -1,278 +1,278 @@ -import speech_recognition as sr -import pyttsx3 -import json -import random -import datetime -import dateparser -import threading -import time - -# Initialize the TTS engine -engine = pyttsx3.init() -engine.setProperty('rate', 150) - -# Initialize empty user data and memory data -user_data = {} -memory_data = {} - -# Function to speak text -def speak(text): - engine.say(text) - engine.runAndWait() - -# Function to capture voice input -def voice_to_text(): - recognizer = sr.Recognizer() - with sr.Microphone() as source: - print("Listening for your command...") - try: - audio = recognizer.listen(source, timeout=10) # Timeout after 10 seconds - command = recognizer.recognize_google(audio) - print(f"Captured voice command: {command}") - return command - except sr.UnknownValueError: - speak("I didn't catch that. Could you please repeat?") - return None - except sr.RequestError: - speak("The speech recognition service is unavailable at the moment.") - return None - -# Function to load user and memory data -def load_data(): - global user_data, memory_data - try: - with open("user_data.json", "r") as f: - user_data = json.load(f) - except FileNotFoundError: - print("No previous user data found.") - - try: - with open("memory_data.json", "r") as f: - memory_data = json.load(f) - except FileNotFoundError: - print("No previous memory data found.") - -# Function to save user and memory data -def save_data(): - with open("user_data.json", "w") as f: - json.dump(user_data, f) - with open("memory_data.json", "w") as f: - json.dump(memory_data, f) - -# Create a user profile if it doesn't exist -def create_user_profile(user_name): - if user_name not in user_data: - user_data[user_name] = {"quiz_scores": [], "preferred_language": "Spanish"} - -# Get the user's name -def get_user_name(): - speak("What is your name?") - user_name = voice_to_text() - return user_name.lower() if user_name else "default_user" - -# Function to handle reminders based on time and conversations -def add_reminder(user, note, time=None): - if user not in memory_data: - memory_data[user] = [] - - reminder = {"note": note, "reminder_time": time.isoformat() if time else None} - memory_data[user].append(reminder) - save_data() - - if time: - speak(f"Reminder set for {note} at {time.strftime('%Y-%m-%d %H:%M:%S')}.") - else: - speak(f"Note saved: {note}") - -def list_active_reminders(user): - if user in memory_data: - active_reminders = [note for note in memory_data[user] if note.get("reminder_time")] - if active_reminders: - speak("Here are your active reminders:") - for reminder in active_reminders: - reminder_time = reminder.get("reminder_time") - speak(f"Reminder: {reminder['note']} at {reminder_time}") - else: - speak("You have no active reminders.") - else: - speak("You have no saved reminders.") - -def search_memory(user, keyword): - if user in memory_data: - results = [note for note in memory_data[user] if keyword.lower() in note["note"].lower()] - if results: - speak(f"I found {len(results)} note(s) related to {keyword}:") - for result in results: - speak(result["note"]) - else: - speak(f"No notes found containing {keyword}.") - else: - speak("No memory data available.") - -# Recurring reminder function -def set_recurring_reminder(user, note, interval="daily"): - next_reminder_time = None - if interval == "daily": - next_reminder_time = datetime.datetime.now() + datetime.timedelta(days=1) - elif interval == "weekly": - next_reminder_time = datetime.datetime.now() + datetime.timedelta(weeks=1) - - memory_data[user].append({"note": note, "reminder_time": next_reminder_time.isoformat(), "interval": interval}) - save_data() - speak(f"I have set a {interval} reminder for {note}.") - -# Math tutoring function -def math_tutor(): - speak("What math problem would you like help with?") - user_input = voice_to_text() - - if user_input: - if "2 plus 2" in user_input.lower(): - speak("The answer to 2 plus 2 is 4.") - elif "quadratic formula" in user_input.lower(): - speak("The quadratic formula is negative b plus or minus the square root of b squared minus 4ac, all divided by 2a.") - else: - speak("I'm not sure of the answer. Would you like me to search online or provide a step-by-step explanation?") - else: - speak("I didn't understand your request. Could you please repeat?") - -# Language practice function -def language_practice(language="Spanish"): - supported_languages = ["spanish", "french"] - if language.lower() not in supported_languages: - speak(f"Sorry, I only support {', '.join(supported_languages)} at the moment.") - return - - speak(f"Let's practice {language}. Please say a sentence in {language}, and I'll correct it if needed.") - user_sentence = voice_to_text() - - if user_sentence: - if language.lower() == "spanish" and "estoy aprendiendo español" in user_sentence.lower(): - speak("Great! Your sentence is correct.") - elif language.lower() == "french" and "je parle français" in user_sentence.lower(): - speak("Great! Your sentence is correct.") - else: - speak(f"Sorry, I didn't understand that {language} sentence.") - else: - speak("Could you try that sentence again?") - -# Quiz function -def quiz(subject="math"): - question_bank = { - "math": [ - {"question": "What is 5 times 6?", "answer": "30"}, - {"question": "What is the square root of 64?", "answer": "8"}, - {"question": "What is 9 minus 3?", "answer": "6"} - ], - "science": [ - {"question": "What is the chemical symbol for water?", "answer": "H2O"}, - {"question": "What planet is known as the Red Planet?", "answer": "Mars"}, - {"question": "What is the atomic number of hydrogen?", "answer": "1"} - ] - } - - questions = random.sample(question_bank[subject], 2) # Select 2 random questions - - score = 0 - for q in questions: - speak(q["question"]) - user_answer = voice_to_text() - - if not user_answer: - speak("I didn't hear an answer. Could you try again?") - continue - - if q["answer"].lower() in user_answer.lower(): - speak("That's correct!") - score += 1 - else: - speak(f"Sorry, the correct answer is {q['answer']}.") - - speak(f"Your final score is {score} out of {len(questions)}.") - -# Background task to handle reminders asynchronously -def reminder_checker(): - while True: - current_time = datetime.datetime.now().isoformat() - for user, reminders in memory_data.items(): - for reminder in reminders: - if reminder.get("reminder_time") and reminder["reminder_time"] <= current_time: - speak(f"Reminder: {reminder['note']}") - reminders.remove(reminder) - save_data() - time.sleep(60) - -# Main function for the voice assistant -if __name__ == "__main__": - load_data() - user_name = get_user_name() - create_user_profile(user_name) - - # Start background thread for reminders - threading.Thread(target=reminder_checker, daemon=True).start() - - speak(f"Hello {user_name.capitalize()}, how can I assist you today?") - - while True: - command = voice_to_text() - - if command is None: - continue # Retry if the command was not understood - - if "exit" in command.lower() or "stop" in command.lower(): - speak("Goodbye! Stay curious and keep learning!") - save_data() - break - - # Trigger math tutoring - elif "math" in command.lower() and "help" in command.lower(): - math_tutor() - - # Trigger language practice - elif "practice" in command.lower() and "language" in command.lower(): - preferred_language = user_data[user_name]["preferred_language"] - speak(f"Would you like to practice {preferred_language}, or a different language?") - language_choice = voice_to_text() - if "different" in language_choice.lower(): - speak("Which language would you like to practice?") - preferred_language = voice_to_text() - user_data[user_name]["preferred_language"] = preferred_language - language_practice(preferred_language) - - # Trigger quiz - elif "quiz" in command.lower(): - speak("Which subject would you like a quiz on? Math or Science?") - subject_choice = voice_to_text() - if "math" in subject_choice.lower(): - quiz("math") - elif "science" in subject_choice.lower(): - quiz("science") - else: - speak("I only have quizzes for math and science at the moment.") - - # Add a reminder - elif "remind" in command.lower(): - speak("What should I remind you about?") - reminder_note = voice_to_text() - - speak("When should I remind you?") - reminder_time_input = voice_to_text() - reminder_time = dateparser.parse(reminder_time_input) - - if reminder_note and reminder_time: - add_reminder(user_name, reminder_note, reminder_time) - else: - speak("I couldn't set the reminder. Please try again.") - - # Search memory - elif "search" in command.lower() and "memory" in command.lower(): - speak("What would you like me to search for?") - keyword = voice_to_text() - search_memory(user_name, keyword) - - # List active reminders - elif "list" in command.lower() and "reminder" in command.lower(): - list_active_reminders(user_name) - - else: - speak("I'm sorry, I didn't understand that command.") +import speech_recognition as sr +import pyttsx3 +import json +import random +import datetime +import dateparser +import threading +import time + +# Initialize the TTS engine +engine = pyttsx3.init() +engine.setProperty('rate', 150) + +# Initialize empty user data and memory data +user_data = {} +memory_data = {} + +# Function to speak text +def speak(text): + engine.say(text) + engine.runAndWait() + +# Function to capture voice input +def voice_to_text(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening for your command...") + try: + audio = recognizer.listen(source, timeout=10) # Timeout after 10 seconds + command = recognizer.recognize_google(audio) + print(f"Captured voice command: {command}") + return command + except sr.UnknownValueError: + speak("I didn't catch that. Could you please repeat?") + return None + except sr.RequestError: + speak("The speech recognition service is unavailable at the moment.") + return None + +# Function to load user and memory data +def load_data(): + global user_data, memory_data + try: + with open("user_data.json", "r") as f: + user_data = json.load(f) + except FileNotFoundError: + print("No previous user data found.") + + try: + with open("memory_data.json", "r") as f: + memory_data = json.load(f) + except FileNotFoundError: + print("No previous memory data found.") + +# Function to save user and memory data +def save_data(): + with open("user_data.json", "w") as f: + json.dump(user_data, f) + with open("memory_data.json", "w") as f: + json.dump(memory_data, f) + +# Create a user profile if it doesn't exist +def create_user_profile(user_name): + if user_name not in user_data: + user_data[user_name] = {"quiz_scores": [], "preferred_language": "Spanish"} + +# Get the user's name +def get_user_name(): + speak("What is your name?") + user_name = voice_to_text() + return user_name.lower() if user_name else "default_user" + +# Function to handle reminders based on time and conversations +def add_reminder(user, note, time=None): + if user not in memory_data: + memory_data[user] = [] + + reminder = {"note": note, "reminder_time": time.isoformat() if time else None} + memory_data[user].append(reminder) + save_data() + + if time: + speak(f"Reminder set for {note} at {time.strftime('%Y-%m-%d %H:%M:%S')}.") + else: + speak(f"Note saved: {note}") + +def list_active_reminders(user): + if user in memory_data: + active_reminders = [note for note in memory_data[user] if note.get("reminder_time")] + if active_reminders: + speak("Here are your active reminders:") + for reminder in active_reminders: + reminder_time = reminder.get("reminder_time") + speak(f"Reminder: {reminder['note']} at {reminder_time}") + else: + speak("You have no active reminders.") + else: + speak("You have no saved reminders.") + +def search_memory(user, keyword): + if user in memory_data: + results = [note for note in memory_data[user] if keyword.lower() in note["note"].lower()] + if results: + speak(f"I found {len(results)} note(s) related to {keyword}:") + for result in results: + speak(result["note"]) + else: + speak(f"No notes found containing {keyword}.") + else: + speak("No memory data available.") + +# Recurring reminder function +def set_recurring_reminder(user, note, interval="daily"): + next_reminder_time = None + if interval == "daily": + next_reminder_time = datetime.datetime.now() + datetime.timedelta(days=1) + elif interval == "weekly": + next_reminder_time = datetime.datetime.now() + datetime.timedelta(weeks=1) + + memory_data[user].append({"note": note, "reminder_time": next_reminder_time.isoformat(), "interval": interval}) + save_data() + speak(f"I have set a {interval} reminder for {note}.") + +# Math tutoring function +def math_tutor(): + speak("What math problem would you like help with?") + user_input = voice_to_text() + + if user_input: + if "2 plus 2" in user_input.lower(): + speak("The answer to 2 plus 2 is 4.") + elif "quadratic formula" in user_input.lower(): + speak("The quadratic formula is negative b plus or minus the square root of b squared minus 4ac, all divided by 2a.") + else: + speak("I'm not sure of the answer. Would you like me to search online or provide a step-by-step explanation?") + else: + speak("I didn't understand your request. Could you please repeat?") + +# Language practice function +def language_practice(language="Spanish"): + supported_languages = ["spanish", "french"] + if language.lower() not in supported_languages: + speak(f"Sorry, I only support {', '.join(supported_languages)} at the moment.") + return + + speak(f"Let's practice {language}. Please say a sentence in {language}, and I'll correct it if needed.") + user_sentence = voice_to_text() + + if user_sentence: + if language.lower() == "spanish" and "estoy aprendiendo español" in user_sentence.lower(): + speak("Great! Your sentence is correct.") + elif language.lower() == "french" and "je parle français" in user_sentence.lower(): + speak("Great! Your sentence is correct.") + else: + speak(f"Sorry, I didn't understand that {language} sentence.") + else: + speak("Could you try that sentence again?") + +# Quiz function +def quiz(subject="math"): + question_bank = { + "math": [ + {"question": "What is 5 times 6?", "answer": "30"}, + {"question": "What is the square root of 64?", "answer": "8"}, + {"question": "What is 9 minus 3?", "answer": "6"} + ], + "science": [ + {"question": "What is the chemical symbol for water?", "answer": "H2O"}, + {"question": "What planet is known as the Red Planet?", "answer": "Mars"}, + {"question": "What is the atomic number of hydrogen?", "answer": "1"} + ] + } + + questions = random.sample(question_bank[subject], 2) # Select 2 random questions + + score = 0 + for q in questions: + speak(q["question"]) + user_answer = voice_to_text() + + if not user_answer: + speak("I didn't hear an answer. Could you try again?") + continue + + if q["answer"].lower() in user_answer.lower(): + speak("That's correct!") + score += 1 + else: + speak(f"Sorry, the correct answer is {q['answer']}.") + + speak(f"Your final score is {score} out of {len(questions)}.") + +# Background task to handle reminders asynchronously +def reminder_checker(): + while True: + current_time = datetime.datetime.now().isoformat() + for user, reminders in memory_data.items(): + for reminder in reminders: + if reminder.get("reminder_time") and reminder["reminder_time"] <= current_time: + speak(f"Reminder: {reminder['note']}") + reminders.remove(reminder) + save_data() + time.sleep(60) + +# Main function for the voice assistant +if __name__ == "__main__": + load_data() + user_name = get_user_name() + create_user_profile(user_name) + + # Start background thread for reminders + threading.Thread(target=reminder_checker, daemon=True).start() + + speak(f"Hello {user_name.capitalize()}, how can I assist you today?") + + while True: + command = voice_to_text() + + if command is None: + continue # Retry if the command was not understood + + if "exit" in command.lower() or "stop" in command.lower(): + speak("Goodbye! Stay curious and keep learning!") + save_data() + break + + # Trigger math tutoring + elif "math" in command.lower() and "help" in command.lower(): + math_tutor() + + # Trigger language practice + elif "practice" in command.lower() and "language" in command.lower(): + preferred_language = user_data[user_name]["preferred_language"] + speak(f"Would you like to practice {preferred_language}, or a different language?") + language_choice = voice_to_text() + if "different" in language_choice.lower(): + speak("Which language would you like to practice?") + preferred_language = voice_to_text() + user_data[user_name]["preferred_language"] = preferred_language + language_practice(preferred_language) + + # Trigger quiz + elif "quiz" in command.lower(): + speak("Which subject would you like a quiz on? Math or Science?") + subject_choice = voice_to_text() + if "math" in subject_choice.lower(): + quiz("math") + elif "science" in subject_choice.lower(): + quiz("science") + else: + speak("I only have quizzes for math and science at the moment.") + + # Add a reminder + elif "remind" in command.lower(): + speak("What should I remind you about?") + reminder_note = voice_to_text() + + speak("When should I remind you?") + reminder_time_input = voice_to_text() + reminder_time = dateparser.parse(reminder_time_input) + + if reminder_note and reminder_time: + add_reminder(user_name, reminder_note, reminder_time) + else: + speak("I couldn't set the reminder. Please try again.") + + # Search memory + elif "search" in command.lower() and "memory" in command.lower(): + speak("What would you like me to search for?") + keyword = voice_to_text() + search_memory(user_name, keyword) + + # List active reminders + elif "list" in command.lower() and "reminder" in command.lower(): + list_active_reminders(user_name) + + else: + speak("I'm sorry, I didn't understand that command.") diff --git a/Multi-Device Sync in a virtual assistant.py b/Python Snippets/Multi-Device Sync in a virtual assistant.py similarity index 100% rename from Multi-Device Sync in a virtual assistant.py rename to Python Snippets/Multi-Device Sync in a virtual assistant.py diff --git a/Task Scheduling & Time Management.py b/Python Snippets/Task Scheduling & Time Management.py similarity index 100% rename from Task Scheduling & Time Management.py rename to Python Snippets/Task Scheduling & Time Management.py diff --git a/Task_Scheduler b/Python Snippets/Task_Scheduler similarity index 100% rename from Task_Scheduler rename to Python Snippets/Task_Scheduler diff --git a/Task_Script b/Python Snippets/Task_Script similarity index 100% rename from Task_Script rename to Python Snippets/Task_Script diff --git a/TempConvereter.py b/Python Snippets/TempConvereter.py similarity index 100% rename from TempConvereter.py rename to Python Snippets/TempConvereter.py diff --git a/Time_capsule.py b/Python Snippets/Time_capsule.py similarity index 97% rename from Time_capsule.py rename to Python Snippets/Time_capsule.py index 5f02885..84f5ead 100644 --- a/Time_capsule.py +++ b/Python Snippets/Time_capsule.py @@ -1,189 +1,189 @@ -import datetime -import speech_recognition as sr -import pyttsx3 - -class TimeCapsule: - def __init__(self): - self.capsules = [] - self.password = "securepassword" # Set your password here - - def record_message(self, message, release_date): - """Record a new time capsule message.""" - if release_date < datetime.datetime.now().date(): - return "🚫 Oops! The release date must be in the future. Can you try again?" - - capsule = { - 'message': message, - 'release_date': release_date, - 'revealed': False - } - self.capsules.append(capsule) - return f"🌟 Your message has been safely stored! It will be revealed on {release_date.strftime('%Y-%m-%d')}." - - def check_capsules(self): - """Check and reveal any messages that should be visible now.""" - today = datetime.datetime.now().date() - revealed_messages = [] - remaining_capsules = [] - - for capsule in self.capsules: - if not capsule['revealed'] and today >= capsule['release_date']: - revealed_messages.append(capsule['message']) - capsule['revealed'] = True - else: - remaining_capsules.append(capsule) - - self.capsules = remaining_capsules # Clean up revealed capsules - return revealed_messages if revealed_messages else ["⏳ No messages are ready to be revealed just yet!"] - - def view_capsules(self): - """View the status of stored capsules.""" - if not self.capsules: - return ["📦 You haven't stored any messages in your time capsule yet."] - - capsule_list = [] - for i, capsule in enumerate(self.capsules, 1): - status = "✅ Revealed" if capsule['revealed'] else f"🔒 Hidden until {capsule['release_date'].strftime('%Y-%m-%d')}" - capsule_list.append(f"{i}. Status: {status}") - - return capsule_list - - def edit_capsule(self, index, new_message): - """Edit an existing capsule message with password verification.""" - if 0 <= index < len(self.capsules): - entered_password = input("🔒 Please enter your password to proceed: ") - if entered_password == self.password: - old_message = self.capsules[index]['message'] - self.capsules[index]['message'] = new_message - return f"✏️ Your message has been updated from '{old_message}' to '{new_message}'." - else: - return "🚫 Action cancelled. Incorrect password." - return "🚫 Error: Invalid capsule index! Please try again." - - def delete_capsule(self, index): - """Delete a capsule.""" - if 0 <= index < len(self.capsules): - removed_message = self.capsules.pop(index)['message'] - return f"🗑️ The message '{removed_message}' has been successfully deleted from your time capsule." - return "🚫 Error: Invalid capsule index! Can't delete that." - - def search_capsules(self, keyword): - """Search for messages containing the keyword.""" - found_messages = [capsule for capsule in self.capsules if keyword.lower() in capsule['message'].lower()] - if found_messages: - return [f"Message: '{capsule['message']}' | Release Date: {capsule['release_date'].strftime('%Y-%m-%d')}" for capsule in found_messages] - return ["🔍 No messages found containing that keyword."] - - def sort_capsules(self, by='date'): - """Sort capsules by release date or status.""" - if by == 'date': - self.capsules.sort(key=lambda x: x['release_date']) - return "🗂️ Capsules sorted by release date." - elif by == 'status': - self.capsules.sort(key=lambda x: x['revealed']) - return "🗂️ Capsules sorted by status." - return "🚫 Invalid sort option!" - -# Voice Interaction Setup -def speak(text): - """Convert text to speech.""" - engine = pyttsx3.init() - engine.say(text) - engine.runAndWait() - -def listen(): - """Listen for voice input and convert it to text.""" - recognizer = sr.Recognizer() - with sr.Microphone() as source: - print("🎤 Listening...") - audio = recognizer.listen(source) - try: - command = recognizer.recognize_google(audio) - print(f"You said: {command}") - return command.lower() - except sr.UnknownValueError: - print("👂 Sorry, I could not understand you.") - return "" - except sr.RequestError: - print("⚠️ Could not request results from Google Speech Recognition service.") - return "" - -# Example integration into a main assistant app -def main_assistant(): - time_capsule = TimeCapsule() - - speak("Hello! Welcome to your Time Capsule Assistant! Ready to store your precious memories?") - - while True: - speak("What would you like to do? You can say record, check, view, edit, delete, search, sort, help, or exit.") - command = listen() - - if "record" in command: - speak("Please tell me your message.") - message = listen() - speak("When would you like this message to be revealed? Please say the date in YYYY-MM-DD format.") - release_date_input = listen() - try: - release_date = datetime.datetime.strptime(release_date_input, '%Y-%m-%d').date() - response = time_capsule.record_message(message, release_date) - speak(response) - except ValueError: - speak("🚫 Invalid date format. Please try again.") - - elif "check" in command: - revealed_messages = time_capsule.check_capsules() - for msg in revealed_messages: - speak(f"Revealed message: {msg}") - - elif "view" in command: - capsules = time_capsule.view_capsules() - for item in capsules: - speak(item) - - elif "edit" in command: - speak("Which message would you like to edit? Please provide the index number.") - index_input = listen() - try: - index = int(index_input) - 1 - speak("Please tell me your new message.") - new_message = listen() - response = time_capsule.edit_capsule(index, new_message) - speak(response) - except (ValueError, IndexError): - speak("🚫 Invalid input. Please try again.") - - elif "delete" in command: - speak("Which message would you like to delete? Please provide the index number.") - index_input = listen() - try: - index = int(index_input) - 1 - response = time_capsule.delete_capsule(index) - speak(response) - except (ValueError, IndexError): - speak("🚫 Invalid input. Please try again.") - - elif "search" in command: - speak("Please say a keyword to search for.") - keyword = listen() - results = time_capsule.search_capsules(keyword) - for result in results: - speak(result) - - elif "sort" in command: - speak("Would you like to sort by date or status?") - sort_by = listen() - response = time_capsule.sort_capsules(by=sort_by) - speak(response) - - elif "help" in command: - speak("Here are the commands you can use: record, check, view, edit, delete, search, sort, or exit.") - - elif "exit" in command: - speak("Thank you for using the Time Capsule Assistant! Keep cherishing your memories! Goodbye!") - break - - else: - speak("Hmm, I didn't quite catch that. Can you please try again?") - -if __name__ == "__main__": - main_assistant() +import datetime +import speech_recognition as sr +import pyttsx3 + +class TimeCapsule: + def __init__(self): + self.capsules = [] + self.password = "securepassword" # Set your password here + + def record_message(self, message, release_date): + """Record a new time capsule message.""" + if release_date < datetime.datetime.now().date(): + return "🚫 Oops! The release date must be in the future. Can you try again?" + + capsule = { + 'message': message, + 'release_date': release_date, + 'revealed': False + } + self.capsules.append(capsule) + return f"🌟 Your message has been safely stored! It will be revealed on {release_date.strftime('%Y-%m-%d')}." + + def check_capsules(self): + """Check and reveal any messages that should be visible now.""" + today = datetime.datetime.now().date() + revealed_messages = [] + remaining_capsules = [] + + for capsule in self.capsules: + if not capsule['revealed'] and today >= capsule['release_date']: + revealed_messages.append(capsule['message']) + capsule['revealed'] = True + else: + remaining_capsules.append(capsule) + + self.capsules = remaining_capsules # Clean up revealed capsules + return revealed_messages if revealed_messages else ["⏳ No messages are ready to be revealed just yet!"] + + def view_capsules(self): + """View the status of stored capsules.""" + if not self.capsules: + return ["📦 You haven't stored any messages in your time capsule yet."] + + capsule_list = [] + for i, capsule in enumerate(self.capsules, 1): + status = "✅ Revealed" if capsule['revealed'] else f"🔒 Hidden until {capsule['release_date'].strftime('%Y-%m-%d')}" + capsule_list.append(f"{i}. Status: {status}") + + return capsule_list + + def edit_capsule(self, index, new_message): + """Edit an existing capsule message with password verification.""" + if 0 <= index < len(self.capsules): + entered_password = input("🔒 Please enter your password to proceed: ") + if entered_password == self.password: + old_message = self.capsules[index]['message'] + self.capsules[index]['message'] = new_message + return f"✏️ Your message has been updated from '{old_message}' to '{new_message}'." + else: + return "🚫 Action cancelled. Incorrect password." + return "🚫 Error: Invalid capsule index! Please try again." + + def delete_capsule(self, index): + """Delete a capsule.""" + if 0 <= index < len(self.capsules): + removed_message = self.capsules.pop(index)['message'] + return f"🗑️ The message '{removed_message}' has been successfully deleted from your time capsule." + return "🚫 Error: Invalid capsule index! Can't delete that." + + def search_capsules(self, keyword): + """Search for messages containing the keyword.""" + found_messages = [capsule for capsule in self.capsules if keyword.lower() in capsule['message'].lower()] + if found_messages: + return [f"Message: '{capsule['message']}' | Release Date: {capsule['release_date'].strftime('%Y-%m-%d')}" for capsule in found_messages] + return ["🔍 No messages found containing that keyword."] + + def sort_capsules(self, by='date'): + """Sort capsules by release date or status.""" + if by == 'date': + self.capsules.sort(key=lambda x: x['release_date']) + return "🗂️ Capsules sorted by release date." + elif by == 'status': + self.capsules.sort(key=lambda x: x['revealed']) + return "🗂️ Capsules sorted by status." + return "🚫 Invalid sort option!" + +# Voice Interaction Setup +def speak(text): + """Convert text to speech.""" + engine = pyttsx3.init() + engine.say(text) + engine.runAndWait() + +def listen(): + """Listen for voice input and convert it to text.""" + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("🎤 Listening...") + audio = recognizer.listen(source) + try: + command = recognizer.recognize_google(audio) + print(f"You said: {command}") + return command.lower() + except sr.UnknownValueError: + print("👂 Sorry, I could not understand you.") + return "" + except sr.RequestError: + print("⚠️ Could not request results from Google Speech Recognition service.") + return "" + +# Example integration into a main assistant app +def main_assistant(): + time_capsule = TimeCapsule() + + speak("Hello! Welcome to your Time Capsule Assistant! Ready to store your precious memories?") + + while True: + speak("What would you like to do? You can say record, check, view, edit, delete, search, sort, help, or exit.") + command = listen() + + if "record" in command: + speak("Please tell me your message.") + message = listen() + speak("When would you like this message to be revealed? Please say the date in YYYY-MM-DD format.") + release_date_input = listen() + try: + release_date = datetime.datetime.strptime(release_date_input, '%Y-%m-%d').date() + response = time_capsule.record_message(message, release_date) + speak(response) + except ValueError: + speak("🚫 Invalid date format. Please try again.") + + elif "check" in command: + revealed_messages = time_capsule.check_capsules() + for msg in revealed_messages: + speak(f"Revealed message: {msg}") + + elif "view" in command: + capsules = time_capsule.view_capsules() + for item in capsules: + speak(item) + + elif "edit" in command: + speak("Which message would you like to edit? Please provide the index number.") + index_input = listen() + try: + index = int(index_input) - 1 + speak("Please tell me your new message.") + new_message = listen() + response = time_capsule.edit_capsule(index, new_message) + speak(response) + except (ValueError, IndexError): + speak("🚫 Invalid input. Please try again.") + + elif "delete" in command: + speak("Which message would you like to delete? Please provide the index number.") + index_input = listen() + try: + index = int(index_input) - 1 + response = time_capsule.delete_capsule(index) + speak(response) + except (ValueError, IndexError): + speak("🚫 Invalid input. Please try again.") + + elif "search" in command: + speak("Please say a keyword to search for.") + keyword = listen() + results = time_capsule.search_capsules(keyword) + for result in results: + speak(result) + + elif "sort" in command: + speak("Would you like to sort by date or status?") + sort_by = listen() + response = time_capsule.sort_capsules(by=sort_by) + speak(response) + + elif "help" in command: + speak("Here are the commands you can use: record, check, view, edit, delete, search, sort, or exit.") + + elif "exit" in command: + speak("Thank you for using the Time Capsule Assistant! Keep cherishing your memories! Goodbye!") + break + + else: + speak("Hmm, I didn't quite catch that. Can you please try again?") + +if __name__ == "__main__": + main_assistant() diff --git a/Voice-Controlled Email and Messaging.py b/Python Snippets/Voice-Controlled Email and Messaging.py similarity index 100% rename from Voice-Controlled Email and Messaging.py rename to Python Snippets/Voice-Controlled Email and Messaging.py diff --git a/Voice-Controlled_Convenience.py b/Python Snippets/Voice-Controlled_Convenience.py similarity index 100% rename from Voice-Controlled_Convenience.py rename to Python Snippets/Voice-Controlled_Convenience.py diff --git a/app.py b/Python Snippets/app.py similarity index 100% rename from app.py rename to Python Snippets/app.py diff --git a/auto_update_requirements.py b/Python Snippets/auto_update_requirements.py similarity index 100% rename from auto_update_requirements.py rename to Python Snippets/auto_update_requirements.py diff --git a/book_recc.py b/Python Snippets/book_recc.py similarity index 100% rename from book_recc.py rename to Python Snippets/book_recc.py diff --git a/budget_planner.py b/Python Snippets/budget_planner.py similarity index 100% rename from budget_planner.py rename to Python Snippets/budget_planner.py diff --git a/cli_setup.py b/Python Snippets/cli_setup.py similarity index 100% rename from cli_setup.py rename to Python Snippets/cli_setup.py diff --git a/email_sender.py b/Python Snippets/email_sender.py similarity index 100% rename from email_sender.py rename to Python Snippets/email_sender.py diff --git a/enhanced_text_to_speech.py b/Python Snippets/enhanced_text_to_speech.py similarity index 100% rename from enhanced_text_to_speech.py rename to Python Snippets/enhanced_text_to_speech.py diff --git a/enhanced_weather-info.py b/Python Snippets/enhanced_weather-info.py similarity index 100% rename from enhanced_weather-info.py rename to Python Snippets/enhanced_weather-info.py diff --git a/enhanced_weather.py b/Python Snippets/enhanced_weather.py similarity index 100% rename from enhanced_weather.py rename to Python Snippets/enhanced_weather.py diff --git a/face_detection.py b/Python Snippets/face_detection.py similarity index 100% rename from face_detection.py rename to Python Snippets/face_detection.py diff --git a/face_detector.py b/Python Snippets/face_detector.py similarity index 100% rename from face_detector.py rename to Python Snippets/face_detector.py diff --git a/feedback.py b/Python Snippets/feedback.py similarity index 100% rename from feedback.py rename to Python Snippets/feedback.py diff --git a/gemini_info.py b/Python Snippets/gemini_info.py similarity index 96% rename from gemini_info.py rename to Python Snippets/gemini_info.py index 06600ad..8d47226 100644 --- a/gemini_info.py +++ b/Python Snippets/gemini_info.py @@ -1,74 +1,74 @@ -import google.generativeai as genai - -# Configure the API key -genai.configure(api_key="API Key") # Replace with your actual API key - -# Set up the model configuration -generation_config = { - "temperature": 0.9, - "top_p": 1, - "top_k": 1, - "max_output_tokens": 2048, -} - -safety_settings = [ - { - "category": "HARM_CATEGORY_HARASSMENT", - "threshold": "BLOCK_MEDIUM_AND_ABOVE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "threshold": "BLOCK_MEDIUM_AND_ABOVE" - }, - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "threshold": "BLOCK_MEDIUM_AND_ABOVE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "threshold": "BLOCK_MEDIUM_AND_ABOVE" - } -] - -# Initialize the model (ensure this method is correct) -model = genai.GenerativeModel( - model_name="gemini-pro", - generation_config=generation_config, - safety_settings=safety_settings -) - -def get_gemini_response(prompt): - try: - response = model.generate_content(prompt) # Verify this method - return response.text.strip() - except Exception as e: - return f"Error: {e}" - - -if __name__ == "__main__": - q = """ - I have a list of tools that can perform specific actions. Based on the user query, select the appropriate tool from the list and extract the necessary inputs. Please respond in the following JSON format: - - {{ - "tool": "", - "inputs": {{ - "input1": "", - "input2": "", - ... - }} - }} - - Here is the list of tools: - 1. "just_print": Requires general response if none of the following tools fits best. - 2. "set_reminder": Requires "time" (strictly in ISO format . that is,'date+T+time', including both date and time) and "message". - 3. "search_wikipedia": Requires "search_query". - 4. "get_weather": Requires "city_name". - 5. "tell_joke": Requires no inputs. - 6. "play_music": Requires "song_name". - 7. "open_website": Requires "website_name". - - If the tool requires no inputs, leave the "inputs" field empty. - - Query: "Heyy.... How is weather in hyderabad" - """ - print(get_gemini_response(q)) +import google.generativeai as genai + +# Configure the API key +genai.configure(api_key="API Key") # Replace with your actual API key + +# Set up the model configuration +generation_config = { + "temperature": 0.9, + "top_p": 1, + "top_k": 1, + "max_output_tokens": 2048, +} + +safety_settings = [ + { + "category": "HARM_CATEGORY_HARASSMENT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "threshold": "BLOCK_MEDIUM_AND_ABOVE" + } +] + +# Initialize the model (ensure this method is correct) +model = genai.GenerativeModel( + model_name="gemini-pro", + generation_config=generation_config, + safety_settings=safety_settings +) + +def get_gemini_response(prompt): + try: + response = model.generate_content(prompt) # Verify this method + return response.text.strip() + except Exception as e: + return f"Error: {e}" + + +if __name__ == "__main__": + q = """ + I have a list of tools that can perform specific actions. Based on the user query, select the appropriate tool from the list and extract the necessary inputs. Please respond in the following JSON format: + + {{ + "tool": "", + "inputs": {{ + "input1": "", + "input2": "", + ... + }} + }} + + Here is the list of tools: + 1. "just_print": Requires general response if none of the following tools fits best. + 2. "set_reminder": Requires "time" (strictly in ISO format . that is,'date+T+time', including both date and time) and "message". + 3. "search_wikipedia": Requires "search_query". + 4. "get_weather": Requires "city_name". + 5. "tell_joke": Requires no inputs. + 6. "play_music": Requires "song_name". + 7. "open_website": Requires "website_name". + + If the tool requires no inputs, leave the "inputs" field empty. + + Query: "Heyy.... How is weather in hyderabad" + """ + print(get_gemini_response(q)) diff --git a/gui_assistant.py b/Python Snippets/gui_assistant.py similarity index 100% rename from gui_assistant.py rename to Python Snippets/gui_assistant.py diff --git a/health.py b/Python Snippets/health.py similarity index 100% rename from health.py rename to Python Snippets/health.py diff --git a/health_assistant.py b/Python Snippets/health_assistant.py similarity index 100% rename from health_assistant.py rename to Python Snippets/health_assistant.py diff --git a/imdb.py b/Python Snippets/imdb.py similarity index 100% rename from imdb.py rename to Python Snippets/imdb.py diff --git a/language_practice_partner.py b/Python Snippets/language_practice_partner.py similarity index 97% rename from language_practice_partner.py rename to Python Snippets/language_practice_partner.py index 3a1ad34..1036a6e 100644 --- a/language_practice_partner.py +++ b/Python Snippets/language_practice_partner.py @@ -1,127 +1,127 @@ -import random -import requests -import speech_recognition as sr -from gtts import gTTS -import os -import time - -class LanguagePracticePartner: - def __init__(self): - self.vocab_quizzes = { - 'beginner': ['cat', 'dog', 'apple'], - 'intermediate': ['university', 'beautiful', 'important'], - 'advanced': ['comprehend', 'perspective', 'analyze'] - } - self.daily_challenges = [ - "Translate 'Good morning' to Spanish.", - "Use the word 'exciting' in a sentence.", - "Write a short paragraph about your day in the target language." - ] - self.progress = { - 'conversations': 0, - 'quizzes': 0, - 'pronunciation': 0, - 'challenges': 0 - } - self.translation_api_url = "https://api.mymemory.translated.net/get" - - def practice_conversation(self): - print("Let's practice a conversation! Type 'exit' to finish.") - while True: - user_input = input("You: ") - if user_input.lower() == 'exit': - break - if user_input.strip() == '': - print("Assistant: Please say something.") - else: - print(f"Assistant: Great job! You said: '{user_input}'. Keep practicing!") - self.progress['conversations'] += 1 - - def vocabulary_quiz(self): - level = input("Choose your proficiency level (beginner, intermediate, advanced): ").lower() - if level in self.vocab_quizzes: - words = self.vocab_quizzes[level] - random_word = random.choice(words) - answer = input(f"What is the translation of '{random_word}'? ") - correct_answer = self.get_translation(random_word) - if answer.lower() == correct_answer: - print("Correct! Well done.") - else: - print(f"Incorrect. The correct answer is: {correct_answer}.") - self.progress['quizzes'] += 1 - else: - print("Invalid level. Please try again.") - - def get_translation(self, word): - response = requests.get(self.translation_api_url, params={'q': word, 'langpair': 'en|es'}) - data = response.json() - return data['responseData']['translatedText'] - - def pronunciation_assistance(self): - print("Please say a word or phrase...") - recognizer = sr.Recognizer() - with sr.Microphone() as source: - audio = recognizer.listen(source) - try: - text = recognizer.recognize_google(audio) - print(f"You said: '{text}'.") - self.provide_pronunciation_feedback(text) - except sr.UnknownValueError: - print("Sorry, I could not understand the audio.") - except sr.RequestError: - print("Could not request results from the speech recognition service.") - self.progress['pronunciation'] += 1 - - def provide_pronunciation_feedback(self, text): - # This is a simple implementation; you can enhance this further. - # Here we could compare against a reference pronunciation. - print(f"Assistant: Great job saying '{text}'!") - - # Provide spoken feedback using text-to-speech - tts = gTTS(f"Great job saying {text}!", lang='en') - tts.save("feedback.mp3") - os.system("start feedback.mp3") - time.sleep(2) # Wait for the audio to finish playing - os.remove("feedback.mp3") # Clean up - - def daily_language_challenge(self): - challenge = random.choice(self.daily_challenges) - print(f"Today's challenge: {challenge}") - self.progress['challenges'] += 1 - - def display_progress(self): - print("\nYour Progress:") - for activity, count in self.progress.items(): - print(f"{activity.capitalize()}: {count} sessions completed.") - print("\nKeep up the good work!") - - def main_menu(self): - while True: - print("\n--- Language Practice Partner ---") - print("1. Practice Conversations") - print("2. Vocabulary Quiz") - print("3. Pronunciation Assistance") - print("4. Daily Language Challenge") - print("5. Display Progress") - print("6. Exit") - - choice = input("Choose an option: ") - if choice == '1': - self.practice_conversation() - elif choice == '2': - self.vocabulary_quiz() - elif choice == '3': - self.pronunciation_assistance() - elif choice == '4': - self.daily_language_challenge() - elif choice == '5': - self.display_progress() - elif choice == '6': - print("Goodbye! Keep practicing.") - break - else: - print("Invalid choice, please try again.") - -if __name__ == "__main__": - partner = LanguagePracticePartner() - partner.main_menu() +import random +import requests +import speech_recognition as sr +from gtts import gTTS +import os +import time + +class LanguagePracticePartner: + def __init__(self): + self.vocab_quizzes = { + 'beginner': ['cat', 'dog', 'apple'], + 'intermediate': ['university', 'beautiful', 'important'], + 'advanced': ['comprehend', 'perspective', 'analyze'] + } + self.daily_challenges = [ + "Translate 'Good morning' to Spanish.", + "Use the word 'exciting' in a sentence.", + "Write a short paragraph about your day in the target language." + ] + self.progress = { + 'conversations': 0, + 'quizzes': 0, + 'pronunciation': 0, + 'challenges': 0 + } + self.translation_api_url = "https://api.mymemory.translated.net/get" + + def practice_conversation(self): + print("Let's practice a conversation! Type 'exit' to finish.") + while True: + user_input = input("You: ") + if user_input.lower() == 'exit': + break + if user_input.strip() == '': + print("Assistant: Please say something.") + else: + print(f"Assistant: Great job! You said: '{user_input}'. Keep practicing!") + self.progress['conversations'] += 1 + + def vocabulary_quiz(self): + level = input("Choose your proficiency level (beginner, intermediate, advanced): ").lower() + if level in self.vocab_quizzes: + words = self.vocab_quizzes[level] + random_word = random.choice(words) + answer = input(f"What is the translation of '{random_word}'? ") + correct_answer = self.get_translation(random_word) + if answer.lower() == correct_answer: + print("Correct! Well done.") + else: + print(f"Incorrect. The correct answer is: {correct_answer}.") + self.progress['quizzes'] += 1 + else: + print("Invalid level. Please try again.") + + def get_translation(self, word): + response = requests.get(self.translation_api_url, params={'q': word, 'langpair': 'en|es'}) + data = response.json() + return data['responseData']['translatedText'] + + def pronunciation_assistance(self): + print("Please say a word or phrase...") + recognizer = sr.Recognizer() + with sr.Microphone() as source: + audio = recognizer.listen(source) + try: + text = recognizer.recognize_google(audio) + print(f"You said: '{text}'.") + self.provide_pronunciation_feedback(text) + except sr.UnknownValueError: + print("Sorry, I could not understand the audio.") + except sr.RequestError: + print("Could not request results from the speech recognition service.") + self.progress['pronunciation'] += 1 + + def provide_pronunciation_feedback(self, text): + # This is a simple implementation; you can enhance this further. + # Here we could compare against a reference pronunciation. + print(f"Assistant: Great job saying '{text}'!") + + # Provide spoken feedback using text-to-speech + tts = gTTS(f"Great job saying {text}!", lang='en') + tts.save("feedback.mp3") + os.system("start feedback.mp3") + time.sleep(2) # Wait for the audio to finish playing + os.remove("feedback.mp3") # Clean up + + def daily_language_challenge(self): + challenge = random.choice(self.daily_challenges) + print(f"Today's challenge: {challenge}") + self.progress['challenges'] += 1 + + def display_progress(self): + print("\nYour Progress:") + for activity, count in self.progress.items(): + print(f"{activity.capitalize()}: {count} sessions completed.") + print("\nKeep up the good work!") + + def main_menu(self): + while True: + print("\n--- Language Practice Partner ---") + print("1. Practice Conversations") + print("2. Vocabulary Quiz") + print("3. Pronunciation Assistance") + print("4. Daily Language Challenge") + print("5. Display Progress") + print("6. Exit") + + choice = input("Choose an option: ") + if choice == '1': + self.practice_conversation() + elif choice == '2': + self.vocabulary_quiz() + elif choice == '3': + self.pronunciation_assistance() + elif choice == '4': + self.daily_language_challenge() + elif choice == '5': + self.display_progress() + elif choice == '6': + print("Goodbye! Keep practicing.") + break + else: + print("Invalid choice, please try again.") + +if __name__ == "__main__": + partner = LanguagePracticePartner() + partner.main_menu() diff --git a/language_translator.py b/Python Snippets/language_translator.py similarity index 97% rename from language_translator.py rename to Python Snippets/language_translator.py index f23a36c..61c8e5a 100644 --- a/language_translator.py +++ b/Python Snippets/language_translator.py @@ -1,94 +1,94 @@ - -ion , translate and pyttsx3 libraries -#make sure there are no microphone or hardware issues - -import speech_recognition as sr -import pyttsx3 -from translate import Translator - -# Initialize the TTS engine -engine = pyttsx3.init() - -# Function to translate using translate-python -def translate_text(text, target_language): - try: - translator = Translator(to_lang=target_language) - translation = translator.translate(text) - return translation - except Exception as e: - return f"Sorry, the translation service encountered an error: {e}" - -# Function to speak the translated text -def speak(text): - engine.say(text) - engine.runAndWait() - - - - - - -# Function to capture voice commands and convert speech to text -def voice_to_text(): - recognizer = sr.Recognizer() - with sr.Microphone() as source: - print("Listening for your command...") - audio = recognizer.listen(source) - try: - command = recognizer.recognize_google(audio) - print(f"Captured voice command: {command}") - return command - except sr.UnknownValueError: - print("Sorry, I didn't understand that.") - return "Sorry, I didn't understand that." - except sr.RequestError: - print("Speech recognition service is unavailable.") - return "Sorry, the speech recognition service is not available." - -# Function to process translation commands via voice -def process_translation_command(command): - if "translate" in command.lower(): - try: - print(f"Command received for translation: {command}") - - # Parse the command to extract the text and target language - if "'" not in command or "to " not in command: - speak("Please provide a valid command, for example: Translate 'Hello' to French.") - return - - text_to_translate = command.split("'")[1] - target_language = command.split("to ")[1].strip().lower() - - # Provide feedback on extracted text and language - print(f"Text to translate: {text_to_translate}") - print(f"Target language: {target_language}") - - # Perform the translation - translated_text = translate_text(text_to_translate, target_language) - print(f"Translated Text: {translated_text}") - speak(f"The translation is: {translated_text}") - - except IndexError: - speak("Sorry, I couldn't process the command format. Please try again.") - except Exception as e: - speak(f"Sorry, I couldn't process that translation: {e}") - print(f"Error: {e}") - else: - speak("Please give a translation command that includes 'Translate'.") - -# Main function for the voice assistant -if __name__ == "__main__": - speak("Hello! I'm your translation assistant. How can I help you?") - - while True: - command = voice_to_text() - print(f"Command received: {command}") - - if "exit" in command.lower() or "stop" in command.lower(): - speak("Goodbye!") - break - elif command.lower() == "sorry, i didn't understand that.": - continue # If speech recognition fails, re-listen for a command - else: - process_translation_command(command) - + +ion , translate and pyttsx3 libraries +#make sure there are no microphone or hardware issues + +import speech_recognition as sr +import pyttsx3 +from translate import Translator + +# Initialize the TTS engine +engine = pyttsx3.init() + +# Function to translate using translate-python +def translate_text(text, target_language): + try: + translator = Translator(to_lang=target_language) + translation = translator.translate(text) + return translation + except Exception as e: + return f"Sorry, the translation service encountered an error: {e}" + +# Function to speak the translated text +def speak(text): + engine.say(text) + engine.runAndWait() + + + + + + +# Function to capture voice commands and convert speech to text +def voice_to_text(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening for your command...") + audio = recognizer.listen(source) + try: + command = recognizer.recognize_google(audio) + print(f"Captured voice command: {command}") + return command + except sr.UnknownValueError: + print("Sorry, I didn't understand that.") + return "Sorry, I didn't understand that." + except sr.RequestError: + print("Speech recognition service is unavailable.") + return "Sorry, the speech recognition service is not available." + +# Function to process translation commands via voice +def process_translation_command(command): + if "translate" in command.lower(): + try: + print(f"Command received for translation: {command}") + + # Parse the command to extract the text and target language + if "'" not in command or "to " not in command: + speak("Please provide a valid command, for example: Translate 'Hello' to French.") + return + + text_to_translate = command.split("'")[1] + target_language = command.split("to ")[1].strip().lower() + + # Provide feedback on extracted text and language + print(f"Text to translate: {text_to_translate}") + print(f"Target language: {target_language}") + + # Perform the translation + translated_text = translate_text(text_to_translate, target_language) + print(f"Translated Text: {translated_text}") + speak(f"The translation is: {translated_text}") + + except IndexError: + speak("Sorry, I couldn't process the command format. Please try again.") + except Exception as e: + speak(f"Sorry, I couldn't process that translation: {e}") + print(f"Error: {e}") + else: + speak("Please give a translation command that includes 'Translate'.") + +# Main function for the voice assistant +if __name__ == "__main__": + speak("Hello! I'm your translation assistant. How can I help you?") + + while True: + command = voice_to_text() + print(f"Command received: {command}") + + if "exit" in command.lower() or "stop" in command.lower(): + speak("Goodbye!") + break + elif command.lower() == "sorry, i didn't understand that.": + continue # If speech recognition fails, re-listen for a command + else: + process_translation_command(command) + diff --git a/linearEquations.py b/Python Snippets/linearEquations.py similarity index 100% rename from linearEquations.py rename to Python Snippets/linearEquations.py diff --git a/main_assistant.py b/Python Snippets/main_assistant.py similarity index 100% rename from main_assistant.py rename to Python Snippets/main_assistant.py diff --git a/mainutilities.py b/Python Snippets/mainutilities.py similarity index 100% rename from mainutilities.py rename to Python Snippets/mainutilities.py diff --git a/memory_game.py b/Python Snippets/memory_game.py similarity index 100% rename from memory_game.py rename to Python Snippets/memory_game.py diff --git a/memorygame.py b/Python Snippets/memorygame.py similarity index 100% rename from memorygame.py rename to Python Snippets/memorygame.py diff --git a/mood_tracker.py b/Python Snippets/mood_tracker.py similarity index 100% rename from mood_tracker.py rename to Python Snippets/mood_tracker.py diff --git a/new_weather_info.py b/Python Snippets/new_weather_info.py similarity index 100% rename from new_weather_info.py rename to Python Snippets/new_weather_info.py diff --git a/news_info.py b/Python Snippets/news_info.py similarity index 96% rename from news_info.py rename to Python Snippets/news_info.py index 405f2c3..1955a9c 100644 --- a/news_info.py +++ b/Python Snippets/news_info.py @@ -1,72 +1,72 @@ -import requests -import json -import os - -def get_news(api_key, category='general', page=1, page_size=5, query=None): - try: - base_url = 'https://newsapi.org/v2/top-headlines' if not query else 'https://newsapi.org/v2/everything' - params = { - 'apiKey': api_key, - 'category': category, - 'page': page, - 'pagesize': page_size - } - - if query: - params.pop('category') - params['q'] = query - - response = requests.get(base_url, params=params) - response.raise_for_status() - - data = response.json() - articles = data.get('articles', []) - - return articles - - except requests.exceptions.RequestException as e: - print(f"An error occurred: {e}") - return [] - except json.JSONDecodeError as e: - print(f"Failed to parse JSON: {e}") - return [] - -def save_articles(articles, filename='articles.json'): - with open(filename, 'w') as f: - json.dump(articles, f, indent=4) - print(f"Articles saved to {filename}.") - -def main(): - API_KEY = os.environ.get('NEWS_API_KEY') - if not API_KEY: - print("Please set the NEWS_API_KEY environment variable.") - return - - category = input("Enter news category (such as: general, business, technology, sports, entertainment, politics, health and science): ") - while True: - try: - num_articles = int(input("How many articles would you like to see? ")) - if num_articles <= 0: - print("Please enter a positive integer.") - else: - break - except ValueError: - print("Invalid input. Please enter a positive integer.") - - query = input("Enter a keyword to search for articles (or press Enter to skip): ") - if query == "": - query = None - - articles = get_news(API_KEY, category=category, page_size=num_articles, query=query) - - if articles: - save_articles(articles) - for article in articles: - print(f"Title: {article['title']}") - print(f"Author: {article.get('author', 'N/A')}") - print(f"Published at: {article['publishedAt']}") - print(f"Description: {article.get('description', 'N/A')}\n") - -if __name__ == "__main__": - main() +import requests +import json +import os + +def get_news(api_key, category='general', page=1, page_size=5, query=None): + try: + base_url = 'https://newsapi.org/v2/top-headlines' if not query else 'https://newsapi.org/v2/everything' + params = { + 'apiKey': api_key, + 'category': category, + 'page': page, + 'pagesize': page_size + } + + if query: + params.pop('category') + params['q'] = query + + response = requests.get(base_url, params=params) + response.raise_for_status() + + data = response.json() + articles = data.get('articles', []) + + return articles + + except requests.exceptions.RequestException as e: + print(f"An error occurred: {e}") + return [] + except json.JSONDecodeError as e: + print(f"Failed to parse JSON: {e}") + return [] + +def save_articles(articles, filename='articles.json'): + with open(filename, 'w') as f: + json.dump(articles, f, indent=4) + print(f"Articles saved to {filename}.") + +def main(): + API_KEY = os.environ.get('NEWS_API_KEY') + if not API_KEY: + print("Please set the NEWS_API_KEY environment variable.") + return + + category = input("Enter news category (such as: general, business, technology, sports, entertainment, politics, health and science): ") + while True: + try: + num_articles = int(input("How many articles would you like to see? ")) + if num_articles <= 0: + print("Please enter a positive integer.") + else: + break + except ValueError: + print("Invalid input. Please enter a positive integer.") + + query = input("Enter a keyword to search for articles (or press Enter to skip): ") + if query == "": + query = None + + articles = get_news(API_KEY, category=category, page_size=num_articles, query=query) + + if articles: + save_articles(articles) + for article in articles: + print(f"Title: {article['title']}") + print(f"Author: {article.get('author', 'N/A')}") + print(f"Published at: {article['publishedAt']}") + print(f"Description: {article.get('description', 'N/A')}\n") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/open_app.py b/Python Snippets/open_app.py similarity index 95% rename from open_app.py rename to Python Snippets/open_app.py index d04d0b4..22afdc2 100644 --- a/open_app.py +++ b/Python Snippets/open_app.py @@ -1,6 +1,6 @@ -import os - -def open_application(command): - if 'notepad' in command: - os.system('notepad') - # Add more applications as needed +import os + +def open_application(command): + if 'notepad' in command: + os.system('notepad') + # Add more applications as needed diff --git a/open_files.py b/Python Snippets/open_files.py similarity index 100% rename from open_files.py rename to Python Snippets/open_files.py diff --git a/phone_numbers.py b/Python Snippets/phone_numbers.py similarity index 100% rename from phone_numbers.py rename to Python Snippets/phone_numbers.py diff --git a/qrcodes.py b/Python Snippets/qrcodes.py similarity index 100% rename from qrcodes.py rename to Python Snippets/qrcodes.py diff --git a/quote_of_the_day.py b/Python Snippets/quote_of_the_day.py similarity index 100% rename from quote_of_the_day.py rename to Python Snippets/quote_of_the_day.py diff --git a/real_time_shopping_list.py b/Python Snippets/real_time_shopping_list.py similarity index 100% rename from real_time_shopping_list.py rename to Python Snippets/real_time_shopping_list.py diff --git a/reminderr.py b/Python Snippets/reminderr.py similarity index 100% rename from reminderr.py rename to Python Snippets/reminderr.py diff --git a/sentiment_analysis.py b/Python Snippets/sentiment_analysis.py similarity index 100% rename from sentiment_analysis.py rename to Python Snippets/sentiment_analysis.py diff --git a/stocks.py b/Python Snippets/stocks.py similarity index 100% rename from stocks.py rename to Python Snippets/stocks.py diff --git a/sun_scan.py b/Python Snippets/sun_scan.py similarity index 100% rename from sun_scan.py rename to Python Snippets/sun_scan.py diff --git a/sustainabilty_tracker.py b/Python Snippets/sustainabilty_tracker.py similarity index 97% rename from sustainabilty_tracker.py rename to Python Snippets/sustainabilty_tracker.py index f3ba42a..b1a6d06 100644 --- a/sustainabilty_tracker.py +++ b/Python Snippets/sustainabilty_tracker.py @@ -1,166 +1,166 @@ -import speech_recognition as sr -import pyttsx3 -import json -from datetime import datetime, timedelta -import matplotlib.pyplot as plt -import random - -# Initialize the TTS engine -engine = pyttsx3.init() -engine.setProperty('rate', 150) # Slower speaking rate - -# Function to speak text -def speak(text): - engine.say(text) - engine.runAndWait() - -# Persistent data storage -def save_data(): - with open("sustainability_data.json", "w") as file: - json.dump(sustainability_data, file) - -def load_data(): - global sustainability_data - try: - with open("sustainability_data.json", "r") as file: - sustainability_data = json.load(file) - except FileNotFoundError: - print("No previous data found.") - sustainability_data = {} - -# Load data at the start of the program -load_data() - -# Example user-specific sustainability data structure -def initialize_user_data(user): - if user not in sustainability_data: - sustainability_data[user] = { - "transportation": [], - "energy_usage": [], - "water_usage": [], - "waste": [] - } - -# Function to capture voice input -def voice_to_text(): - recognizer = sr.Recognizer() - with sr.Microphone() as source: - print("Listening for your command...") - try: - audio = recognizer.listen(source, timeout=10) # Timeout after 10 seconds - command = recognizer.recognize_google(audio) - print(f"Captured voice command: {command}") - return command - except sr.UnknownValueError: - speak("I didn't catch that. Could you please repeat?") - return None - except sr.RequestError: - speak("The speech recognition service is unavailable at the moment.") - return None - -# Function to log sustainability data with timestamp -def log_sustainability_data(user, category, value): - timestamp = datetime.now().isoformat() - sustainability_data[user][category].append({"date": timestamp, "value": value}) - save_data() - -# Function to provide sustainability recommendations -def provide_recommendations(user): - user_data = sustainability_data[user] - - if sum([item["value"] for item in user_data["transportation"]]) > 100: - speak("You have logged over 100 kilometers in transportation. Consider using public transport or carpooling to reduce your carbon footprint.") - - if sum([item["value"] for item in user_data["energy_usage"]]) > 500: - speak("Your energy consumption seems high. Try turning off appliances when not in use to save energy.") - - if sum([item["value"] for item in user_data["water_usage"]]) > 300: - speak("You have logged high water usage. Consider taking shorter showers or fixing leaks to save water.") - - if sum([item["value"] for item in user_data["waste"]]) > 50: - speak("You have logged a lot of waste. Consider recycling or composting to reduce your waste footprint.") - -# Function to calculate carbon footprint for transportation (mocked API integration) -def get_carbon_footprint_km(km): - # Mock API response for the carbon footprint - carbon_per_km = 0.21 # Average kg CO2 per km for a car - return round(km * carbon_per_km, 2) - -# Function to plot sustainability data -def plot_sustainability_data(user): - categories = ['transportation', 'energy_usage', 'water_usage', 'waste'] - values = [sum([item["value"] for item in sustainability_data[user][cat]]) for cat in categories] - - plt.bar(categories, values) - plt.ylabel('Units') - plt.title(f'{user.capitalize()}\'s Sustainability Tracker') - plt.show() - -# Function to provide historical data summary -def get_weekly_summary(user): - categories = ['transportation', 'energy_usage', 'water_usage', 'waste'] - one_week_ago = datetime.now() - timedelta(days=7) - weekly_summary = {cat: 0 for cat in categories} - - for category in categories: - for entry in sustainability_data[user][category]: - entry_date = datetime.fromisoformat(entry['date']) - if entry_date > one_week_ago: - weekly_summary[category] += entry["value"] - - return weekly_summary - -# Function to confirm user's entry -def confirm_entry(category, value): - speak(f"Did you mean to log {value} units to {category}? Please say yes or no.") - confirmation = voice_to_text() - if confirmation and "yes" in confirmation.lower(): - return True - return False - -# Main function for the voice assistant -if __name__ == "__main__": - user = "default_user" # Placeholder for user identification - initialize_user_data(user) # Initialize user data if not present - speak("Hello! I'm your sustainability assistant. How can I help you today?") - - while True: - command = voice_to_text() - - if command is None: - continue # Retry if the command was not understood - - print(f"Command received: {command}") - - # Exit the assistant if the user says "exit" or "stop" - if "exit" in command.lower() or "stop" in command.lower(): - speak("Goodbye! Stay sustainable!") - break - - # Example: Log transportation - elif "log" in command.lower() and "transportation" in command.lower(): - try: - # Extract the number of kilometers from the command - km = int(command.split()[-1]) # Assuming the last word is a number - if confirm_entry("transportation", km): - carbon_footprint = get_carbon_footprint_km(km) - log_sustainability_data(user, "transportation", km) - speak(f"Logged {km} kilometers. This corresponds to a carbon footprint of {carbon_footprint} kilograms of CO2.") - except ValueError: - speak("I couldn't understand the number of kilometers. Please say it again.") - - # Example: Show weekly summary - elif "weekly summary" in command.lower(): - weekly_data = get_weekly_summary(user) - speak(f"Here is your weekly summary: Transportation {weekly_data['transportation']} kilometers, Energy usage {weekly_data['energy_usage']} units, Water usage {weekly_data['water_usage']} liters, Waste {weekly_data['waste']} kilograms.") - - # Example: Show data visualization - elif "show graph" in command.lower(): - plot_sustainability_data(user) - - # Provide recommendations - elif "recommend" in command.lower(): - provide_recommendations(user) - - else: - speak("I didn't catch that. Please say a valid command, like 'log transportation' or 'show graph'.") +import speech_recognition as sr +import pyttsx3 +import json +from datetime import datetime, timedelta +import matplotlib.pyplot as plt +import random + +# Initialize the TTS engine +engine = pyttsx3.init() +engine.setProperty('rate', 150) # Slower speaking rate + +# Function to speak text +def speak(text): + engine.say(text) + engine.runAndWait() + +# Persistent data storage +def save_data(): + with open("sustainability_data.json", "w") as file: + json.dump(sustainability_data, file) + +def load_data(): + global sustainability_data + try: + with open("sustainability_data.json", "r") as file: + sustainability_data = json.load(file) + except FileNotFoundError: + print("No previous data found.") + sustainability_data = {} + +# Load data at the start of the program +load_data() + +# Example user-specific sustainability data structure +def initialize_user_data(user): + if user not in sustainability_data: + sustainability_data[user] = { + "transportation": [], + "energy_usage": [], + "water_usage": [], + "waste": [] + } + +# Function to capture voice input +def voice_to_text(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening for your command...") + try: + audio = recognizer.listen(source, timeout=10) # Timeout after 10 seconds + command = recognizer.recognize_google(audio) + print(f"Captured voice command: {command}") + return command + except sr.UnknownValueError: + speak("I didn't catch that. Could you please repeat?") + return None + except sr.RequestError: + speak("The speech recognition service is unavailable at the moment.") + return None + +# Function to log sustainability data with timestamp +def log_sustainability_data(user, category, value): + timestamp = datetime.now().isoformat() + sustainability_data[user][category].append({"date": timestamp, "value": value}) + save_data() + +# Function to provide sustainability recommendations +def provide_recommendations(user): + user_data = sustainability_data[user] + + if sum([item["value"] for item in user_data["transportation"]]) > 100: + speak("You have logged over 100 kilometers in transportation. Consider using public transport or carpooling to reduce your carbon footprint.") + + if sum([item["value"] for item in user_data["energy_usage"]]) > 500: + speak("Your energy consumption seems high. Try turning off appliances when not in use to save energy.") + + if sum([item["value"] for item in user_data["water_usage"]]) > 300: + speak("You have logged high water usage. Consider taking shorter showers or fixing leaks to save water.") + + if sum([item["value"] for item in user_data["waste"]]) > 50: + speak("You have logged a lot of waste. Consider recycling or composting to reduce your waste footprint.") + +# Function to calculate carbon footprint for transportation (mocked API integration) +def get_carbon_footprint_km(km): + # Mock API response for the carbon footprint + carbon_per_km = 0.21 # Average kg CO2 per km for a car + return round(km * carbon_per_km, 2) + +# Function to plot sustainability data +def plot_sustainability_data(user): + categories = ['transportation', 'energy_usage', 'water_usage', 'waste'] + values = [sum([item["value"] for item in sustainability_data[user][cat]]) for cat in categories] + + plt.bar(categories, values) + plt.ylabel('Units') + plt.title(f'{user.capitalize()}\'s Sustainability Tracker') + plt.show() + +# Function to provide historical data summary +def get_weekly_summary(user): + categories = ['transportation', 'energy_usage', 'water_usage', 'waste'] + one_week_ago = datetime.now() - timedelta(days=7) + weekly_summary = {cat: 0 for cat in categories} + + for category in categories: + for entry in sustainability_data[user][category]: + entry_date = datetime.fromisoformat(entry['date']) + if entry_date > one_week_ago: + weekly_summary[category] += entry["value"] + + return weekly_summary + +# Function to confirm user's entry +def confirm_entry(category, value): + speak(f"Did you mean to log {value} units to {category}? Please say yes or no.") + confirmation = voice_to_text() + if confirmation and "yes" in confirmation.lower(): + return True + return False + +# Main function for the voice assistant +if __name__ == "__main__": + user = "default_user" # Placeholder for user identification + initialize_user_data(user) # Initialize user data if not present + speak("Hello! I'm your sustainability assistant. How can I help you today?") + + while True: + command = voice_to_text() + + if command is None: + continue # Retry if the command was not understood + + print(f"Command received: {command}") + + # Exit the assistant if the user says "exit" or "stop" + if "exit" in command.lower() or "stop" in command.lower(): + speak("Goodbye! Stay sustainable!") + break + + # Example: Log transportation + elif "log" in command.lower() and "transportation" in command.lower(): + try: + # Extract the number of kilometers from the command + km = int(command.split()[-1]) # Assuming the last word is a number + if confirm_entry("transportation", km): + carbon_footprint = get_carbon_footprint_km(km) + log_sustainability_data(user, "transportation", km) + speak(f"Logged {km} kilometers. This corresponds to a carbon footprint of {carbon_footprint} kilograms of CO2.") + except ValueError: + speak("I couldn't understand the number of kilometers. Please say it again.") + + # Example: Show weekly summary + elif "weekly summary" in command.lower(): + weekly_data = get_weekly_summary(user) + speak(f"Here is your weekly summary: Transportation {weekly_data['transportation']} kilometers, Energy usage {weekly_data['energy_usage']} units, Water usage {weekly_data['water_usage']} liters, Waste {weekly_data['waste']} kilograms.") + + # Example: Show data visualization + elif "show graph" in command.lower(): + plot_sustainability_data(user) + + # Provide recommendations + elif "recommend" in command.lower(): + provide_recommendations(user) + + else: + speak("I didn't catch that. Please say a valid command, like 'log transportation' or 'show graph'.") diff --git a/sync.py b/Python Snippets/sync.py similarity index 100% rename from sync.py rename to Python Snippets/sync.py diff --git a/task_automation.py b/Python Snippets/task_automation.py similarity index 100% rename from task_automation.py rename to Python Snippets/task_automation.py diff --git a/telegram_bot.py b/Python Snippets/telegram_bot.py similarity index 100% rename from telegram_bot.py rename to Python Snippets/telegram_bot.py diff --git a/test_email.py b/Python Snippets/test_email.py similarity index 100% rename from test_email.py rename to Python Snippets/test_email.py diff --git a/test_weather.py b/Python Snippets/test_weather.py similarity index 100% rename from test_weather.py rename to Python Snippets/test_weather.py diff --git a/text_summarization.py b/Python Snippets/text_summarization.py similarity index 96% rename from text_summarization.py rename to Python Snippets/text_summarization.py index 52e2338..1fff8aa 100644 --- a/text_summarization.py +++ b/Python Snippets/text_summarization.py @@ -1,89 +1,89 @@ -import os -import json -from transformers import pipeline - -# Set up the summarization model -summarizer = pipeline("summarization") - -# File to store texts for summarization -TEXT_FILE = "texts.json" -texts_list = [] - -def load_texts(): - global texts_list - if os.path.exists(TEXT_FILE): - with open(TEXT_FILE, "r") as file: - texts_list = json.load(file) - print("Loaded texts for summarization.") - else: - print("No texts to load.") - -def save_texts_to_file(): - with open(TEXT_FILE, "w") as file: - json.dump(texts_list, file, indent=4) - -def show_texts(): - if texts_list: - print("Texts to Summarize:") - for idx, text in enumerate(texts_list, 1): - print(f"{idx}. {text}") - else: - print("No texts available for summarization!") - -def submit_text(): - text = input("Enter the text to summarize (type 'exit' to stop): ") - if text.lower() != 'exit': - texts_list.append(text) - print("Text added for summarization!") - save_texts_to_file() - -def summarize_texts(): - show_texts() - if texts_list: - try: - choice = int(input("Enter the number of the text you want to summarize: ")) - 1 - if 0 <= choice < len(texts_list): - text_to_summarize = texts_list[choice] - summary = summarizer(text_to_summarize, max_length=130, min_length=30, do_sample=False) - print(f"Summary: {summary[0]['summary_text']}") - else: - print("Invalid choice, no text summarized.") - except ValueError: - print("Please enter a valid number.") - -def clear_texts(): - if texts_list: - texts_list.clear() - print("All texts have been cleared.") - save_texts_to_file() - else: - print("No texts to clear.") - -def feedback_system(): - load_texts() - while True: - print("\nText Summarization System") - print("1. Submit Text") - print("2. Show Texts") - print("3. Summarize Text") - print("4. Clear All Texts") - print("5. Exit") - - choice = input("Please select an option (1-5): ") - - if choice == "1": - submit_text() - elif choice == "2": - show_texts() - elif choice == "3": - summarize_texts() - elif choice == "4": - clear_texts() - elif choice == "5": - print("Exiting text summarization system.") - break - else: - print("Invalid choice, please try again.") - -if __name__ == "__main__": - feedback_system() +import os +import json +from transformers import pipeline + +# Set up the summarization model +summarizer = pipeline("summarization") + +# File to store texts for summarization +TEXT_FILE = "texts.json" +texts_list = [] + +def load_texts(): + global texts_list + if os.path.exists(TEXT_FILE): + with open(TEXT_FILE, "r") as file: + texts_list = json.load(file) + print("Loaded texts for summarization.") + else: + print("No texts to load.") + +def save_texts_to_file(): + with open(TEXT_FILE, "w") as file: + json.dump(texts_list, file, indent=4) + +def show_texts(): + if texts_list: + print("Texts to Summarize:") + for idx, text in enumerate(texts_list, 1): + print(f"{idx}. {text}") + else: + print("No texts available for summarization!") + +def submit_text(): + text = input("Enter the text to summarize (type 'exit' to stop): ") + if text.lower() != 'exit': + texts_list.append(text) + print("Text added for summarization!") + save_texts_to_file() + +def summarize_texts(): + show_texts() + if texts_list: + try: + choice = int(input("Enter the number of the text you want to summarize: ")) - 1 + if 0 <= choice < len(texts_list): + text_to_summarize = texts_list[choice] + summary = summarizer(text_to_summarize, max_length=130, min_length=30, do_sample=False) + print(f"Summary: {summary[0]['summary_text']}") + else: + print("Invalid choice, no text summarized.") + except ValueError: + print("Please enter a valid number.") + +def clear_texts(): + if texts_list: + texts_list.clear() + print("All texts have been cleared.") + save_texts_to_file() + else: + print("No texts to clear.") + +def feedback_system(): + load_texts() + while True: + print("\nText Summarization System") + print("1. Submit Text") + print("2. Show Texts") + print("3. Summarize Text") + print("4. Clear All Texts") + print("5. Exit") + + choice = input("Please select an option (1-5): ") + + if choice == "1": + submit_text() + elif choice == "2": + show_texts() + elif choice == "3": + summarize_texts() + elif choice == "4": + clear_texts() + elif choice == "5": + print("Exiting text summarization system.") + break + else: + print("Invalid choice, please try again.") + +if __name__ == "__main__": + feedback_system() diff --git a/text_to_speech.py b/Python Snippets/text_to_speech.py similarity index 96% rename from text_to_speech.py rename to Python Snippets/text_to_speech.py index b198a3d..7313e19 100644 --- a/text_to_speech.py +++ b/Python Snippets/text_to_speech.py @@ -1,26 +1,26 @@ -from gtts import gTTS -import os -import platform - -# Taking input from the user -text = input("Enter the text you want to convert to speech: ") - -# Specifying the language for conversion -language = 'en' - -# Creating the gTTS object and converting the text -speech = gTTS(text=text, lang=language, slow=False) - -# Saving the speech to an mp3 file -filename = "user_output.mp3" -speech.save(filename) - -# Detect the OS and play the mp3 file accordingly -os_type = platform.system() - -if os_type == "Windows": - os.system(f"start {filename}") -elif os_type == "Darwin": # macOS - os.system(f"afplay {filename}") -else: # Linux - os.system(f"mpg321 {filename}") # mpg321 should be installed on Linux +from gtts import gTTS +import os +import platform + +# Taking input from the user +text = input("Enter the text you want to convert to speech: ") + +# Specifying the language for conversion +language = 'en' + +# Creating the gTTS object and converting the text +speech = gTTS(text=text, lang=language, slow=False) + +# Saving the speech to an mp3 file +filename = "user_output.mp3" +speech.save(filename) + +# Detect the OS and play the mp3 file accordingly +os_type = platform.system() + +if os_type == "Windows": + os.system(f"start {filename}") +elif os_type == "Darwin": # macOS + os.system(f"afplay {filename}") +else: # Linux + os.system(f"mpg321 {filename}") # mpg321 should be installed on Linux diff --git a/time_module.py b/Python Snippets/time_module.py similarity index 100% rename from time_module.py rename to Python Snippets/time_module.py diff --git a/trivia_night.py b/Python Snippets/trivia_night.py similarity index 100% rename from trivia_night.py rename to Python Snippets/trivia_night.py diff --git a/unit_convertor.py b/Python Snippets/unit_convertor.py similarity index 97% rename from unit_convertor.py rename to Python Snippets/unit_convertor.py index bc919e2..676f348 100644 --- a/unit_convertor.py +++ b/Python Snippets/unit_convertor.py @@ -1,92 +1,92 @@ -#install speech_recognition , pint and pyttsx3 libraries -#make sure there are no microphone or hardware issues - -import speech_recognition as sr -import pyttsx3 -import pint - -# Initialize the unit registry from pint and TTS engine -unit_registry = pint.UnitRegistry() -engine = pyttsx3.init() - -# Function to speak output using TTS -def speak(text): - engine.say(text) - engine.runAndWait() - -# Function to convert units using pint with better error handling -def convert_units(value, from_unit, to_unit): - try: - # Create a quantity from the value and original unit - quantity = value * unit_registry(from_unit) - # Convert the quantity to the target unit - converted_quantity = quantity.to(to_unit) - return converted_quantity - except pint.errors.DimensionalityError: - return f"Incompatible units: cannot convert {from_unit} to {to_unit}." - except Exception as e: - return f"Error: {e}" - -# Function to capture voice commands and convert speech to text -def voice_to_text(): - recognizer = sr.Recognizer() - with sr.Microphone() as source: - print("Listening for your command...") - recognizer.adjust_for_ambient_noise(source) # Adjust for ambient noise - audio = recognizer.listen(source) - try: - # Convert speech to text using Google Web Speech API - return recognizer.recognize_google(audio) - except sr.UnknownValueError: - return "Sorry, I didn't understand that." - except sr.RequestError: - return "Sorry, the speech recognition service is not available." - -# Function to process voice commands related to unit conversion -def process_conversion_command(command): - # Simple string-based parsing for unit conversion commands - # Example command: "Convert 10 meters to feet" - try: - # Normalize the command string - command = command.lower().replace("convert", "").replace("to", "").strip() - words = command.split() - - # Check if the command contains the necessary components - if len(words) < 3: - speak("Sorry, the command format should be: convert [value] [from_unit] to [to_unit].") - return - - # Parse the value and units from the command - try: - value = float(words[0]) - except ValueError: - speak("The value to convert must be a number.") - return - - from_unit = words[1] - to_unit = words[2] - - # Perform the unit conversion - result = convert_units(value, from_unit, to_unit) - if isinstance(result, str): - speak(result) # Handle any error messages from the conversion - else: - speak(f"{value} {from_unit} is equal to {result:.2f} {to_unit}") - except Exception as e: - speak(f"An error occurred while processing your command: {e}") - -# Main function to trigger the voice assistant -if __name__ == "__main__": - speak("Hello! I'm your assistant. How can I help you with unit conversions?") - - while True: - command = voice_to_text() - print(f"Command received: {command}") - - if "exit" in command.lower() or "stop" in command.lower(): - speak("Goodbye!") - break - elif "convert" in command.lower(): - process_conversion_command(command) - else: - speak("Please give a command to convert units or say 'exit' to stop.") +#install speech_recognition , pint and pyttsx3 libraries +#make sure there are no microphone or hardware issues + +import speech_recognition as sr +import pyttsx3 +import pint + +# Initialize the unit registry from pint and TTS engine +unit_registry = pint.UnitRegistry() +engine = pyttsx3.init() + +# Function to speak output using TTS +def speak(text): + engine.say(text) + engine.runAndWait() + +# Function to convert units using pint with better error handling +def convert_units(value, from_unit, to_unit): + try: + # Create a quantity from the value and original unit + quantity = value * unit_registry(from_unit) + # Convert the quantity to the target unit + converted_quantity = quantity.to(to_unit) + return converted_quantity + except pint.errors.DimensionalityError: + return f"Incompatible units: cannot convert {from_unit} to {to_unit}." + except Exception as e: + return f"Error: {e}" + +# Function to capture voice commands and convert speech to text +def voice_to_text(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening for your command...") + recognizer.adjust_for_ambient_noise(source) # Adjust for ambient noise + audio = recognizer.listen(source) + try: + # Convert speech to text using Google Web Speech API + return recognizer.recognize_google(audio) + except sr.UnknownValueError: + return "Sorry, I didn't understand that." + except sr.RequestError: + return "Sorry, the speech recognition service is not available." + +# Function to process voice commands related to unit conversion +def process_conversion_command(command): + # Simple string-based parsing for unit conversion commands + # Example command: "Convert 10 meters to feet" + try: + # Normalize the command string + command = command.lower().replace("convert", "").replace("to", "").strip() + words = command.split() + + # Check if the command contains the necessary components + if len(words) < 3: + speak("Sorry, the command format should be: convert [value] [from_unit] to [to_unit].") + return + + # Parse the value and units from the command + try: + value = float(words[0]) + except ValueError: + speak("The value to convert must be a number.") + return + + from_unit = words[1] + to_unit = words[2] + + # Perform the unit conversion + result = convert_units(value, from_unit, to_unit) + if isinstance(result, str): + speak(result) # Handle any error messages from the conversion + else: + speak(f"{value} {from_unit} is equal to {result:.2f} {to_unit}") + except Exception as e: + speak(f"An error occurred while processing your command: {e}") + +# Main function to trigger the voice assistant +if __name__ == "__main__": + speak("Hello! I'm your assistant. How can I help you with unit conversions?") + + while True: + command = voice_to_text() + print(f"Command received: {command}") + + if "exit" in command.lower() or "stop" in command.lower(): + speak("Goodbye!") + break + elif "convert" in command.lower(): + process_conversion_command(command) + else: + speak("Please give a command to convert units or say 'exit' to stop.") diff --git a/update_req.py b/Python Snippets/update_req.py similarity index 100% rename from update_req.py rename to Python Snippets/update_req.py diff --git a/updated-voice_recognition.py b/Python Snippets/updated-voice_recognition.py similarity index 100% rename from updated-voice_recognition.py rename to Python Snippets/updated-voice_recognition.py diff --git a/updatednews_info.py b/Python Snippets/updatednews_info.py similarity index 100% rename from updatednews_info.py rename to Python Snippets/updatednews_info.py diff --git a/virtual_assistant.py b/Python Snippets/virtual_assistant.py similarity index 100% rename from virtual_assistant.py rename to Python Snippets/virtual_assistant.py diff --git a/voice.py b/Python Snippets/voice.py similarity index 97% rename from voice.py rename to Python Snippets/voice.py index 890d28a..1c2b352 100644 --- a/voice.py +++ b/Python Snippets/voice.py @@ -1,84 +1,84 @@ -import pyttsx3 -import speech_recognition as sr -import wikipedia -import webbrowser -import os - -# init pyttsx -engine = pyttsx3.init("sapi5") -voices = engine.getProperty("voices") - -engine.setProperty('voice', voices[1].id) # 1 for female and 0 for male voice - - -def speak(audio): - engine.say(audio) - engine.runAndWait() - - -def take_command(): - r = sr.Recognizer() - with sr.Microphone() as source: - print("Listening...") - r.pause_threshold = 1 - audio = r.listen(source) - try: - print("Recognizing...") - query = r.recognize_google(audio, language='en-in') - print("User said:" + query + "\n") - except Exception as e: - print(e) - speak("I didnt understand") - return "None" - return query - - -if __name__ == '__main__': - - speak("hazelo assistance activated ") - speak("How can i help you") - while True: - query = take_command().lower() - if 'wikipedia' in query: - speak("Searching Wikipedia ...") - query = query.replace("wikipedia", '') - results = wikipedia.summary(query, sentences=2) - speak("According to wikipedia") - speak(results) - elif 'who are you' in query: - speak("I am hazelo developed by Shaista Attar") - elif 'open youtube' in query: - speak("opening youtube") - webbrowser.open("youtube.com") - elif 'open google' in query: - speak("opening google") - webbrowser.open("google.com") - elif 'open github' in query: - speak("opening github") - webbrowser.open("github.com") - elif 'open stackoverflow' in query: - speak("opening stackoverflow") - webbrowser.open("stackoverflow.com") - elif 'open spotify' in query: - speak("opening spotify") - webbrowser.open("spotify.com") - elif 'open whatsapp' in query: - speak("opening whatsapp") - webbrowser.open("whatsapp.com") - elif 'open prepinsta' in query: - speak("opening prepinsta") - webbrowser.open("prepinstaprime.com") - elif 'tell me a joke' in query: - speak("collecting a good joke for yea. here is a good joke") - print("Hear about the new restaurant called Karma?Theres no menu: You get what you deserve.") - elif 'local disk d' in query: - speak("opening local disk D") - webbrowser.open("D://") - elif 'local disk c' in query: - speak("opening local disk C") - webbrowser.open("C://") - elif 'local disk e' in query: - speak("opening local disk E") - webbrowser.open("E://") - elif 'sleep' in query: +import pyttsx3 +import speech_recognition as sr +import wikipedia +import webbrowser +import os + +# init pyttsx +engine = pyttsx3.init("sapi5") +voices = engine.getProperty("voices") + +engine.setProperty('voice', voices[1].id) # 1 for female and 0 for male voice + + +def speak(audio): + engine.say(audio) + engine.runAndWait() + + +def take_command(): + r = sr.Recognizer() + with sr.Microphone() as source: + print("Listening...") + r.pause_threshold = 1 + audio = r.listen(source) + try: + print("Recognizing...") + query = r.recognize_google(audio, language='en-in') + print("User said:" + query + "\n") + except Exception as e: + print(e) + speak("I didnt understand") + return "None" + return query + + +if __name__ == '__main__': + + speak("hazelo assistance activated ") + speak("How can i help you") + while True: + query = take_command().lower() + if 'wikipedia' in query: + speak("Searching Wikipedia ...") + query = query.replace("wikipedia", '') + results = wikipedia.summary(query, sentences=2) + speak("According to wikipedia") + speak(results) + elif 'who are you' in query: + speak("I am hazelo developed by Shaista Attar") + elif 'open youtube' in query: + speak("opening youtube") + webbrowser.open("youtube.com") + elif 'open google' in query: + speak("opening google") + webbrowser.open("google.com") + elif 'open github' in query: + speak("opening github") + webbrowser.open("github.com") + elif 'open stackoverflow' in query: + speak("opening stackoverflow") + webbrowser.open("stackoverflow.com") + elif 'open spotify' in query: + speak("opening spotify") + webbrowser.open("spotify.com") + elif 'open whatsapp' in query: + speak("opening whatsapp") + webbrowser.open("whatsapp.com") + elif 'open prepinsta' in query: + speak("opening prepinsta") + webbrowser.open("prepinstaprime.com") + elif 'tell me a joke' in query: + speak("collecting a good joke for yea. here is a good joke") + print("Hear about the new restaurant called Karma?Theres no menu: You get what you deserve.") + elif 'local disk d' in query: + speak("opening local disk D") + webbrowser.open("D://") + elif 'local disk c' in query: + speak("opening local disk C") + webbrowser.open("C://") + elif 'local disk e' in query: + speak("opening local disk E") + webbrowser.open("E://") + elif 'sleep' in query: exit(0) \ No newline at end of file diff --git a/voice_recognition.py b/Python Snippets/voice_recognition.py similarity index 96% rename from voice_recognition.py rename to Python Snippets/voice_recognition.py index a191e92..8769c5d 100644 --- a/voice_recognition.py +++ b/Python Snippets/voice_recognition.py @@ -1,43 +1,43 @@ -import speech_recognition as sr - -def recognize_speech(timeout=2, phrase_time_limit=5): - recognizer = sr.Recognizer() - - # Try to open microphone and listen for speech - try: - with sr.Microphone() as source: - print("Adjusting for ambient noise, please wait...") - recognizer.adjust_for_ambient_noise(source) - - print("Listening...") - audio = recognizer.listen(source, timeout=timeout, phrase_time_limit=phrase_time_limit) - - except sr.WaitTimeoutError: - print("Listening timed out while waiting for phrase to start.") - return "None" - except Exception as e: - print(f"Error accessing the microphone: {e}") - return "None" - - # Try recognizing speech using Google Speech Recognition - try: - print("Recognizing...") - query = recognizer.recognize_google(audio, language='en-in') - print(f"User said: {query}\n") - - except sr.UnknownValueError: - print("Could not understand audio") - return "None" - except sr.RequestError: - print("Could not request results; check your network connection") - return "None" - except Exception as e: - print(f"Error: {e}") - return "None" - - return query.lower() - -# Test the function -if __name__ == "__main__": - recognize_speech() - +import speech_recognition as sr + +def recognize_speech(timeout=2, phrase_time_limit=5): + recognizer = sr.Recognizer() + + # Try to open microphone and listen for speech + try: + with sr.Microphone() as source: + print("Adjusting for ambient noise, please wait...") + recognizer.adjust_for_ambient_noise(source) + + print("Listening...") + audio = recognizer.listen(source, timeout=timeout, phrase_time_limit=phrase_time_limit) + + except sr.WaitTimeoutError: + print("Listening timed out while waiting for phrase to start.") + return "None" + except Exception as e: + print(f"Error accessing the microphone: {e}") + return "None" + + # Try recognizing speech using Google Speech Recognition + try: + print("Recognizing...") + query = recognizer.recognize_google(audio, language='en-in') + print(f"User said: {query}\n") + + except sr.UnknownValueError: + print("Could not understand audio") + return "None" + except sr.RequestError: + print("Could not request results; check your network connection") + return "None" + except Exception as e: + print(f"Error: {e}") + return "None" + + return query.lower() + +# Test the function +if __name__ == "__main__": + recognize_speech() + diff --git a/weather_info.py b/Python Snippets/weather_info.py similarity index 97% rename from weather_info.py rename to Python Snippets/weather_info.py index d31442e..fb16b41 100644 --- a/weather_info.py +++ b/Python Snippets/weather_info.py @@ -1,60 +1,60 @@ -import os -import requests - -API_KEY = os.getenv('OPENWEATHER_API_KEY') or input("Please enter your OpenWeather API key: ").strip() -BASE_URL = "http://api.openweathermap.org/data/2.5/weather?" - -def validate_units(units): - """Validate and return appropriate units for the weather data.""" - valid_units = {"metric": "°C", "imperial": "°F", "kelvin": "K"} - return valid_units.get(units.lower(), "K") # Default to Kelvin if units are invalid - -def get_weather(city_name, units="metric"): - """Fetch weather data for the provided city and display it in the selected units.""" - city_name = city_name.strip() - if not city_name: - return "Please provide a valid city name." - - if not API_KEY: - return "API key not found. Please set the 'OPENWEATHER_API_KEY' environment variable." - - # Prepare the API URL - units = units or "kelvin" - unit_symbol = validate_units(units) - url = f"{BASE_URL}q={city_name}&appid={API_KEY}&units={units}" - - try: - # Make the request to the OpenWeather API - response = requests.get(url) - response.raise_for_status() # Raise exception for HTTP errors - data = response.json() - - if data["cod"] != 200: - error_messages = { - "404": "City not found.", - "401": "Invalid API key.", - "429": "Too many requests. Please try again later." - } - return error_messages.get(str(data["cod"]), f"Error: {data.get('message', 'Unknown error occurred')}") - - # Extract weather details - temp = data["main"]["temp"] - description = data["weather"][0]["description"] - - return f"Temperature: {temp:.2f}{unit_symbol}\nDescription: {description.capitalize()}" - - except requests.exceptions.RequestException as e: - return f"Network error: Unable to retrieve data. Details: {e}" - - except ValueError: - return "Error: Unable to parse response data. Please try again." - -if __name__ == "__main__": - while True: - city = input("Enter city name (or type 'exit' to quit): ").strip() - if city.lower() == 'exit': - print("Goodbye!") - break - - unit = input("Units (metric/imperial/kelvin, leave empty for Kelvin): ").strip() or None - print(get_weather(city, unit)) +import os +import requests + +API_KEY = os.getenv('OPENWEATHER_API_KEY') or input("Please enter your OpenWeather API key: ").strip() +BASE_URL = "http://api.openweathermap.org/data/2.5/weather?" + +def validate_units(units): + """Validate and return appropriate units for the weather data.""" + valid_units = {"metric": "°C", "imperial": "°F", "kelvin": "K"} + return valid_units.get(units.lower(), "K") # Default to Kelvin if units are invalid + +def get_weather(city_name, units="metric"): + """Fetch weather data for the provided city and display it in the selected units.""" + city_name = city_name.strip() + if not city_name: + return "Please provide a valid city name." + + if not API_KEY: + return "API key not found. Please set the 'OPENWEATHER_API_KEY' environment variable." + + # Prepare the API URL + units = units or "kelvin" + unit_symbol = validate_units(units) + url = f"{BASE_URL}q={city_name}&appid={API_KEY}&units={units}" + + try: + # Make the request to the OpenWeather API + response = requests.get(url) + response.raise_for_status() # Raise exception for HTTP errors + data = response.json() + + if data["cod"] != 200: + error_messages = { + "404": "City not found.", + "401": "Invalid API key.", + "429": "Too many requests. Please try again later." + } + return error_messages.get(str(data["cod"]), f"Error: {data.get('message', 'Unknown error occurred')}") + + # Extract weather details + temp = data["main"]["temp"] + description = data["weather"][0]["description"] + + return f"Temperature: {temp:.2f}{unit_symbol}\nDescription: {description.capitalize()}" + + except requests.exceptions.RequestException as e: + return f"Network error: Unable to retrieve data. Details: {e}" + + except ValueError: + return "Error: Unable to parse response data. Please try again." + +if __name__ == "__main__": + while True: + city = input("Enter city name (or type 'exit' to quit): ").strip() + if city.lower() == 'exit': + print("Goodbye!") + break + + unit = input("Units (metric/imperial/kelvin, leave empty for Kelvin): ").strip() or None + print(get_weather(city, unit)) diff --git a/website_data.py b/Python Snippets/website_data.py similarity index 96% rename from website_data.py rename to Python Snippets/website_data.py index 66b8365..4cb1e7b 100644 --- a/website_data.py +++ b/Python Snippets/website_data.py @@ -1,14 +1,14 @@ - - -# website_data.py -# Dictionary to store website names and their URLs - - -WEBSITES = { - "LinkedIn": "https://www.linkedin.com", - "google": "https://www.google.com", - "youtube": "https://www.youtube.com", - "Surynshsk": "https://suryanshsk.netlify.app/", - "Instagram": "https://www.instagram.com/suryanshsk/", - # Add more websites as needed -} + + +# website_data.py +# Dictionary to store website names and their URLs + + +WEBSITES = { + "LinkedIn": "https://www.linkedin.com", + "google": "https://www.google.com", + "youtube": "https://www.youtube.com", + "Surynshsk": "https://suryanshsk.netlify.app/", + "Instagram": "https://www.instagram.com/suryanshsk/", + # Add more websites as needed +} diff --git a/websocket_server.py b/Python Snippets/websocket_server.py similarity index 96% rename from websocket_server.py rename to Python Snippets/websocket_server.py index 3442fa1..4f3cdf9 100644 --- a/websocket_server.py +++ b/Python Snippets/websocket_server.py @@ -1,15 +1,15 @@ -import asyncio -import websockets - -async def handle_client(websocket, path): - async for message in websocket: - print(f"Received message: {message}") - # Example: echo the message back to the client - await websocket.send(f"Server received: {message}") - -async def main(): - async with websockets.serve(handle_client, "localhost", 8765): - await asyncio.Future() # run forever - -if __name__ == "__main__": - asyncio.run(main()) +import asyncio +import websockets + +async def handle_client(websocket, path): + async for message in websocket: + print(f"Received message: {message}") + # Example: echo the message back to the client + await websocket.send(f"Server received: {message}") + +async def main(): + async with websockets.serve(handle_client, "localhost", 8765): + await asyncio.Future() # run forever + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/wikipedia_info.py b/Python Snippets/wikipedia_info.py similarity index 97% rename from wikipedia_info.py rename to Python Snippets/wikipedia_info.py index 4895c67..0872478 100644 --- a/wikipedia_info.py +++ b/Python Snippets/wikipedia_info.py @@ -1,81 +1,81 @@ -import wikipedia -import logging -import time - - -logging.basicConfig(filename='wikipedia_search.log', level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s') - - -search_history = [] - -def search_wikipedia(query, num_sentences=1, lang='en'): - - wikipedia.set_lang(lang) - try: - - summary = wikipedia.summary(query, sentences=num_sentences) - search_history.append({'query': query, 'language': lang, 'summary': summary}) - - logging.info(f"Successfully searched for '{query}' in language '{lang}' with {num_sentences} sentence(s) on {time.strftime('%Y-%m-%d at %H:%M:%S')}") - print(f"\n--- Search Result ---\nQuery: {query}\nLanguage: {lang}\nSummary: {summary}\n") - - except wikipedia.exceptions.DisambiguationError as e: - - logging.warning(f"Disambiguation error for: {query}, options: {e.options}") - print(f"\nDisambiguationError: Your search term '{query}' is ambiguous. Possible options are:\n") - for option in e.options: - print(f"- {option}") - - except wikipedia.exceptions.PageError: - - logging.error(f"PageError: No page found for: {query}") - print(f"\nPageError: No page found for '{query}'. Please try again with a different term.\n") - - except Exception as e: - - logging.error(f"Error: {e}") - print(f"\nError: {e}\n") - - -def show_search_history(): - - if search_history: - print("\n--- Search History ---\n") - for index, entry in enumerate(search_history, 1): - print(f"{index}. Query: {entry['query']} | Language: {entry['language']}\nSummary: {entry['summary']}\n") - else: - print("\nNo search history is found.\n") - -def main(): - while True: - print("\nMenu:\n1. Search Wikipedia\n2. View Search History\n3. Exit") - choice = input("Enter your choice (1-3): ") - - if choice == '1': - query = input("\nEnter the search query: ") - num_sentences = input("How many sentences do you want in the summary? (default 1): ") - lang = input("Enter language code (default 'en'): ") - - - num_sentences = int(num_sentences) if num_sentences else 1 - lang = lang if lang else 'en' - - - search_wikipedia(query, num_sentences, lang) - - elif choice == '2': - - show_search_history() - - elif choice == '3': - print("\nExiting the program.") - break - - else: - print("\nInvalid choice.\n") - - -if __name__ == "__main__": - main() - +import wikipedia +import logging +import time + + +logging.basicConfig(filename='wikipedia_search.log', level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s') + + +search_history = [] + +def search_wikipedia(query, num_sentences=1, lang='en'): + + wikipedia.set_lang(lang) + try: + + summary = wikipedia.summary(query, sentences=num_sentences) + search_history.append({'query': query, 'language': lang, 'summary': summary}) + + logging.info(f"Successfully searched for '{query}' in language '{lang}' with {num_sentences} sentence(s) on {time.strftime('%Y-%m-%d at %H:%M:%S')}") + print(f"\n--- Search Result ---\nQuery: {query}\nLanguage: {lang}\nSummary: {summary}\n") + + except wikipedia.exceptions.DisambiguationError as e: + + logging.warning(f"Disambiguation error for: {query}, options: {e.options}") + print(f"\nDisambiguationError: Your search term '{query}' is ambiguous. Possible options are:\n") + for option in e.options: + print(f"- {option}") + + except wikipedia.exceptions.PageError: + + logging.error(f"PageError: No page found for: {query}") + print(f"\nPageError: No page found for '{query}'. Please try again with a different term.\n") + + except Exception as e: + + logging.error(f"Error: {e}") + print(f"\nError: {e}\n") + + +def show_search_history(): + + if search_history: + print("\n--- Search History ---\n") + for index, entry in enumerate(search_history, 1): + print(f"{index}. Query: {entry['query']} | Language: {entry['language']}\nSummary: {entry['summary']}\n") + else: + print("\nNo search history is found.\n") + +def main(): + while True: + print("\nMenu:\n1. Search Wikipedia\n2. View Search History\n3. Exit") + choice = input("Enter your choice (1-3): ") + + if choice == '1': + query = input("\nEnter the search query: ") + num_sentences = input("How many sentences do you want in the summary? (default 1): ") + lang = input("Enter language code (default 'en'): ") + + + num_sentences = int(num_sentences) if num_sentences else 1 + lang = lang if lang else 'en' + + + search_wikipedia(query, num_sentences, lang) + + elif choice == '2': + + show_search_history() + + elif choice == '3': + print("\nExiting the program.") + break + + else: + print("\nInvalid choice.\n") + + +if __name__ == "__main__": + main() + From 2d3ef4cefd2543d979a2d19bceaa09315935a026 Mon Sep 17 00:00:00 2001 From: AnanteshG Date: Fri, 18 Oct 2024 22:37:55 +0530 Subject: [PATCH 06/73] added dijkstra --- Dijkstra/main.py | 75 +++++++++++++++++++++++++++++++++++++++++++ Dijkstra/test_main.py | 41 +++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 Dijkstra/main.py create mode 100644 Dijkstra/test_main.py diff --git a/Dijkstra/main.py b/Dijkstra/main.py new file mode 100644 index 0000000..a78e80f --- /dev/null +++ b/Dijkstra/main.py @@ -0,0 +1,75 @@ +import networkx as nx +import matplotlib.pyplot as plt + +# function to create graph +def graph_create(): + G = nx.Graph() + nodes_num = int(input("Enter the number of nodes: ")) + for i in range(nodes_num): + nodes_name = input(f"Enter the name of node {i+1} : ") + + edges = int(input("Enter the number of edges: ")) + for i in range(edges): + edge_name = input(f"Enter edge {i+1} : (format: source, destination, value): ") + source, destination, weight = edge_name.split() + G.add_edge(source, destination, weight = int(weight)) + + return G + +# dijkstra algorithm implementation +def dijkstra(graph, start): + distances = {node: float("inf") for node in graph.nodes} #dictionary to store shortest distances + distances[start] = 0 + paths = {node: [] for node in graph.nodes} #dictionary to store shortest paths + visited = set() + + while len(visited) < len(graph.nodes): #loop till all nodes are visited + not_visited = {node: distances[node] for node in graph.nodes if node not in visited} #dictionary contains distances of unvisited nodes + min_node = min(not_visited, key=not_visited.get) # to get node with minimum distance from start node + visited.add(min_node) + + for neighbor, weight in graph[min_node].items(): + # If the distance to the neighbor through the current node is less than the previously known shortest distance to the neighbor + if distances[min_node] + weight["weight"] < distances[neighbor]: + # Update the shortest distance and path to the neighbor + distances[neighbor] = distances[min_node] + weight["weight"] + paths[neighbor] = paths[min_node] + [min_node] + + # After visiting all nodes, finalize the shortest paths by adding the destination node to each path + + paths = {node: path + [node] for node, path in paths.items() if path} + + return distances, paths + +def visualise_dijkstra(graph, start): + if start not in graph.nodes: + print("Start node not found in graph") + return + + distances, paths = dijkstra(graph, start) + pos = nx.spring_layout(graph) + plt.get_current_fig_manager().window.title("Dijkstra Algorithm Visualiser") + nx.draw(graph, pos, with_labels = True, node_color = "lightblue", edgecolors="black", node_size = 500, font_size = 15, font_weight = "bold") + labels = nx.get_edge_attributes(graph, "weight") + nx.draw_networkx_edge_labels(graph, pos, edge_labels = labels, font_size = 8) + + plt.title("Dijkstra's Algorithm Visualisation") + print("Shortest distances from the start node:") + for node, distance in distances.items(): + print(f"{node}: {distance}") + + print("Shortest paths from the start node:") + for node, path in paths.items(): + print(f"{node}: {' -> '.join(path)}") + + plt.show() + +if __name__ == "__main__": + user_graph = graph_create() + start_node = input("Enter the start node: ") + visualise_dijkstra(user_graph, start_node) + + + + + \ No newline at end of file diff --git a/Dijkstra/test_main.py b/Dijkstra/test_main.py new file mode 100644 index 0000000..1a7ed36 --- /dev/null +++ b/Dijkstra/test_main.py @@ -0,0 +1,41 @@ +import unittest +from main import dijkstra + +class DijkstraTestCase(unittest.TestCase): + def test_shortest_path(self): + graph = { + 'A': {'B': {'weight': 5}, 'C': {'weight': 3}}, + 'B': {'A': {'weight': 5}, 'C': {'weight': 2}, 'D': {'weight': 1}}, + 'C': {'A': {'weight': 3}, 'B': {'weight': 2}, 'D': {'weight': 4}, 'E': {'weight': 6}}, + 'D': {'B': {'weight': 1}, 'C': {'weight': 4}, 'E': {'weight': 2}}, + 'E': {'C': {'weight': 6}, 'D': {'weight': 2}} + } + start_node = 'A' + expected_distances = {'A': 0, 'B': 3, 'C': 3, 'D': 4, 'E': 6} + expected_paths = {'A': ['A'], 'B': ['A', 'B'], 'C': ['A', 'C'], 'D': ['A', 'B', 'D'], 'E': ['A', 'B', 'D', 'E']} + + distances, paths = dijkstra(graph, start_node) + + self.assertEqual(distances, expected_distances) + self.assertEqual(paths, expected_paths) + + def test_disconnected_graph(self): + graph = { + 'A': {'B': {'weight': 5}, 'C': {'weight': 3}}, + 'B': {'A': {'weight': 5}, 'C': {'weight': 2}, 'D': {'weight': 1}}, + 'C': {'A': {'weight': 3}, 'B': {'weight': 2}, 'D': {'weight': 4}, 'E': {'weight': 6}}, + 'D': {'B': {'weight': 1}, 'C': {'weight': 4}, 'E': {'weight': 2}}, + 'E': {'C': {'weight': 6}, 'D': {'weight': 2}}, + 'F': {} # Disconnected node + } + start_node = 'A' + expected_distances = {'A': 0, 'B': 3, 'C': 3, 'D': 4, 'E': 6} + expected_paths = {'A': ['A'], 'B': ['A', 'B'], 'C': ['A', 'C'], 'D': ['A', 'B', 'D'], 'E': ['A', 'B', 'D', 'E']} + + distances, paths = dijkstra(graph, start_node) + + self.assertEqual(distances, expected_distances) + self.assertEqual(paths, expected_paths) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From a134265f5a9b8067d5176a84ae5c56831b55ec8b Mon Sep 17 00:00:00 2001 From: Aasthajiit <22103060@mail.jiit.ac.in> Date: Sat, 19 Oct 2024 00:49:40 +0530 Subject: [PATCH 07/73] Create movie.py --- movie.py | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 movie.py diff --git a/movie.py b/movie.py new file mode 100644 index 0000000..261aff6 --- /dev/null +++ b/movie.py @@ -0,0 +1,250 @@ +import requests +import json +import os +from colorama import init, Fore, Back, Style + +init(autoreset=True) + +DATA_FILE = 'profile.json' # Used to store user profiles + +def load_profile(): + if os.path.exists(DATA_FILE): + with open(DATA_FILE, 'r') as file: + return json.load(file) + return {} + +def save_profile(profiles): + with open(DATA_FILE, 'w') as file: + json.dump(profiles, file) + +def book_recommendation(preferred_genre): + api_url = f"https://www.googleapis.com/books/v1/volumes?q=subject:{preferred_genre}&maxResults=5" + response = requests.get(api_url) + + if response.status_code == 200: + books = response.json().get('items', []) + recommendation = [] + + for book in books: + title = book['volumeInfo'].get('title', 'No title available') + authors = book['volumeInfo'].get('authors', ['unknown author']) + cover_image = book['volumeInfo'].get('imageLinks', {}).get('thumbnail', 'no image available') + recommendation.append({ + 'title': title, + 'authors': authors, + 'cover_image': cover_image + }) + + return recommendation + else: + print(Fore.RED + "Error in fetching the data") + return [] + +def display_recommendation(books): + if not books: + print(Fore.YELLOW + "No recommendations found.") + return + + print(Fore.CYAN + "\nBook Recommendations: ") + for i, book in enumerate(books, start=1): + print(Fore.GREEN + f"{i}. Title: {book['title']}") + print(Fore.MAGENTA + f" Authors: {', '.join(book['authors'])}") + print(Fore.LIGHTYELLOW_EX + f" Cover Image: {book['cover_image']}\n") + +def add_to_reading_list(book, user_data): + user_data['reading_list'].append(book) + save_profile(user_profiles) + print(Fore.GREEN + f"{book['title']} has been added to your reading list.") + +def rate_review_book(title, user_data): + rating = input(Fore.YELLOW + "Enter your rating (1-5): ") + review = input(Fore.YELLOW + "Enter your review: ") + user_data['reviews'][title] = {'rating': rating, 'review': review} + save_profile(user_profiles) + print(Fore.GREEN + f"Thank you for your review of {title}") + +def view_reading_list(user_data): + if not user_data['reading_list']: + print(Fore.YELLOW + "Your reading list is empty.") + return + + print(Fore.CYAN + "\nYour Reading List: ") + for i, book in enumerate(user_data['reading_list'], start=1): + print(Fore.GREEN + f"{i}. Title: {book['title']}") + print(Fore.MAGENTA + f" Authors: {', '.join(book['authors'])}") + +def view_reviews(user_data): + if not user_data['reviews']: + print(Fore.YELLOW + "You have no reviews yet.") + return + + print(Fore.CYAN + "\nYour Reviews: ") + for title, review_data in user_data['reviews'].items(): + print(Fore.LIGHTYELLOW_EX + f"- {title}: {review_data['rating']} stars, Review: {review_data['review']}") + +def register_user(username): + if username in user_profiles: + print(Fore.RED + "Username already exists. Please choose a different username.") + return None + + user_profiles[username] = { + 'preferred_genre': '', + 'reading_list': [], + 'reviews': {} + } + save_profile(user_profiles) + print(Fore.GREEN + f"User {username} registered successfully!") + return user_profiles[username] + +def login_user(username): + if username in user_profiles: + print(Fore.GREEN + f"Welcome back, {username}!") + return user_profiles[username] + else: + print(Fore.RED + "Username does not exist, please register yourself.") + return None + +def suggested_reading(): + print(Style.BRIGHT + Fore.CYAN + "\nSuggested Readings: ") + suggested_books = [ + { + 'title': 'The Alchemist', + 'author': 'Paulo Coelho', + 'fact': 'A novel that emphasizes the importance of pursuing one’s dreams.', + 'intro': 'Follow Santiago, a shepherd boy, as he journeys to discover his personal legend.' + }, + { + 'title': 'Becoming', + 'author': 'Michelle Obama', + 'fact': 'A memoir from the former First Lady of the United States.', + 'intro': 'In this deeply personal memoir, Michelle Obama invites readers into her world.' + }, + { + 'title': 'Educated', + 'author': 'Tara Westover', + 'fact': 'A memoir that recounts the author’s quest for knowledge.', + 'intro': 'Born to survivalists in the mountains of Idaho, Tara Westover didn’t set foot in a classroom until she was 17.' + }, + { + 'title': 'The Night Circus', + 'author': 'Erin Morgenstern', + 'fact': 'A fantasy novel set in a magical circus that only opens at night.', + 'intro': 'Two young illusionists, bound by a rivalry, participate in a magical competition that shapes their fates.' + }, + { + 'title': 'Sapiens: A Brief History of Humankind', + 'author': 'Yuval Noah Harari', + 'fact': 'A non-fiction book that explores the history of humanity.', + 'intro': 'Harari takes readers on a journey through the history of humankind, from the Stone Age to the modern world.' + } + ] + + for book in suggested_books: + print(Fore.GREEN + f"Title: {book['title']}") + print(Fore.MAGENTA + f"Author: {book['author']}") + print(Fore.LIGHTYELLOW_EX + f"Fact: {book['fact']}") + print(Fore.LIGHTWHITE_EX + f"Intro: {book['intro']}\n") + +def bestselling_books(): + print(Style.BRIGHT + Fore.CYAN + "\nBestselling Books: ") + books = [ + { + 'title': 'Where the Crawdads Sing', + 'author': 'Delia Owens', + 'fact': 'This novel spent over 100 weeks on the New York Times bestseller list.', + }, + { + 'title': 'The Midnight Library', + 'author': 'Matt Haig', + 'fact': 'A thought-provoking story about the choices we make in life.', + }, + { + 'title': 'The Vanishing Half', + 'author': 'Brit Bennett', + 'fact': 'A multi-generational narrative that tackles themes of race and identity.', + }, + { + 'title': 'The Book Thief', + 'author': 'Markus Zusak', + 'fact': 'A historical novel narrated by Death, set in Nazi Germany during WWII.', + }, + { + 'title': 'A Thousand Splendid Suns', + 'author': 'Khaled Hosseini', + 'fact': 'A powerful tale of female friendship, love, and endurance in war-torn Afghanistan.', + } + ] + + for book in books: + print(Fore.GREEN + f"Title: {book['title']}") + print(Fore.MAGENTA + f"Author: {book['author']}") + print(Fore.LIGHTYELLOW_EX + f"Fact: {book['fact']}\n") + +def main(): + global user_profiles + user_profiles = load_profile() # Load profile data + + print(Fore.CYAN + "Welcome to the Book Recommendation Assistant!") + + while True: + action = input(Fore.YELLOW + "Do you want to (r)egister, (l)ogin, or (e)xit? ").lower() + + if action == 'e': + print(Fore.CYAN + "Goodbye!") + break + + elif action == 'r': + username = input(Fore.YELLOW + "Enter a username to register: ") + user_data = register_user(username) + if user_data is None: + continue + + elif action == 'l': + username = input(Fore.YELLOW + "Enter a username to login: ") + user_data = login_user(username) + if user_data is None: + continue + + if user_data: + preferred_genre = input(Fore.CYAN + "Enter your preferred genre: ") + user_data['preferred_genre'] = preferred_genre + save_profile(user_profiles) + + # Automatically fetch and display book recommendations right after user enters genre + print(Fore.CYAN + f"\nFetching book recommendations for the genre '{preferred_genre}'...") + books = book_recommendation(preferred_genre) + display_recommendation(books) + + while True: + choice = input(Fore.YELLOW + "Would you like to (a)dd a book to your reading list, (r)ate a book, (v)iew your reading list, (vr) view your reviews, (sr) for suggested readings, (bb) for bestselling books, (br) for book recommendations, or (logout) to switch users? ").lower() + + if choice == 'logout': + break + + elif choice == 'br': # Re-fetch book recommendations upon request + books = book_recommendation(preferred_genre) + display_recommendation(books) + + elif choice == 'a': + book_choice = int(input(Fore.YELLOW + "Enter the number of the book you want to add to your reading list: ")) - 1 + add_to_reading_list(books[book_choice], user_data) + + elif choice == 'r': + book_choice = int(input(Fore.YELLOW + "Enter the number of the book you want to rate: ")) - 1 + rate_review_book(books[book_choice]['title'], user_data) + + elif choice == 'v': + view_reading_list(user_data) + + elif choice == 'vr': + view_reviews(user_data) + + elif choice == 'sr': + suggested_reading() + + elif choice == 'bb': + bestselling_books() + + +if __name__ == "__main__": + main() From 0edf0c52f2bbba02940d163073e340b455b3ddc2 Mon Sep 17 00:00:00 2001 From: zsquare12 <36557466+zsquare12@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:08:00 +0530 Subject: [PATCH 08/73] Add weather information page with user input form --- pages/page2.py | 0 pages/weather_info_st.py | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+) delete mode 100644 pages/page2.py create mode 100644 pages/weather_info_st.py diff --git a/pages/page2.py b/pages/page2.py deleted file mode 100644 index e69de29..0000000 diff --git a/pages/weather_info_st.py b/pages/weather_info_st.py new file mode 100644 index 0000000..7d8b38c --- /dev/null +++ b/pages/weather_info_st.py @@ -0,0 +1,21 @@ +import streamlit as st +from weather_info import get_weather + +st.title('Weather Information') + +# Create a form for user input +with st.form(key='weather_form'): + city = st.text_input('Enter city name (or type "exit" to quit): ') + unit = st.text_input('Units (metric/imperial/kelvin, leave empty for Kelvin): ') + submit_button = st.form_submit_button(label='Submit') + +# Display the weather information on form submission +if submit_button: + if city.lower() == 'exit': + st.write("Goodbye!") + else: + weather_data = get_weather(city, unit) + if weather_data: + st.write(f"## {weather_data}") + else: + st.write("No weather data available.") From 09d991a16e20538dc391c1afe7fd25025cbcf159 Mon Sep 17 00:00:00 2001 From: ragini Date: Sat, 19 Oct 2024 15:10:48 +0530 Subject: [PATCH 09/73] added functionality to COntact in footer --- frontend/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/index.html b/frontend/index.html index 618d089..15aa725 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -158,7 +158,7 @@

Quick Links

  • API Key Setup
  • Features
  • About Us
  • -
  • Contact
  • +
  • Contact
  • From 5611eb5b850530049003518a59e1347164d32694 Mon Sep 17 00:00:00 2001 From: siri-chandana-macha Date: Sat, 19 Oct 2024 17:37:53 +0530 Subject: [PATCH 10/73] Added FAQ Section --- faq.html | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 1 + script.js | 2 ++ style.css | 57 +++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 faq.html diff --git a/faq.html b/faq.html new file mode 100644 index 0000000..fd1fae0 --- /dev/null +++ b/faq.html @@ -0,0 +1,63 @@ + + + + + + + FAQ - Voice Assistant + + + + + + + + + +
    +
    + +

    Frequently Asked Questions

    +
    +
    +
    What is VOICE.py?
    +
    VOICE.py is a Python-based virtual assistant using Gemini AI, offering voice recognition, text-to-speech, and access to weather updates, news, and Wikipedia. Its customizable web interface ensures a seamless user experience.
    +
    + +
    +
    How do I use the assistant?
    +
    Click on the "Speak to the Assistant" button and ask your question.
    +
    + +
    +
    How does the voice recognition feature work?
    +
    The voice recognition feature uses the SpeechRecognition library to convert spoken words into text, which is then processed to execute commands.
    +
    + +
    +
    What APIs are integrated into VOICE.py?
    +
    VOICE.py integrates several APIs, including weather APIs for real-time updates, news APIs for fetching the latest headlines, and Wikipedia API for retrieving information.
    +
    + +
    +
    Can I use the assistant offline?
    +
    The assistant's core features, such as voice recognition and text-to-speech, may require an internet connection for optimal performance. However, some functionalities might work offline depending on how they are implemented
    +
    +
    + + + + + + + + + diff --git a/index.html b/index.html index dbe66a2..0e5ac49 100644 --- a/index.html +++ b/index.html @@ -18,6 +18,7 @@
  • Features
  • Contact
  • About
  • +
  • FAQ
  • diff --git a/script.js b/script.js index d046801..0993c02 100644 --- a/script.js +++ b/script.js @@ -16,4 +16,6 @@ document.getElementById('start-button').addEventListener('click', function() { ws.onclose = function() { console.log('WebSocket connection closed'); }; + + }); diff --git a/style.css b/style.css index 6064a30..96aa19b 100644 --- a/style.css +++ b/style.css @@ -138,4 +138,59 @@ body { #start-button { font-size: 1rem; } -} \ No newline at end of file + +} + +.faq { + max-width: 1400px; /* Adjust as needed */ + margin: 0 auto; + font-family: "Montserrat", sans-serif + } + + .faq-item { + border: 1px solid #F3FF35; /* Border around all sides */ + border-radius: 8px; /* Rounded corners */ + margin-bottom: 15px; /* Gap between items */ + overflow: hidden; /* Ensures rounded corners are applied to children */ + } + + .faq-question { + width: 100%; + padding: 20px; + background-color: #FFFACD ; + cursor: pointer; + font-size: 20px; + font-weight: bold; + display: flex; + justify-content: space-between; + align-items: center; + } + + .arrow { + font-size: 16px; + transition: transform 0.3s ease; + + } + + + .faq-answer { + padding: 15px 20px; + background-color:#ADD8E6; + display: none; + font-size: 20px; + } + + .faq-item:hover .faq-answer { + display: block; + } + + .faq-item:hover .faq-question { + background-color: #f4eff6; + } + + .faq-item:hover .arrow { + transform: rotate(180deg); + } + + + From 53b824017df8ad9fecd0c155df380de5e9bc2a94 Mon Sep 17 00:00:00 2001 From: shalini Date: Sat, 19 Oct 2024 20:22:17 +0530 Subject: [PATCH 11/73] Corrected image path --- frontend/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/index.html b/frontend/index.html index 618d089..7f5f307 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -32,7 +32,7 @@
    - Voice Assistant Image + Voice Assistant Image

    Python Voice Assistant with Gemini AI

    A smart, AI-powered voice assistant that simplifies your living!

    From c44c576a2ab687fc277af3467912e74776311458 Mon Sep 17 00:00:00 2001 From: Nishant Dwivedi <135944619+nishant4500@users.noreply.github.com> Date: Sat, 19 Oct 2024 22:19:47 +0530 Subject: [PATCH 12/73] Create hand gestures.py --- hand gestures.py | 134 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 hand gestures.py diff --git a/hand gestures.py b/hand gestures.py new file mode 100644 index 0000000..3706204 --- /dev/null +++ b/hand gestures.py @@ -0,0 +1,134 @@ +import os +import numpy as np +import cv2 +from keras.models import Sequential +from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense +from keras.utils import to_categorical +from sklearn.model_selection import train_test_split +from sklearn.preprocessing import LabelEncoder + +# 1. Data Collection Function +# Capture video frames and label them with corresponding gesture +def collect_gesture_data(gesture_name, num_samples): + cap = cv2.VideoCapture(0) + data_dir = 'gesture_data' + if not os.path.exists(data_dir): + os.makedirs(data_dir) + + gesture_dir = os.path.join(data_dir, gesture_name) + if not os.path.exists(gesture_dir): + os.makedirs(gesture_dir) + + print(f'Collecting {num_samples} samples for gesture "{gesture_name}"') + count = 0 + while count < num_samples: + ret, frame = cap.read() + if not ret: + break + # Convert to grayscale for simplicity + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + # Resize the frame to a fixed size + resized_frame = cv2.resize(gray, (64, 64)) + + # Show the frame + cv2.imshow('Gesture Collection', frame) + + # Save frame to disk + file_name = os.path.join(gesture_dir, f'{gesture_name}_{count}.jpg') + cv2.imwrite(file_name, resized_frame) + count += 1 + + # Break if 'q' is pressed + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + cv2.destroyAllWindows() + print(f"Collected {count} frames for gesture {gesture_name}.") + +# 2. Preprocessing the Dataset +def load_data(data_dir): + images = [] + labels = [] + + for gesture_name in os.listdir(data_dir): + gesture_dir = os.path.join(data_dir, gesture_name) + if not os.path.isdir(gesture_dir): + continue + + for img_name in os.listdir(gesture_dir): + img_path = os.path.join(gesture_dir, img_name) + img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) + img = img / 255.0 # Normalize the image + images.append(img) + labels.append(gesture_name) + + images = np.array(images).reshape(-1, 64, 64, 1) # Reshape for CNN + label_encoder = LabelEncoder() + labels = to_categorical(label_encoder.fit_transform(labels)) + + return images, labels, label_encoder + +# 3. CNN Model Definition +def build_model(input_shape, num_classes): + model = Sequential() + model.add(Conv2D(32, (3, 3), activation='relu', input_shape=input_shape)) + model.add(MaxPooling2D((2, 2))) + model.add(Conv2D(64, (3, 3), activation='relu')) + model.add(MaxPooling2D((2, 2))) + model.add(Flatten()) + model.add(Dense(128, activation='relu')) + model.add(Dense(num_classes, activation='softmax')) + model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) + return model + +# 4. Main Program +if __name__ == '__main__': + gestures = ['play', 'pause', 'stop', 'volume_up', 'volume_down'] + num_samples_per_gesture = 500 + + # Collecting gesture data + for gesture in gestures: + collect_gesture_data(gesture, num_samples_per_gesture) + + # Load and preprocess data + data_dir = 'gesture_data' + images, labels, label_encoder = load_data(data_dir) + + # Split data into training and testing sets + X_train, X_test, y_train, y_test = train_test_split(images, labels, test_size=0.2, random_state=42) + + # Build the CNN model + input_shape = (64, 64, 1) # Grayscale images, 64x64 pixels + num_classes = len(gestures) + model = build_model(input_shape, num_classes) + + # Train the model + model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_test, y_test)) + + # Save the model + model.save('gesture_recognition_cnn.h5') + + # Testing the model with live input + cap = cv2.VideoCapture(0) + while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + resized_frame = cv2.resize(gray, (64, 64)) + reshaped_frame = np.expand_dims(resized_frame, axis=0).reshape(-1, 64, 64, 1) + + prediction = model.predict(reshaped_frame) + predicted_class = np.argmax(prediction) + gesture_label = label_encoder.inverse_transform([predicted_class])[0] + + cv2.putText(frame, gesture_label, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) + cv2.imshow('Gesture Recognition', frame) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + cv2.destroyAllWindows() From b1cedafd3e1f52f7dcf1b12ed80e3b95825ea576 Mon Sep 17 00:00:00 2001 From: Ishu Singh Date: Sat, 19 Oct 2024 22:46:30 +0530 Subject: [PATCH 13/73] added random joke generator --- random_joke_generator.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 random_joke_generator.py diff --git a/random_joke_generator.py b/random_joke_generator.py new file mode 100644 index 0000000..52dd81d --- /dev/null +++ b/random_joke_generator.py @@ -0,0 +1,40 @@ +import requests +from textblob import TextBlob + +def get_random_joke(): + joke_url = "https://icanhazdadjoke.com/" + emoji_map = { + "positive": "😊", + "neutral": "😐", + "negative": "😢" + } + + headers = { + "Accept": "application/json", + "User-Agent": "Mozilla/5.0" + } + + def get_sentiment(joke): + analysis = TextBlob(joke) + if analysis.sentiment.polarity > 0: + return "positive" + elif analysis.sentiment.polarity == 0: + return "neutral" + else: + return "negative" + + try: + joke_response = requests.get(joke_url, headers=headers) + joke_response.raise_for_status() + joke_data = joke_response.json() + joke = joke_data["joke"] + + sentiment = get_sentiment(joke) + emoji = emoji_map.get(sentiment, "") + + return f"{joke} {emoji}" + except requests.exceptions.RequestException as e: + return f"Error fetching joke: {e}" + +if __name__ == "__main__": + print(get_random_joke()) \ No newline at end of file From ec83407d60780ab277555aa8fb62196b65871d38 Mon Sep 17 00:00:00 2001 From: Om Karmakar Date: Sun, 20 Oct 2024 11:41:47 +0530 Subject: [PATCH 14/73] Reaction TImer Game added --- reactiontimer.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 reactiontimer.py diff --git a/reactiontimer.py b/reactiontimer.py new file mode 100644 index 0000000..ce10e4a --- /dev/null +++ b/reactiontimer.py @@ -0,0 +1,57 @@ +import tkinter as tk +import random +import time +from tkinter import messagebox + +class ReactionTimerGame: + def __init__(self, root): + self.root = root + self.root.title("Reaction Timer: Color Change") + self.root.geometry("400x200") + + self.label = tk.Label(self.root, text="Wait for the button to turn green...", font=("Helvetica", 14)) + self.label.pack(pady=20) + + self.button = tk.Button(self.root, text="Click Me!", bg="gray", font=("Helvetica", 14), width=20, height=2, state=tk.DISABLED) + self.button.pack(pady=20) + self.button.bind("", self.check_reaction) + + self.start_button = tk.Button(self.root, text="Start", command=self.start_game, font=("Helvetica", 14), width=10) + self.start_button.pack(pady=20) + + self.start_time = 0 + self.is_ready = False + + def start_game(self): + self.start_button.config(state=tk.DISABLED) + self.label.config(text="Get Ready...") + self.button.config(bg="gray", state=tk.DISABLED) + + delay = random.uniform(2, 5) # Random delay between 2 and 5 seconds + self.root.after(int(delay * 1000), self.activate_button) + + def activate_button(self): + self.button.config(bg="green", state=tk.NORMAL) + self.label.config(text="Click now!") + self.start_time = time.time() + self.is_ready = True + + def check_reaction(self, event): + if self.is_ready: + reaction_time = time.time() - self.start_time + self.is_ready = False + messagebox.showinfo("Reaction Time", f"Your reaction time: {reaction_time:.3f} seconds") + else: + messagebox.showwarning("Too Soon!", "You clicked too soon!") + + self.reset_game() + + def reset_game(self): + self.button.config(bg="gray", state=tk.DISABLED) + self.label.config(text="Wait for the button to turn green...") + self.start_button.config(state=tk.NORMAL) + +if __name__ == "__main__": + root = tk.Tk() + game = ReactionTimerGame(root) + root.mainloop() From 0f30ba0ed4ad4eb1ff778930090a81e926e0c7a0 Mon Sep 17 00:00:00 2001 From: Neeru <161798182+neeru24@users.noreply.github.com> Date: Sun, 20 Oct 2024 13:08:45 +0530 Subject: [PATCH 15/73] Update README.md --- README.md | 337 ++++-------------------------------------------------- 1 file changed, 23 insertions(+), 314 deletions(-) diff --git a/README.md b/README.md index a6edd4a..b4db589 100644 --- a/README.md +++ b/README.md @@ -183,323 +183,32 @@ Make sure to replace `"GEMINI_API_KEY"`, `'YOUR_NEWS_API_KEY'`, and `'YOUR_WEATH --- -## Our Valuable Contributors ❤️✨ + # Project Admin⚡ + + + + + + +

    Suryansh singh

    + +
    + +
    + +## Acknowledgements We are grateful to all the contributors who have helped improve this project. Your contributions are what make this project better! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - suryanshsk -
    - Owner -
    - Suryansh singh -
    -
    - - yashksaini-coder -
    - Yash Kumar Saini -
    -
    - - PavanTeja2005 -
    - PavanTeja2005 -
    -
    - - Chin-may02 -
    - Vuppu Chinmay -
    -
    - - Kritika75 -
    - Kritika Singh -
    -
    - - 23wh1a0513 -
    - 23wh1a0513 -
    -
    - - djv554 -
    - Deanne Vaz -
    -
    - - wizaye -
    - Vijayendher Gatla -
    -
    - - harshbhardwaj000 -
    - Harsh Bhardwaj -
    -
    - - nishant4500 -
    - Nishant Dwivedi -
    -
    - - pavitraag -
    - Pavitraa G -
    -
    - - Dsmita03 -
    - Debasmita Sarkar -
    -
    - - jitendra-ky -
    - jitendra Kumar -
    -
    - - Yogitha128 -
    - Yogitha128 -
    -
    - - samyak-aditya -
    - Samyak Aditya -
    -
    - - ganjivamshiii -
    - ganjivamshiii -
    -
    - - Aasthaa10 -
    - Aastha Kumari -
    -
    - - Aryan-9488 -
    - Aryan -
    -
    - - NamanVer02 -
    - Naman Verma -
    -
    - - Aasthajiit -
    - Aasthajiit -
    -
    - - Shaistaattar42 -
    - Shaistaattar -
    -
    - - jaidh01 -
    - Jai Dhingra -
    -
    - - deepanshubaghel -
    - Deepanshu Baghel -
    -
    - - pratikwayal01 -
    - Pratik Wayal -
    -
    - - ShrishtiSingh26 -
    - Shrishti -
    -
    - - Deeptig9138 -
    - Deepti Gupta -
    -
    - - say-het -
    - Het Modi -
    -
    - - kushwxha -
    - Ashwin Kushwaha -
    -
    - - Herostomo -
    - Kshitij Vijay Hedau -
    -
    - - AnujSaha0111 -
    - Anuj Saha -
    -
    - - omkarmakar -
    - Om Karmakar -
    -
    - - Codewithmeowmeow -
    - codewithvibha -
    -
    - - imDarshanGK -
    - Darshan G K -
    -
    - - sanchitc05 -
    - Sanchit Chauhan -
    -
    - - from13 -
    - from13 -
    -
    - - Amulya-B28 -
    - Amulya-B28 -
    -
    - - 23WH1A0507 -
    - 23WH1A0507 -
    -
    - - sejals23 -
    - Sejal -
    -
    - - shwetzz14 -
    - Shweta Patil -
    -
    - - Maryam0330 -
    - Maryam Panjri -
    -
    - - ragini-gp -
    - Ragini Gupta -
    -
    - +

    + +

    +

    + + + +

    +

    Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes. From 3babdb9155f05f852284a2465a9fa2bb557e9baf Mon Sep 17 00:00:00 2001 From: BHARDWAJ Date: Sun, 20 Oct 2024 13:43:29 +0530 Subject: [PATCH 16/73] hover optipn activated in contact section nav-bar --- frontend/contact.html | 3 ++- frontend/index.html | 20 ++++++++++++-------- frontend/style.css | 2 ++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/frontend/contact.html b/frontend/contact.html index b631926..023e77a 100644 --- a/frontend/contact.html +++ b/frontend/contact.html @@ -76,7 +76,8 @@ } nav ul li a:hover { - background-color: var(--color15); + border-radius: 8px; + background-color: blue; color: white; } diff --git a/frontend/index.html b/frontend/index.html index 827e772..780c9c4 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -24,10 +24,13 @@ src="image/voice-assistant-ai-high-resolution-logo-transparent.png" width="20%" alt="Voice-Assistant-Ai"> @@ -42,7 +45,7 @@

    Python Voice Assistant with Gemini AI

    Features

    -
    +

    Voice Recognition

    @@ -118,7 +121,8 @@

    🌤 Weather API Key

    • Create an account on OpenWeatherMap or - WeatherAPI.
    • + WeatherAPI. +
    • Generate your API key from the dashboard.
    • Replace YOUR_WEATHER_API_KEY in the weather module of the project.
    @@ -195,10 +199,10 @@

    Contact Us

    } } - document.getElementById("scroll_top_btn").addEventListener("click", function(e) { - e.preventDefault(); // Prevent default anchor click behavior - window.scrollTo({ top: 0, behavior: 'smooth' }); // Scroll to top with smooth animation - }); + document.getElementById("scroll_top_btn").addEventListener("click", function (e) { + e.preventDefault(); // Prevent default anchor click behavior + window.scrollTo({ top: 0, behavior: 'smooth' }); // Scroll to top with smooth animation + }); - + \ No newline at end of file diff --git a/frontend/style.css b/frontend/style.css index 37fb8a5..53580aa 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -101,6 +101,7 @@ nav ul li a { } nav ul li a:hover { + border-radius: 8px; background-color: var(--color15); color: white; } @@ -118,6 +119,7 @@ nav ul li a:hover { color: var(--color6); text-align: center; padding: 50px 20px; + } .header-content img { From 86f4b0628eb63d24558076e1744aed3e703ee004 Mon Sep 17 00:00:00 2001 From: zsquare12 <36557466+zsquare12@users.noreply.github.com> Date: Sun, 20 Oct 2024 14:12:53 +0530 Subject: [PATCH 17/73] streamlit new info page added --- pages/news_info.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 pages/news_info.py diff --git a/pages/news_info.py b/pages/news_info.py new file mode 100644 index 0000000..7e680b8 --- /dev/null +++ b/pages/news_info.py @@ -0,0 +1,64 @@ +import requests +import json +import os +import streamlit as st + +def get_news(api_key, category='general', page=1, page_size=5, query=None): + try: + base_url = 'https://newsapi.org/v2/top-headlines' if not query else 'https://newsapi.org/v2/everything' + params = { + 'apiKey': api_key, + 'category': category, + 'page': page, + 'pagesize': page_size + } + + if query: + params.pop('category') + params['q'] = query + + response = requests.get(base_url, params=params) + response.raise_for_status() + + data = response.json() + articles = data.get('articles', []) + + return articles + + except requests.exceptions.RequestException as e: + st.error(f"An error occurred: {e}") + return [] + except json.JSONDecodeError as e: + st.error(f"Failed to parse JSON: {e}") + return [] + +def save_articles(articles, filename='articles.json'): + with open(filename, 'w') as f: + json.dump(articles, f, indent=4) + st.success(f"Articles saved to {filename}.") + +def main(): + st.title("News Fetcher") + + API_KEY = os.environ.get('NEWS_API_KEY') + if not API_KEY: + st.error("Please set the NEWS_API_KEY environment variable.") + return + + category = st.selectbox("Enter news category", ['general', 'business', 'technology', 'sports', 'entertainment', 'politics', 'health', 'science']) + num_articles = st.number_input("How many articles would you like to see?", min_value=1, step=1) + query = st.text_input("Enter a keyword to search for articles (or leave blank to skip)") + + if st.button("Fetch News"): + articles = get_news(API_KEY, category=category, page_size=num_articles, query=query if query else None) + + if articles: + save_articles(articles) + for article in articles: + st.subheader(article['title']) + st.write(f"**Author:** {article.get('author', 'N/A')}") + st.write(f"**Published at:** {article['publishedAt']}") + st.write(f"**Description:** {article.get('description', 'N/A')}\n") + +if __name__ == "__main__": + main() From de5cb588d6cae0104282de9f8cbd1569676a9ced Mon Sep 17 00:00:00 2001 From: zsquare12 <36557466+zsquare12@users.noreply.github.com> Date: Sun, 20 Oct 2024 14:47:20 +0530 Subject: [PATCH 18/73] Add streamlit app with Python Voice Assistant features --- st_app.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 st_app.py diff --git a/st_app.py b/st_app.py new file mode 100644 index 0000000..312d90c --- /dev/null +++ b/st_app.py @@ -0,0 +1,35 @@ +import streamlit as st + +st.set_page_config( + page_title="Python Voice Assistant", + page_icon="🎙️", + layout="centered", + initial_sidebar_state="auto", +) + +st.title("Python-Voice-Assistant-Suryanshsk") + +st.write( + "Welcome to the Python Voice Assistant! This app demonstrates how to build a simple voice assistant using Python." +) + + +st.markdown(''' +# Features + +- **Voice Recognition**: Processes and understands spoken commands. +- **Text-to-Speech**: Converts text responses into spoken output. +- **Weather Information**: Provides real-time weather updates. +- **News Updates**: Fetches the latest news headlines. +- **Jokes**: Delivers a variety of jokes. +- **Wikipedia Information**: Retrieves data from Wikipedia. +- **Music Management**: Handles and plays music. +- **Web Interface**: Interactive frontend with animations. +- **Your Question**: It Give Answer OF Your Questions. + + +## Virtual Assistant with Gemini AI + + +A sophisticated Python-based virtual assistant utilizing Gemini AI. This project integrates various functionalities to create a versatile and interactive assistant. +''') \ No newline at end of file From 2c8a8ef29aba2f6fe6a1e959132fd49560d0f47f Mon Sep 17 00:00:00 2001 From: zsquare12 <36557466+zsquare12@users.noreply.github.com> Date: Sun, 20 Oct 2024 14:47:30 +0530 Subject: [PATCH 19/73] Add random joke generator feature --- pages/jokes.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 pages/jokes.py diff --git a/pages/jokes.py b/pages/jokes.py new file mode 100644 index 0000000..5176b62 --- /dev/null +++ b/pages/jokes.py @@ -0,0 +1,45 @@ +import requests +from textblob import TextBlob +import streamlit as st + +def get_random_joke(): + joke_url = "https://icanhazdadjoke.com/" + emoji_map = { + "positive": "😊", + "neutral": "😐", + "negative": "😢" + } + + headers = { + "Accept": "application/json", + "User-Agent": "Mozilla/5.0" + } + + def get_sentiment(joke): + analysis = TextBlob(joke) + if analysis.sentiment.polarity > 0: + return "positive" + elif analysis.sentiment.polarity == 0: + return "neutral" + else: + return "negative" + + try: + joke_response = requests.get(joke_url, headers=headers) + joke_response.raise_for_status() + joke_data = joke_response.json() + joke = joke_data["joke"] + + sentiment = get_sentiment(joke) + emoji = emoji_map.get(sentiment, "") + + return f"{joke} {emoji}" + except requests.exceptions.RequestException as e: + return f"Error fetching joke: {e}" + +# Streamlit app +st.title("Random Joke Generator") + +if st.button("Get a Random Joke"): + joke = get_random_joke() + st.write(joke) \ No newline at end of file From f0140f7e59a8a3c8e09273a40f2821cc4ad02b80 Mon Sep 17 00:00:00 2001 From: Ravikrishna J <139262612+call-meRavi-SHORT-CODE@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:37:34 +0530 Subject: [PATCH 20/73] Create weather_cloth_recommendation.py --- weather_cloth_recommendation.py | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 weather_cloth_recommendation.py diff --git a/weather_cloth_recommendation.py b/weather_cloth_recommendation.py new file mode 100644 index 0000000..5dd2f29 --- /dev/null +++ b/weather_cloth_recommendation.py @@ -0,0 +1,56 @@ +import os +import requests +import google.generativeai as genai +import pyttsx3 as p + +# Set up API credentials +os.environ['GOOGLE_API_KEY'] = "your_gemini_api_key" +GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY') +genai.configure(api_key=GOOGLE_API_KEY) + +OPENWEATHERMAP_API_KEY = "your_weather_api_key" + +# Initialize text-to-speech engine +engine = p.init() + +def speak(text): + engine.say(text) + engine.runAndWait() + +def get_location(): + try: + response = requests.get('http://ipinfo.io/json') + data = response.json() + city = data.get('city', 'Unknown city') + return city + except Exception as e: + return f"Unable to fetch location data. Error: {str(e)}" + +def get_weather(city): + url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={OPENWEATHERMAP_API_KEY}&units=metric" + try: + response = requests.get(url) + data = response.json() + if data["cod"] == 200: + weather = data["weather"][0]["description"] + temperature = data["main"]["temp"] + return f"The current weather in {city} is {weather} with a temperature of {temperature}°C." + else: + return f"Unable to fetch weather data for {city}. Error: {data.get('message', 'Unknown error')}" + except Exception as e: + return f"An error occurred while fetching weather data: {str(e)}" + +def generate_text(prompt): + model = genai.GenerativeModel('gemini-pro') + try: + response = model.generate_content(f'as a good weather reporter, first give the weather in the city and then recommend whether it is safe to go out and what kind of clothes can be worn from the given input: "{prompt}". Do not use bold words or asterisks in output. Provide the output in sentences.') + text = response.text + print(text) + speak(text) + except Exception as e: + print(f"An error occurred while generating text: {str(e)}") + +if __name__ == "__main__": + city = get_location() + weather_info = get_weather(city) + generate_text(weather_info) From 5d019cf8426ec2222543466e7dff2b6271a795bd Mon Sep 17 00:00:00 2001 From: DEEPANSHU BAGHEL <92099428+deepanshubaghel@users.noreply.github.com> Date: Sun, 20 Oct 2024 19:09:16 +0530 Subject: [PATCH 21/73] tic tac toe with ai added --- Tic_tac_toe_with_ai/tic-tac-toe-AI.py | 346 ++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 Tic_tac_toe_with_ai/tic-tac-toe-AI.py diff --git a/Tic_tac_toe_with_ai/tic-tac-toe-AI.py b/Tic_tac_toe_with_ai/tic-tac-toe-AI.py new file mode 100644 index 0000000..64aebfa --- /dev/null +++ b/Tic_tac_toe_with_ai/tic-tac-toe-AI.py @@ -0,0 +1,346 @@ +#### TIC TAC TOE #### + +#START; + + +#FUNCTIONS; + +def default(): + #To be printed as Default; + print("\nWelcome! Let's play TIC TAC TOE!\n") + + +def rules(): + print("The board will look like this!") + print("The positions of this 3 x 3 board is same as the right side of your key board.\n") + print(" 7 | 8 | 9 ") + print("-----------") + print(" 4 | 5 | 6 ") + print("-----------") + print(" 1 | 2 | 3 ") + print("\nYou just have to input the position(1-9).") + + +def play(): + #Asking if the player is ready; + return input("\nAre you ready to play the game? Enter [Y]es or [N]o.\t").upper().startswith('Y') + + +def names(): + #Player names input; + + p1_name=input("\nEnter NAME of PLAYER 1:\t").capitalize() + p2_name=input("Enter NAME of PLAYER 2:\t").capitalize() + return (p1_name, p2_name) + + +def choice(): + #Player choice input; + p1_choice = ' ' + p2_choice = ' ' + while p1_choice != 'X' or p1_choice != 'O': #while loop; if the entered value isn't X or O; + + #WHILE LOOP STARTS + + p1_choice = input(f"\n{p1_name}, Do you want to be X or O?\t")[0].upper() + #The input above has [0].upper() in the end; + #So the user can enter x, X, xxxx or XXX; the input will always be taken as X; + #Thereby, increasing the user input window; + + if p1_choice == 'X' or p1_choice == 'O': + #if entered value is X or O; get out of the loop; + break + print("INVALID INPUT! Please Try Again!") + #if the entered value isn't X or O, re-run the while loop; + + #WHILE LOOP ENDS + #Assigning the value to p2 and then diplaying the values; + if p1_choice == 'X': + p2_choice = 'O' + elif p1_choice == 'O': + p2_choice = 'X' + + return (p1_choice, p2_choice) + + + +def first_player(): + #This function will randomly decide who will go first; + import random + return random.choice((0, 1)) + + +def display_board(board, avail): + print(" " + " {} | {} | {} ".format(board[7],board[8],board[9]) + " " + " {} | {} | {} ".format(avail[7],avail[8],avail[9])) + print(" " + "-----------" + " " + "-----------") + print(" " + " {} | {} | {} ".format(board[4],board[5],board[6]) + " " + " {} | {} | {} ".format(avail[4],avail[5],avail[6])) + print(" " + "-----------" + " " + "-----------") + print(" " + " {} | {} | {} ".format(board[1],board[2],board[3]) + " " + " {} | {} | {} ".format(avail[1],avail[2],avail[3])) + + +def player_choice(board, name, choice): + position = 0 + #Initialising position as 0^; so it passes through the while loop; + while position not in [1,2,3,4,5,6,7,8,9] or not space_check(board, position): + position = int(input(f'\n{name} ({choice}), Choose your next position: (1-9) \t')) + + if position not in [1,2,3,4,5,6,7,8,9] or not space_check(board, position) or position == "": + #To check whether the given position is in the set [1-9] or whether it is empty or occupied; + print(f"INVALID INPUT. Please Try Again!\n") + print("\n") + return position + + +# THIS IS THEFUNCTION WHERE AI IS ADDED: +def CompAI(board, name, choice): + position = 0 + possibilities = [x for x, letter in enumerate(board) if letter == ' ' and x != 0] + + # including both X and O, since if computer will win, he will place a choice there, but if the component will win --> we have to block that move + for let in ['O', 'X']: + for i in possibilities: + # Creating a copy of the board everytime, placing the move and checking if it wins; + # Creating a copy like this and not this boardCopy = board, since changes to boardCopy changes the original board; + boardCopy = board[:] + boardCopy[i] = let + if(win_check(boardCopy, let)): + position = i + return position + + openCorners = [x for x in possibilities if x in [1, 3, 7, 9]] + + if len(openCorners) > 0: + position = selectRandom(openCorners) + return position + + if 5 in possibilities: + position = 5 + return position + + openEdges = [x for x in possibilities if x in [2, 4, 6, 8]] + + if len(openEdges) > 0: + position = selectRandom(openEdges) + return position + + + +def selectRandom(board): + import random + ln = len(board) + r = random.randrange(0,ln) + return board[r] + + +def place_marker(board, avail, choice, position): + #To mark/replace the position on the board list; + board[position] = choice + avail[position] = ' ' + + +def space_check(board, position): + #To check whether the given position is empty or occupied; + return board[position] == ' ' + + +def full_board_check(board): + #To check if the board is full, then the game is a draw; + for i in range(1,10): + if space_check(board, i): + return False + return True + + +def win_check(board, choice): + #To check if one of the following patterns are true; then the respective player has won!; + + #HORIZONTAL CHECK; + return ( + ( board[1] == choice and board[2] == choice and board[3] == choice ) + or ( board[4] == choice and board[5] == choice and board[6] == choice ) + or ( board[7] == choice and board[8] == choice and board[9] == choice ) + #VERTICAL CHECK; + or ( board[1] == choice and board[4] == choice and board[7] == choice ) + or ( board[2] == choice and board[5] == choice and board[8] == choice ) + or ( board[3] == choice and board[6] == choice and board[9] == choice ) + #DIAGONAL CHECK; + or ( board[1] == choice and board[5] == choice and board[9] == choice ) + or ( board[3] == choice and board[5] == choice and board[7] == choice ) ) + +def delay(mode): + if mode == 2: + import time + time.sleep(2) + +def replay(): + #If the users want to play the game again? + return input('\nDo you want to play again? Enter [Y]es or [N]o: ').lower().startswith('y') + + + + + +#MAIN PROGRAM STARTS; + +print("\n\t\t NAMASTE! \n") +input("Press ENTER to start!") + +default() +rules() + + +while True: + #################################################################################### + + #Creating the board as a list; to be kept replacing it with user input; + theBoard = [' ']*10 + + #Creating the available options on the board: + available = [str(num) for num in range(0,10)] # a List Comprehension + #available = '0123456789' + + + + print("\n[0]. Player vs. Computer") + print("[1]. Player vs. Player") + print("[2]. Computer vs. Computer") + mode = int(input("\nSelect an option [0]-[2]: ")) + if mode == 1: + #Asking Names; + p1_name, p2_name = names() + # Asking Choices; Printing choices; X or O; + p1_choice, p2_choice = choice() + print(f"\n{p1_name}:", p1_choice) + print(f"{p2_name}:", p2_choice) + + elif mode == 0: + p1_name = input("\nEnter NAME of PLAYER who will go against the Computer:\t").capitalize() + p2_name = "Computer" + # Asking Choices; Printing choices; X or O; + p1_choice, p2_choice = choice() + print(f"\n{p1_name}:", p1_choice) + print(f"{p2_name}:", p2_choice) + + else: + p1_name = "Computer1" + p2_name = "Computer2" + p1_choice, p2_choice = "X", "O" + print(f"\n{p1_name}:", p1_choice) + print(f"\n{p2_name}:", p2_choice) + + + + #Printing randomly who will go first; + if first_player(): + turn = p2_name + else: + turn = p1_name + + print(f"\n{turn} will go first!") + + #Asking the user, if ready to play the game; Output will be True or False; + if(mode == 2): + ent = input("\nThis is going to be fast! Press Enter for the battle to begin!\n") + play_game = 1 + else: + play_game = play() + + while play_game: + + ############################ + #PLAYER1 + if turn == p1_name: + + #Displaying the board; + display_board(theBoard, available) + + #Position of the input; + if mode != 2: + position = player_choice(theBoard, p1_name, p1_choice) + else: + position = CompAI(theBoard, p1_name, p1_choice) + print(f'\n{p1_name} ({p1_choice}) has placed on {position}\n') + + #Replacing the ' ' at *position* to *p1_choice* in *theBoard* list; + place_marker(theBoard, available, p1_choice, position) + + #To check if Player 1 has won after the current input; + if win_check(theBoard, p1_choice): + display_board(theBoard, available) + print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + if(mode): + print(f'\n\nCONGRATULATIONS {p1_name}! YOU HAVE WON THE GAME!\n\n') + else: + print('\n\nTHE Computer HAS WON THE GAME!\n\n') + print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + play_game = False + + else: + #To check if the board is full; if yes, the game is a draw; + if full_board_check(theBoard): + display_board(theBoard, available) + print("~~~~~~~~~~~~~~~~~~") + print('\nThe game is a DRAW!\n') + print("~~~~~~~~~~~~~~~~~~") + break + #If none of the above is possible, next turn of Player 2; + else: + turn = p2_name + + + ############################ + #PLAYER2 + elif turn == p2_name: + + #Displaying the board; + display_board(theBoard, available) + + #Position of the input; + if(mode == 1): + position = player_choice(theBoard, p2_name, p2_choice) + else: + position = CompAI(theBoard, p2_name, p2_choice) + print(f'\n{p2_name} ({p2_choice}) has placed on {position}\n') + + #Replacing the ' ' at *position* to *p2_choice* in *theBoard* list; + place_marker(theBoard, available, p2_choice, position) + + #To check if Player 2 has won after the current input; + if win_check(theBoard, p2_choice): + display_board(theBoard, available) + print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + if(mode): + print(f'\n\nCONGRATULATIONS {p2_name}! YOU HAVE WON THE GAME!\n\n') + else: + print('\n\nTHE Computer HAS WON THE GAME!\n\n') + print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") + play_game = False + + else: + #To check if the board is full; if yes, the game is a draw; + if full_board_check(theBoard): + display_board(theBoard, available) + print("~~~~~~~~~~~~~~~~~~") + print('\nThe game is a DRAW!\n') + print("~~~~~~~~~~~~~~~~~~") + break + #If none of the above is possible, next turn of Player 2; + else: + turn = p1_name + + + #If the users want to play the game again? + if replay(): + #if Yes; + continue + else: + #if No; + break + + #################################################################################### + +print("\n\n\t\t\tTHE END!") + + + +#END \ No newline at end of file From 478a6fcdd0c73d6c30781e7aa26baf5a1c59c5b3 Mon Sep 17 00:00:00 2001 From: Nishant Dwivedi <135944619+nishant4500@users.noreply.github.com> Date: Sun, 20 Oct 2024 19:38:15 +0530 Subject: [PATCH 22/73] Create task.py --- task.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 task.py diff --git a/task.py b/task.py new file mode 100644 index 0000000..14d8e2a --- /dev/null +++ b/task.py @@ -0,0 +1,145 @@ +import smtplib +import time +import json +import sqlite3 +import schedule +from datetime import datetime, timedelta + +def send_email(subject, body, to_email): + try: + smtp_server = 'smtp.gmail.com' + smtp_port = 587 + sender_email = 'youremailid' + send_password = 'yourpassword' + + message = f'Subject: {subject}\n\n{body}' + + with smtplib.SMTP(smtp_server, smtp_port) as server: + server.starttls() + server.login(sender_email, send_password) + server.sendmail(sender_email, to_email, message) + + print(f"Email sent to {to_email}'") + + except Exception as e: + print(f"Something went wrong: {e}") + +class TodoList: + def __init__(self, db_name='todo_list.db'): + self.connection = sqlite3.connect(db_name) + self.create_table() + + def create_table(self): + with self.connection: + self.connection.execute(''' + CREATE TABLE IF NOT EXISTS tasks ( + id INTEGER PRIMARY KEY, + task TEXT NOT NULL, + completed BOOLEAN NOT NULL, + priority TEXT, + due_date TEXT + ) + ''') + + def clear_tasks(self): + with self.connection: + self.connection.execute('DELETE FROM tasks') + print("All tasks cleared.") + + def add_task(self, task, priority='medium', due_date=None): + with self.connection: + self.connection.execute(''' + INSERT INTO tasks (task, completed, priority, due_date) + VALUES (?, ?, ?, ?) + ''', (task, False, priority, due_date)) + print(f"Task added successfully: {task}") + + def complete_task(self, task_id): + with self.connection: + self.connection.execute(''' + UPDATE tasks SET completed = ? WHERE id = ? + ''', (True, task_id)) + print(f"Task completed no. : {task_id}") + + def delete_task(self, task_id): + with self.connection: + self.connection.execute(''' + DELETE FROM tasks WHERE id = ? + ''', (task_id,)) + print(f"Task deleted no. : {task_id}") + + def edit_task(self, task_id, new_task=None, new_priority=None, new_due_date=None): + with self.connection: + if new_task: + self.connection.execute(''' + UPDATE tasks SET task = ? WHERE id = ? + ''', (new_task, task_id)) + if new_priority: + self.connection.execute(''' + UPDATE tasks SET priority = ? WHERE id = ? + ''', (new_priority, task_id)) + if new_due_date: + self.connection.execute(''' + UPDATE tasks SET due_date = ? WHERE id = ? + ''', (new_due_date, task_id)) + print(f"Task edited: {task_id}") + + def show_tasks(self): + cursor = self.connection.cursor() + cursor.execute('SELECT * FROM tasks') + tasks = cursor.fetchall() + if not tasks: + print("None of the tasks are available") + else: + for task in tasks: + status = '✓' if task[2] else '✗' + print(f"{task[0]}: [{status}] {task[1]} (priority: {task[3]}) Due: {task[4]}") + + def search_tasks(self, keyword): + cursor = self.connection.cursor() + cursor.execute('SELECT * FROM tasks WHERE task LIKE ?', ('%' + keyword + '%',)) + tasks = cursor.fetchall() + if not tasks: + print("No matching tasks found") + else: + for task in tasks: + status = '✓' if task[2] else '✗' + print(f"{task[0]}: [{status}] {task[1]} (priority: {task[3]}) Due: {task[4]}") + +def schedule_appointment(date_time, task): + def job(): + print(f"Appointment reminder: {task}") + + schedule.every().day.at(date_time.strftime("%H:%M")).do(job) + print(f"Appointment scheduled for {date_time.strftime('%Y-%m-%d %H:%M')}: {task}") + +if __name__ == "__main__": + + todo_list = TodoList() + + # Clear existing tasks + todo_list.clear_tasks() + + # Add new tasks + todo_list.add_task('Complete the assignment', 'high', '2024-10-10') + todo_list.add_task('Buy skin care', 'low') + todo_list.add_task('Physics Numericals', 'high', '2024-10-10') + todo_list.add_task('Send the ppt to HR', 'high', '2024-10-12') + + todo_list.show_tasks() + + todo_list.complete_task(2) + todo_list.complete_task(4) + + todo_list.show_tasks() + + todo_list.edit_task(1, new_task='submit the maths assignment too', new_priority='high') + + todo_list.show_tasks() + + todo_list.delete_task(2) + + todo_list.search_tasks('assignment') + + appointment_time = datetime.strptime('2024-10-10 05:23', '%Y-%m-%d %H:%M') + schedule_appointment(appointment_time, 'Dentist appointment') From 81822dfb186342be916b1f7eef6a31752a4c0687 Mon Sep 17 00:00:00 2001 From: Nishant Dwivedi <135944619+nishant4500@users.noreply.github.com> Date: Sun, 20 Oct 2024 19:39:42 +0530 Subject: [PATCH 23/73] Create test email.py --- test email.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test email.py diff --git a/test email.py b/test email.py new file mode 100644 index 0000000..487f218 --- /dev/null +++ b/test email.py @@ -0,0 +1,24 @@ +import smtplib + +def send_email(subject, body, to_email): + try: + + smtp_server = 'sandbox.smtp.mailtrap.io' + smtp_port = 2525 # Provided by Mailtrap + sender_email = 'yourusername' # Use Mailtrap's provided username + send_password = 'yourpassword' # Use Mailtrap's provided password + + message = f'Subject: {subject}\n\n{body}' + + with smtplib.SMTP(smtp_server, smtp_port) as server: + server.starttls() + server.login(sender_email, send_password) + server.sendmail(sender_email, to_email, message) + + print(f"Email sent to {to_email}") + + except Exception as e: + print(f"Something went wrong: {e}") + +if __name__ == "__main__": + send_email("Test Email", "This is a test email body", "testemail@gmail.com") From d1fd92b0ab95bab9e92aed05bfae7843a600c2f9 Mon Sep 17 00:00:00 2001 From: Vuppu Chinmay Date: Sun, 20 Oct 2024 20:32:32 +0530 Subject: [PATCH 24/73] Add files via upload --- Heist/Heist.py | 212 ++++++++++++++++++++++++++++++++++++++++++++++++ Heist/readme.md | 30 +++++++ 2 files changed, 242 insertions(+) create mode 100644 Heist/Heist.py create mode 100644 Heist/readme.md diff --git a/Heist/Heist.py b/Heist/Heist.py new file mode 100644 index 0000000..4535330 --- /dev/null +++ b/Heist/Heist.py @@ -0,0 +1,212 @@ +import speech_recognition as sr +import pyttsx3 +import random + +engine = pyttsx3.init() + +def speak(text): + engine.say(text) + engine.runAndWait() + +def listen(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening...") + audio = recognizer.listen(source) + try: + command = recognizer.recognize_google(audio).lower() + print(f"You said: {command}") + return command + except sr.UnknownValueError: + speak("Sorry, I didn't catch that. Please repeat.") + return listen() + except sr.RequestError: + speak("Sorry, there seems to be an issue with the speech service.") + return None + +def choose_heist(heists): + heist_names = ", ".join(heists.keys()) + speak(f"Choose your heist from the following options: {heist_names}.") + user_input = listen() + if user_input in heists: + return user_input + else: + speak("That's not a valid choice. Please choose again.") + return choose_heist(heists) + +def run_heist(story_title, scenarios): + speak(f"Welcome to {story_title}. Let's begin!") + for scenario in scenarios: + speak(scenario['prompt']) + user_input = listen() + if user_input in scenario['success_choices']: + speak(scenario['success_message']) + else: + speak(scenario['failure_message']) + break + +heists = { + "The Art of Deception": [ + { + 'prompt': "You need to gain entry to the exhibition. What do you do?", + 'success_choices': ["steal the invitation", "get the invitation"], + 'success_message': "You successfully lift the invitation.", + 'failure_message': "You get caught and thrown out!" + }, + { + 'prompt': "Learn the layout of the gallery. What do you do?", + 'success_choices': ["search the pamphlet"], + 'success_message': "You find the pamphlet with valuable info.", + 'failure_message': "You get lost in the gallery!" + }, + { + 'prompt': "Acquire disguises to blend in. What do you do?", + 'success_choices': ["visit the rental shop"], + 'success_message': "You acquire convincing outfits.", + 'failure_message': "A guard spots you as suspicious!" + }, + { + 'prompt': "Disable the alarm system. What do you do?", + 'success_choices': ["contact the former employee"], + 'success_message': "You get the security codes.", + 'failure_message': "An unexpected alarm triggers!" + }, + { + 'prompt': "Escape with the painting. What do you do?", + 'success_choices': ["use the service entrance"], + 'success_message': "You slip out undetected with the painting!", + 'failure_message': "You are caught by the police!" + } + ], + "The Museum Heist": [ + { + 'prompt': "Gather information on the museum’s security. What do you do?", + 'success_choices': ["check the bulletin board"], + 'success_message': "You gather guard shift timings.", + 'failure_message': "You miss critical schedule changes!" + }, + { + 'prompt': "Enter the museum undetected. What do you do?", + 'success_choices': ["wait for the right moment"], + 'success_message': "You enter without raising alarms.", + 'failure_message': "You trigger an alarm!" + }, + { + 'prompt': "Create a diversion. What do you do?", + 'success_choices': ["hire the performer"], + 'success_message': "The performer creates chaos.", + 'failure_message': "You attract attention from the guards!" + }, + { + 'prompt': "Access the display case. What do you do?", + 'success_choices': ["use a lock-picking tool"], + 'success_message': "You unlock the case and retrieve the artifact.", + 'failure_message': "You trigger the alarm!" + }, + { + 'prompt': "Get away safely. What do you do?", + 'success_choices': ["head to the alley"], + 'success_message': "You escape in the vehicle.", + 'failure_message': "You run into a police checkpoint!" + } + ], + "The Casino Caper": [ + { + 'prompt': "Create a plan for the heist. What do you do?", + 'success_choices': ["research the layout"], + 'success_message': "You gain a detailed understanding.", + 'failure_message': "You get confused!" + }, + { + 'prompt': "Gain access to the poker tournament. What do you do?", + 'success_choices': ["approach the gambler"], + 'success_message': "You acquire the VIP tickets.", + 'failure_message': "Security catches you!" + }, + { + 'prompt': "Cause a distraction. What do you do?", + 'success_choices': ["trigger the fire alarm"], + 'success_message': "The casino evacuates.", + 'failure_message': "It raises suspicion!" + }, + { + 'prompt': "Access the chip and cash storage. What do you do?", + 'success_choices': ["steal a keycard"], + 'success_message': "You access the storage undetected.", + 'failure_message': "You get caught!" + }, + { + 'prompt': "Escape the casino. What do you do?", + 'success_choices': ["make your way to the garage"], + 'success_message': "You drive away with the loot!", + 'failure_message': "You are intercepted by security!" + } + ], + "The Bank Job": [ + { + 'prompt': "Monitor the bank's security systems. What do you do?", + 'success_choices': ["watch from the café"], + 'success_message': "You note the guard changes.", + 'failure_message': "You get caught!" + }, + { + 'prompt': "Recruit an inside man. What do you do?", + 'success_choices': ["contact the employee"], + 'success_message': "You get valuable intel.", + 'failure_message': "You miss out on crucial information!" + }, + { + 'prompt': "Acquire the necessary tools for the heist. What do you do?", + 'success_choices': ["visit the store"], + 'success_message': "You gather tools without attention.", + 'failure_message': "They fail during the heist!" + }, + { + 'prompt': "Access the bank vault. What do you do?", + 'success_choices': ["use the inside man’s access"], + 'success_message': "You enter the vault.", + 'failure_message': "You trigger an alarm!" + }, + { + 'prompt': "Flee the scene. What do you do?", + 'success_choices': ["follow the escape route"], + 'success_message': "You evade capture and drive away.", + 'failure_message': "You reach a police roadblock!" + } + ], + "The Tech Theft": [ + { + 'prompt': "Gather intel about the prototype. What do you do?", + 'success_choices': ["look up the documents"], + 'success_message': "You gather key information.", + 'failure_message': "You miss crucial details!" + }, + { + 'prompt': "Get into the building. What do you do?", + 'success_choices': ["wait for lunch hour"], + 'success_message': "You slip in unnoticed.", + 'failure_message': "You get caught!" + }, + { + 'prompt': "Blend in with employees. What do you do?", + 'success_choices': ["purchase uniforms"], + 'success_message': "You fit right in.", + 'failure_message': "You attract attention!" + }, + { + 'prompt': "Access the prototype room. What do you do?", + 'success_choices': ["steal a keycard"], + 'success_message': "You enter the room.", + 'failure_message': "You trigger the alarm!" + }, + { + 'prompt': "Escape with the prototype. What do you do?", + 'success_choices': ["head to the alley"], + 'success_message': "You escape with the prototype!", + 'failure_message': "You are intercepted by security!" + } + ] +} + +selected_heist = choose_heist(heists) +run_heist(selected_heist, heists[selected_heist]) \ No newline at end of file diff --git a/Heist/readme.md b/Heist/readme.md new file mode 100644 index 0000000..d851e09 --- /dev/null +++ b/Heist/readme.md @@ -0,0 +1,30 @@ +Heist Simulator: Operation Stealth + + +Overview + +Welcome to Heist Simulator: Operation Stealth, an interactive voice-controlled adventure where you get to choose your own heist and navigate through a series of thrilling scenarios. Will you successfully execute the perfect heist or end up caught? Your choices will determine the outcome! + +Libraries Used + +This project utilizes the following Python libraries: + +SpeechRecognition: For converting spoken language into text, enabling voice commands. + +pyttsx3: For text-to-speech conversion, allowing the program to "speak" the prompts and responses. + +random: Used to add some variability in potential future features. + +What Have I Done? + +Voice Interaction: Implemented a speech recognition system to allow users to interact with the game using their voice. + +Heist Scenarios: Created a collection of unique heist scenarios, each with multiple prompts and choices that lead to success or failure. + +Decision Making: Developed a structure that processes user choices and provides corresponding outcomes, enhancing engagement and replayability. + +User Feedback: Incorporated text-to-speech functionality to provide auditory feedback, making the experience immersive. + +Conclusion + +Heist Simulator: Operation Stealth offers a fun and engaging way to experience the thrill of planning and executing a heist. With voice control and branching storylines, each playthrough is unique. Whether you become a master thief or find yourself behind bars, the adventure awaits! Enjoy your heist! \ No newline at end of file From 7fdf9489ed53145532cc4449b529d14a87acca6a Mon Sep 17 00:00:00 2001 From: Vuppu Chinmay Date: Sun, 20 Oct 2024 20:34:39 +0530 Subject: [PATCH 25/73] Update readme.md --- Heist/readme.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Heist/readme.md b/Heist/readme.md index d851e09..34ac968 100644 --- a/Heist/readme.md +++ b/Heist/readme.md @@ -1,30 +1,30 @@ -Heist Simulator: Operation Stealth +# *Heist Simulator: Operation Stealth* -Overview +## Overview Welcome to Heist Simulator: Operation Stealth, an interactive voice-controlled adventure where you get to choose your own heist and navigate through a series of thrilling scenarios. Will you successfully execute the perfect heist or end up caught? Your choices will determine the outcome! -Libraries Used +## Libraries Used This project utilizes the following Python libraries: -SpeechRecognition: For converting spoken language into text, enabling voice commands. +- SpeechRecognition: For converting spoken language into text, enabling voice commands. -pyttsx3: For text-to-speech conversion, allowing the program to "speak" the prompts and responses. +- pyttsx3: For text-to-speech conversion, allowing the program to "speak" the prompts and responses. -random: Used to add some variability in potential future features. +- random: Used to add some variability in potential future features. -What Have I Done? +## What Have I Done? -Voice Interaction: Implemented a speech recognition system to allow users to interact with the game using their voice. +- Voice Interaction: Implemented a speech recognition system to allow users to interact with the game using their voice. -Heist Scenarios: Created a collection of unique heist scenarios, each with multiple prompts and choices that lead to success or failure. +- Heist Scenarios: Created a collection of unique heist scenarios, each with multiple prompts and choices that lead to success or failure. -Decision Making: Developed a structure that processes user choices and provides corresponding outcomes, enhancing engagement and replayability. +- Decision Making: Developed a structure that processes user choices and provides corresponding outcomes, enhancing engagement and replayability. -User Feedback: Incorporated text-to-speech functionality to provide auditory feedback, making the experience immersive. +- User Feedback: Incorporated text-to-speech functionality to provide auditory feedback, making the experience immersive. -Conclusion +## Conclusion -Heist Simulator: Operation Stealth offers a fun and engaging way to experience the thrill of planning and executing a heist. With voice control and branching storylines, each playthrough is unique. Whether you become a master thief or find yourself behind bars, the adventure awaits! Enjoy your heist! \ No newline at end of file +Heist Simulator: Operation Stealth offers a fun and engaging way to experience the thrill of planning and executing a heist. With voice control and branching storylines, each playthrough is unique. Whether you become a master thief or find yourself behind bars, the adventure awaits! Enjoy your heist! From 970d68af3fbcfc444880d349db9fa34fdc3f164e Mon Sep 17 00:00:00 2001 From: maniranjan2023 Date: Sun, 20 Oct 2024 23:49:37 +0530 Subject: [PATCH 26/73] add_fea #213 add tick tok toe game --- tick_tok_toe/index01.html | 33 ++++++++++++++ tick_tok_toe/logic01.js | 91 +++++++++++++++++++++++++++++++++++++++ tick_tok_toe/style.css | 74 +++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 tick_tok_toe/index01.html create mode 100644 tick_tok_toe/logic01.js create mode 100644 tick_tok_toe/style.css diff --git a/tick_tok_toe/index01.html b/tick_tok_toe/index01.html new file mode 100644 index 0000000..4d47b4d --- /dev/null +++ b/tick_tok_toe/index01.html @@ -0,0 +1,33 @@ + + + + + + Tic-Tac-Toe Game + + + +
    +

    Winner

    + +
    +
    +

    Tic Tac Toe

    +
    +
    + + + + + + + + + +
    +
    + +
    + + + diff --git a/tick_tok_toe/logic01.js b/tick_tok_toe/logic01.js new file mode 100644 index 0000000..8f1665b --- /dev/null +++ b/tick_tok_toe/logic01.js @@ -0,0 +1,91 @@ +let boxes = document.querySelectorAll(".box"); +let resetBtn = document.querySelector("#reset-btn"); +let newGameBtn = document.querySelector("#new-btn"); +let msgContainer = document.querySelector(".msg-container"); +let msg = document.querySelector("#msg"); + +let turnO = true; //playerX, playerO +let count = 0; //To Track Draw + +const winPatterns = [ + [0, 1, 2], + [0, 3, 6], + [0, 4, 8], + [1, 4, 7], + [2, 5, 8], + [2, 4, 6], + [3, 4, 5], + [6, 7, 8], +]; + +const resetGame = () => { + turnO = true; + count = 0; + enableBoxes(); + msgContainer.classList.add("hide"); +}; + +boxes.forEach((box) => { + box.addEventListener("click", () => { + if (turnO) { + //playerO + box.innerText = "O"; + turnO = false; + } else { + //playerX + box.innerText = "X"; + turnO = true; + } + box.disabled = true; + count++; + + let isWinner = checkWinner(); + + if (count === 9 && !isWinner) { + gameDraw(); + } + }); +}); + +const gameDraw = () => { + msg.innerText = `Game was a Draw.`; + msgContainer.classList.remove("hide"); + disableBoxes(); +}; + +const disableBoxes = () => { + for (let box of boxes) { + box.disabled = true; + } +}; + +const enableBoxes = () => { + for (let box of boxes) { + box.disabled = false; + box.innerText = ""; + } +}; + +const showWinner = (winner) => { + msg.innerText = `Congratulations, Winner is ${winner}`; + msgContainer.classList.remove("hide"); + disableBoxes(); +}; + +const checkWinner = () => { + for (let pattern of winPatterns) { + let pos1Val = boxes[pattern[0]].innerText; + let pos2Val = boxes[pattern[1]].innerText; + let pos3Val = boxes[pattern[2]].innerText; + + if (pos1Val != "" && pos2Val != "" && pos3Val != "") { + if (pos1Val === pos2Val && pos2Val === pos3Val) { + showWinner(pos1Val); + return true; + } + } + } +}; + +newGameBtn.addEventListener("click", resetGame); +resetBtn.addEventListener("click", resetGame); diff --git a/tick_tok_toe/style.css b/tick_tok_toe/style.css new file mode 100644 index 0000000..631df29 --- /dev/null +++ b/tick_tok_toe/style.css @@ -0,0 +1,74 @@ +* { + margin: 0; + padding: 0; +} + +body { + background-color: #548687; + text-align: center; +} + +.container { + height: 70vh; + display: flex; + + justify-content: center; + align-items: center; +} + +.game { + height: 60vmin; + width: 60vmin; + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 1.5vmin; +} + +.box { + height: 18vmin; + width: 18vmin; + border-radius: 1rem; + border: none; + box-shadow: 0 0 1rem rgba(0, 0, 0, 0.3); + font-size: 8vmin; + color: #b0413e; + background-color: #ffffc7; +} + +#reset-btn { + padding: 1rem; + font-size: 1.25rem; + background-color: #191913; + color: #fff; + border-radius: 1rem; + border: none; +} + +#new-btn { + padding: 1rem; + font-size: 1.25rem; + background-color: #191913; + color: #fff; + border-radius: 1rem; + border: none; +} + +#msg { + color: #ffffc7; + font-size: 5vmin; +} + +.msg-container { + height: 100vmin; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + gap: 4rem; +} + +.hide { + display: none; +} From c409711789da4fbea31411a71c01438a23ea57bf Mon Sep 17 00:00:00 2001 From: Deanne Vaz Date: Mon, 21 Oct 2024 00:16:32 +0530 Subject: [PATCH 27/73] Add files via upload --- Daily_journal.py | 149 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 Daily_journal.py diff --git a/Daily_journal.py b/Daily_journal.py new file mode 100644 index 0000000..928a6b5 --- /dev/null +++ b/Daily_journal.py @@ -0,0 +1,149 @@ +import speech_recognition as sr +import pyttsx3 +import json +import datetime +import asyncio +import os +import dateparser +from textblob import TextBlob + +# Initialize the TTS engine +engine = pyttsx3.init() +engine.setProperty('rate', 150) + +# Initialize user journal data +journal_data = {} + +# Speak and wait until it's finished (non-blocking version of pyttsx3) +async def speak_async(text): + engine.say(text) + engine.runAndWait() + await asyncio.sleep(0.1) + +# Asynchronous voice recognition input with retries +async def voice_to_text_async(): + recognizer = sr.Recognizer() + with sr.Microphone() as source: + print("Listening for your command...") + try: + audio = recognizer.listen(source, timeout=10) + command = recognizer.recognize_google(audio) + return command + except sr.UnknownValueError: + await speak_async("I didn't catch that. Could you please repeat?") + return None + except sr.RequestError: + await speak_async("The speech recognition service is unavailable at the moment.") + return None + +# Function to load journal data +def load_journal_data(user_name): + global journal_data + if os.path.exists(f"{user_name}_journal.json"): + with open(f"{user_name}_journal.json", "r") as f: + journal_data = json.load(f) + else: + print("No previous journal data found.") + +# Function to save journal data +def save_journal_data(user_name): + with open(f"{user_name}_journal.json", "w") as f: + json.dump(journal_data, f) + +# Function to get today's journal entry +async def daily_journaling_prompt(user_name): + await speak_async("How was your day today? Please reflect on anything significant.") + journal_entry = await voice_to_text_async() + + if journal_entry: + # Save the entry with timestamp + current_date = datetime.datetime.now().strftime("%Y-%m-%d") + if user_name not in journal_data: + journal_data[user_name] = [] + + journal_data[user_name].append({"date": current_date, "entry": journal_entry}) + save_journal_data(user_name) + + # Confirm journal entry saved + await speak_async("Your journal entry has been saved. Would you like to add anything else?") + extra_entry = await voice_to_text_async() + if extra_entry and extra_entry.lower() in ["yes", "sure"]: + await daily_journaling_prompt(user_name) + + # Perform emotion analysis + await analyze_emotion(journal_entry) + else: + await speak_async("It seems there was an issue with your journal entry. Please try again.") + +# Emotion Analysis and Suggestions +async def analyze_emotion(entry): + sentiment = TextBlob(entry).sentiment + polarity = sentiment.polarity + subjectivity = sentiment.subjectivity + + # More detailed emotion analysis + if polarity > 0: + if subjectivity > 0.5: + await speak_async("It seems like you're feeling positive and reflective today. Keep up the good mood!") + else: + await speak_async("You're in a positive mood. Stay grounded!") + elif polarity < 0: + await speak_async("It seems like you're feeling a bit down. How about doing something relaxing or talking to a friend?") + else: + await speak_async("Your entry seems neutral today. Stay balanced and take care of yourself.") + +# Background task for daily journaling with time customization +async def journal_prompt_scheduler(user_name, user_time="20:00"): + while True: + current_time = datetime.datetime.now().strftime("%H:%M") + if current_time == user_time: + await daily_journaling_prompt(user_name) + await asyncio.sleep(60) + +# Main function for the voice assistant +async def main(): + # Get user name for personalization + await speak_async("Hello! What is your name?") + user_name = await voice_to_text_async() + + if user_name is None: + await speak_async("I didn't get your name. I'll call you user for now.") + user_name = "user" # Fallback to prevent overwriting journals + + load_journal_data(user_name) + + # Ask for user journaling time preference + await speak_async("What time would you like to be reminded for your daily journaling? (e.g., 8 PM)") + preferred_time = await voice_to_text_async() + + # Parsing user input for time using dateparser for flexible input + try: + if preferred_time: + time_object = dateparser.parse(preferred_time) + if time_object: + user_time = time_object.strftime('%H:%M') + else: + raise ValueError + else: + user_time = "20:00" # Default to 8 PM + except ValueError: + await speak_async("I couldn't understand the time. Setting it to 8 PM by default.") + user_time = "20:00" + + # Start background task for daily journaling prompt + asyncio.create_task(journal_prompt_scheduler(user_name, user_time)) + + # Main interaction loop + while True: + command = await voice_to_text_async() + + if command is None: + continue + + if "exit" in command.lower(): + await speak_async("Goodbye!") + save_journal_data(user_name) + break + +if __name__ == "__main__": + asyncio.run(main()) From cc7b72239c0fce25a71f3a650f92ad7e6dc189df Mon Sep 17 00:00:00 2001 From: maniranjan <137239336+maniranjan2023@users.noreply.github.com> Date: Mon, 21 Oct 2024 00:36:24 +0530 Subject: [PATCH 28/73] Update index01.html --- tick_tok_toe/index01.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tick_tok_toe/index01.html b/tick_tok_toe/index01.html index 4d47b4d..f897f32 100644 --- a/tick_tok_toe/index01.html +++ b/tick_tok_toe/index01.html @@ -28,6 +28,6 @@

    Tic Tac Toe

    - + From 970dd6932b95be44c1139f444be60421ad5a856b Mon Sep 17 00:00:00 2001 From: maniranjan2023 Date: Mon, 21 Oct 2024 11:55:48 +0530 Subject: [PATCH 29/73] add a forest bomber game --- Forest_bomber game/Forest Bomber.py | 220 ++++++++++++++++++++++++++ Forest_bomber game/background.png | Bin 0 -> 22394 bytes Forest_bomber game/bomb.png | Bin 0 -> 1101 bytes Forest_bomber game/burning_plane.png | Bin 0 -> 2737 bytes Forest_bomber game/burning_tree.png | Bin 0 -> 2268 bytes Forest_bomber game/explosion.ogg | Bin 0 -> 37983 bytes Forest_bomber game/plane.png | Bin 0 -> 1469 bytes Forest_bomber game/tree.png | Bin 0 -> 2199 bytes Forest_bomber game/tree_explosion.ogg | Bin 0 -> 14900 bytes tick_tok_toe/index01.html | 2 +- 10 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 Forest_bomber game/Forest Bomber.py create mode 100644 Forest_bomber game/background.png create mode 100644 Forest_bomber game/bomb.png create mode 100644 Forest_bomber game/burning_plane.png create mode 100644 Forest_bomber game/burning_tree.png create mode 100644 Forest_bomber game/explosion.ogg create mode 100644 Forest_bomber game/plane.png create mode 100644 Forest_bomber game/tree.png create mode 100644 Forest_bomber game/tree_explosion.ogg diff --git a/Forest_bomber game/Forest Bomber.py b/Forest_bomber game/Forest Bomber.py new file mode 100644 index 0000000..913941a --- /dev/null +++ b/Forest_bomber game/Forest Bomber.py @@ -0,0 +1,220 @@ +import sys +import os +import pygame +from pygame.locals import * + +# Initialize Pygame and set up the display +pygame.init() +pygame.mixer.init() + +# Define colors +WHITE = (255, 255, 255) +PURPLE = (96, 85, 154) +LIGHT_BLUE = (157, 220, 241) +DARK_BLUE = (63, 111, 182) +GREEN = (57, 180, 22) + +# Define constants +SCREEN_WIDTH = 640 +SCREEN_HEIGHT = 480 +SCOREBOARD_MARGIN = 4 +LINE_HEIGHT = 18 +BOX_WIDTH = 300 +BOX_HEIGHT = 150 +TOTAL_LEVELS = 4 +TREE_SPACING = 40 +FIRST_TREE = 140 +GROUND_HEIGHT = 8 +TREE_OFF_GROUND = 4 +PLANE_START_X = 0 +PLANE_START_Y = 54 + +# Setup display +game_screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) +pygame.display.set_caption('Forest Bomber') + +# Load resources +background_image = pygame.image.load('background.png').convert() +tree_image = pygame.image.load('tree.png').convert_alpha() +burn_tree_image = pygame.image.load('burning_tree.png').convert_alpha() +plane_image = pygame.image.load('plane.png').convert_alpha() +burn_plane_image = pygame.image.load('burning_plane.png').convert_alpha() +bomb_image = pygame.image.load('bomb.png').convert_alpha() + +# Load sounds +explosion_sound = pygame.mixer.Sound('explosion.ogg') +tree_sound = pygame.mixer.Sound('tree_explosion.ogg') + +# Initialize variables +clock = pygame.time.Clock() +font = pygame.font.SysFont('Helvetica', 16) +level = 1 +score = 0 +hi_score = 0 +speed_boost = 0 +plane_exploded = False +level_cleared = False +plane_front = 0 +plane_explode_sound_played = False +bomb_dropped = False +bomb = bomb_image.get_rect() +plane = plane_image.get_rect() +plane.x = PLANE_START_X +plane.y = PLANE_START_Y +tree = tree_image.get_rect() +tree.y = SCREEN_HEIGHT - tree.height - TREE_OFF_GROUND +burning_tree = 0 +tree_timer = 0 +burning_trees = [] + +# Define the forest layouts +forest_1 = ['T', '-', 'T', '-', '-', '-', 'T', '-', '-', '-', '-', 'T'] +forest_2 = ['-', 'T', '-', '-', 'T', '-', 'T', '-', 'T', 'T', '-', 'T'] +forest_3 = ['T', 'T', '-', '-', 'T', '-', 'T', 'T', 'T', 'T', '-', '-'] +forest_4 = ['T', 'T', '-', '-', 'T', 'T', 'T', '-', 'T', 'T', 'T', '-'] +forest = list(forest_1) + +# Main game loop +while True: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + # Check for key presses + keys = pygame.key.get_pressed() + + # Space to drop bomb + if keys[pygame.K_SPACE]: + if not bomb_dropped and not level_cleared and not plane_exploded: + bomb_dropped = True + bomb.x = plane.x + 15 + bomb.y = plane.y + 10 + + # Enter to restart game or move to next level + if keys[pygame.K_RETURN]: + if plane_exploded or (level == TOTAL_LEVELS and level_cleared): + plane_exploded = False + plane_explode_sound_played = False + score = 0 + speed_boost = 0 + level = 1 + forest = list(forest_1) + plane.x = PLANE_START_X + plane.y = PLANE_START_Y + level_cleared = False + elif level_cleared: + level += 1 + level_cleared = False + if level == 2: + forest = list(forest_2) + elif level == 3: + forest = list(forest_3) + speed_boost = 1 + else: + forest = list(forest_4) + speed_boost = 1 + plane.x = PLANE_START_X + plane.y = PLANE_START_Y + + # Update plane position + if not level_cleared and not plane_exploded: + plane.x += 5 + speed_boost + if plane.x >= SCREEN_WIDTH: + plane.x = 0 + plane.y += 100 + + # Update bomb position + if bomb_dropped: + bomb.y += 5 + bomb.x += 3 + if bomb.y > SCREEN_HEIGHT or bomb.x > SCREEN_WIDTH: + bomb_dropped = False + # Check if bomb hits a tree + for column, forest_item in enumerate(forest): + if forest_item == 'T': + tree.x = FIRST_TREE + column * TREE_SPACING + if bomb.colliderect(tree): + forest[column] = 'B' + bomb_dropped = False + burning_trees.append(column) + tree_timer = 10 + score += 10 * level + tree_sound.play() + + # Update burning trees + if tree_timer > 0: + tree_timer -= 1 + if tree_timer == 0: + for column in burning_trees: + forest[column] = '-' + burning_trees.clear() + + # Check if plane crashes into tree or reaches the end of the level + if plane.y >= SCREEN_HEIGHT - plane.height - GROUND_HEIGHT: + plane_front = plane.x + plane.width + if plane_front >= SCREEN_WIDTH: + level_cleared = True + else: + for column, forest_item in enumerate(forest): + if forest_item == 'T' or forest_item == 'B': + tree_left = FIRST_TREE + column * TREE_SPACING + if plane_front >= tree_left: + plane_exploded = True + + # Check high score + if score > hi_score: + hi_score = score + + # Draw background and game objects + game_screen.blit(background_image, [0, 0]) + + # Draw trees + for column, forest_item in enumerate(forest): + tree.x = FIRST_TREE + column * TREE_SPACING + if forest_item == 'T': + game_screen.blit(tree_image, [tree.x, tree.y]) + elif forest_item == 'B': + game_screen.blit(burn_tree_image, [tree.x, tree.y]) + + # Draw plane + if not plane_exploded: + game_screen.blit(plane_image, [plane.x, plane.y]) + else: + plane.y = SCREEN_HEIGHT - burn_plane_image.get_height() - TREE_OFF_GROUND + game_screen.blit(burn_plane_image, [plane.x, plane.y]) + + # Draw bomb + if bomb_dropped: + game_screen.blit(bomb_image, [bomb.x, bomb.y]) + + # Draw scoreboard + score_text = f"Score: {score}" + hi_text = f"Hi Score: {hi_score}" + level_text = f"Level: {level}" + text = font.render(score_text, True, PURPLE) + game_screen.blit(text, [SCOREBOARD_MARGIN, SCOREBOARD_MARGIN]) + text = font.render(hi_text, True, PURPLE) + game_screen.blit(text, [SCREEN_WIDTH - text.get_width() - SCOREBOARD_MARGIN, SCOREBOARD_MARGIN]) + text = font.render(level_text, True, PURPLE) + game_screen.blit(text, [(SCREEN_WIDTH - text.get_width()) // 2, SCOREBOARD_MARGIN]) + + # Game over or level cleared message + if plane_exploded or level_cleared: + if plane_exploded and not plane_explode_sound_played: + explosion_sound.play() + plane_explode_sound_played = True + if plane_exploded: + text_line_1 = font.render('GAME OVER', True, WHITE) + elif level == TOTAL_LEVELS: + text_line_1 = font.render('GAME OVER - ALL LEVELS CLEARED', True, WHITE) + else: + text_line_1 = font.render(f'LEVEL {level} CLEARED', True, WHITE) + text_line_2 = font.render('RETURN for new game or level', True, WHITE) + pygame.draw.rect(game_screen, DARK_BLUE, [(SCREEN_WIDTH - BOX_WIDTH) // 2, (SCREEN_HEIGHT - BOX_HEIGHT) // 2, BOX_WIDTH, BOX_HEIGHT]) + game_screen.blit(text_line_1, [(SCREEN_WIDTH - text_line_1.get_width()) // 2, SCREEN_HEIGHT // 2 - LINE_HEIGHT]) + game_screen.blit(text_line_2, [(SCREEN_WIDTH - text_line_2.get_width()) // 2, SCREEN_HEIGHT // 2 + LINE_HEIGHT]) + + # Update the display and set the game FPS + pygame.display.update() + clock.tick(30) diff --git a/Forest_bomber game/background.png b/Forest_bomber game/background.png new file mode 100644 index 0000000000000000000000000000000000000000..48618cef547d892930b94a23ce1dc485a274ca56 GIT binary patch literal 22394 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 literal 0 HcmV?d00001 diff --git a/Forest_bomber game/bomb.png b/Forest_bomber game/bomb.png new file mode 100644 index 0000000000000000000000000000000000000000..6a35e619ffe3b1b13bb05c19eb4e31b690ff997b GIT binary patch literal 1101 zcmaJ=O=#3W6b`LODS8t`Pa#E6aW={9=9jLzZno`;yDi&Q7Z2iOX3`C9eoUtBwg`d; z!God*;=!AWdeNH~5ru-F;6d;pg7)aqLwl8V((cwCN(0HvdwJh`-}}2gQ=i;FdU#Y2 zg#Fbir@_wy{M|b;%)jf^`fGk1VwDz~jXc&t2^C5ta;aDi&>U@0M3%08qT_-ve9LdP zSgUr<#!-+%nN6-6#2hUM zH$}tBshVZN!U+*7sxB**tQLTx+KOc>s@Q)d9xWlB-Eb!QvA9%}+Kk1vEO$DcTqmE4 zk~vwmEK63P3?bkaAYBR>>VhyG8+dSNiW5I(eiVwCN90C}tSE7&n<)fwt+wSjO#6l6 zC6l`-mergh2SJwChIPss^goRqt<&aGOyvemqs0XCet2U8Ft6S2figqR#-2`m-W0Up zM0hcvA*(t?iT}wFpV$OqXzGRmu%&pQfUyotsvE#1Sce2_$SY_AKRe-}mUjx}iM(cN zP*p32S+PnJrcvSwy;Lbz2H0wtG8AGui0$*(eJtD+YnKy>Sd=uQXkjn~Gwp~)X*-I= zayjd|As($E?1!21Sk|b`yd9eO*C?4tqCniJwC(S}!t`{Eh^GUWy1W8NRe@z;4DuTG zVBXcd0)$c@PqtNXb5gm6XA%zx*$Q-tYY+-7(^Y}08VFdhpaEhi1rH+=A{9w8rzmH` zvu&6LDn6mvb!#=au(ez?G-^{sY<=*`VPoF)%aK6PA4=2~Mb=<=m z_1RvpC!9Y1a-GXs)hRW*KNjwM9Tk+3A^C6b#^t-;SKbVR&m-Ee#~)vuJ^1m=yBF;f jEA^qTk7ifbR-YXCAXr5B{f&K@&OBBtb?4QYD>wfEH;rG8 literal 0 HcmV?d00001 diff --git a/Forest_bomber game/burning_plane.png b/Forest_bomber game/burning_plane.png new file mode 100644 index 0000000000000000000000000000000000000000..6b2973ef02134bd78351c88a49e29a2bd30cf85b GIT binary patch literal 2737 zcmc&$X;>5I7LHaeJBk!RRMLQ;K$Zy!$%O4UPog@dZ-tT#4zU`d%yl0zdb_Mgk zFgICfg27^A5)Mt~g$a|TLQsVB^Tm2=7$|@YRzp~gEMBf+Xnb&QaT(}(>X?Yb zz7B?*oN~jHrPWM1Vjd%4Ac1y_Hs} z`SAZ}d{kN$wpjra`LGH}Pzup}h#jYu(b)aFp(#O>4P&)Zf+huuXCcA_87xtm>>&V!crr~0;e`SU4G)UZ6-@v^bh3yhh5+(3&d2mUK{ky^r+QN9Q~&@1 zX#OlJo9#iO__I97On(+Qt;>t$Ouu_r;i`Ys;hJ71nhU6n001}M?i%DWU00LCJ zP)Gsspa+SB7g5ACG5`Z)8jXZ|uP^#X{NB|mdV>0)n5M%Jzyc2n2}UvK5DE# zQ1K!fiGoIzPKE#oM?@(Sr%LA^r8Iqn*5}mnLt~(u53L2u(SA~*jZ@nxHOF9Pqy?`E z3n)l;T{%ECx>OZ!W3)v7dzGOoymYCFK9hD2 zS&B1q9NuL4km((6YCn=s7~Zn@Ro~Bj>&-ol9rmyZ9OpG@X7f|CCHmvOqa9^0zgyaP zO{EHC8ya)&hgfyAX2rRA9Se1Nsj}m)O-RbW?(Q4WDh>Wa>RdF>_zCgTq3C(%!xoJk zroGI?7zTCwFLxdWZPORnoWFdp+r;=G!DaFg!PdpA!`{}}1MF+w{p#+X|CX>{)U0_J zvuHeJVK2{eD8wu+gsHEBM#`00+e7!-Sfn{PwT!gwbSEULr9%RXv7~u*y}#xm{=)tq z!?Uwp&BrEs&o(^IF&zC*(?PDi(Gv8_R|o4>qf?ri&kKF?{~Z|m?4TG7W>z_eE7B!pDK*n=kfz%KbdjQ8?ejJSxap#D*@JiH~kDs#hOvI3Kx2|vbHT@=*!N5 zISD>_MdRa(d022Xb-3=*fw^18`dkxR(_A-9gsrVj$-i+SW$13}6MyH^odXWysw1DL z?ybJ`rdZ`Z$q%wDvsahYjLlo?=QWY_LnZ?;Gthe5M4^9ebPMhKj(I<%=jT-p77Zif zxbG)}-8KNu^X+bA#_vq`_w_m8SZVs8zk7UQ-RqPWIdFDD!<<`{fz5)SbFC*@;;J9L zSW_?_|055w{)$60<=ObH^sgLc3GrgT( z^RC5uL|@i$n!eb6&6ZP>yFi!X8MllZ!{v?iFCk5u}+X8b%7oBqEe3x>w$~`YiUbiYL<<;QxieECD+}MGgg?n3O3z+=^=Cj`A@`WQIn&kp zdTp6!iE$@yjuU76IQDx!w0o)4J!{Fit>D z_wnm4SlVM(kInSM2VVFrBtsB)Nw@FB(Af5UM={N`lW!CoD9_5^d8bUG^MZc(g>j~+ zaGlMpf|=CCWkSJ^%jAS4`F{O*PWQ6x->n6&6r+hT`M6mDpO?71NOKNc$#vmI5^ilLKkl_6>};r2Jm*^{DXwh2koY`u z&A9;5?S$pGquOnw{L|o{eyS|aKT)1v5p9~j(yejRIyZ~F^k?xW2Yk0KnrK@0Fwt@4 z(ZRUtaGS=%S+k&7n(`7wO|$gr=LOG{)-9*&HSN24&h%93Ur1d#4mU7(Z2Y(lvK*-j zICw;{r#bxw^qUH6Znm9B&rbdF8(k~!;UG|j!$C)FwA$_qiG?Ko)!vO>ih+u}Eu%KA z9UUb><>lo`e`qPbP>qtx&A+ir0O){^^ac(&8=~d?WqrcU?vMZTL-j__nBT-R%c*WXzx|SDm$YqX!Mk jO*?c4*1J?}n{A6}JjG8by=W+$`ibNO@K`5SZ2anPqYl#~ literal 0 HcmV?d00001 diff --git a/Forest_bomber game/burning_tree.png b/Forest_bomber game/burning_tree.png new file mode 100644 index 0000000000000000000000000000000000000000..f7190a6e4d76a59fb69d8e4a054f7221cc3d3734 GIT binary patch literal 2268 zcmc&$c~}!?8Xx2e;eG(ap%4NthfFfLj|CA(xP)+p6{Qw)OdvoGlfeWkRdLaZyDX(p zK|ClF6|D;0>Nd)Qbg31uT2u-G7F{h^P^ySpIVL+1ar=i)|J`|>neY4Fd4KQwd#`zB zcd9VX5$}x$0KhRJo}Z4bUf3Okv&5d);@tjb79fHwBttDn^kOXxM9I_=n3$jx=fdf* zSXR905*!WymVZ@14GwmqO)oxfF;-q0vB01Jo6(5U~MN z=>irl@L`=)tI!|{wTfuAD3+*;kO&gSbRh(#COP@7VU_MpqOg=v3}Ow1N`@#(r8%zG z+Bzg1{vVBZYU@PB8kmv}>(oVBDOL}8z#QDkOm) zLBigUWeOROCWdG*#HN8PF;faM#BvVEk;oY!n*oX0EHQ)5rOOxXybCYjvgmXHHI~U? zQmIq{J35L3MbSA_E)>m$I1qCYo1oGmVwDtL^sT^rzrhOr5X+0v!eT_N6{*#Qi(QbK zr$*GeJhg@x6JxGAn;5)Sp^~Zfx)5`j7NX|ETE%8q7OPb&iLdj_Q@n!%ERirFh|U2S zaw!XxFc@r5!jjNHSOPIh_|~ zpZ7uh={=#M6*lvCUF_2Q=Wf%LLOd@LAMwe1=(wNBB=XPx@OGPTkJ714>iVSF8=YTn zdhUZxxZe`tCJ_5WN*vnj@*v3;odeOSu<Q&UxS&oIKRWFAOl>oNk>Ka)JT>5m_wh!b5P$+OyPY!q5w7$ohZY%NJmfXn<(JmtJ8^?R zl1l-Nys-Lhdc#?XkdTy$d zd$1$RRNQc-vSi@?@YNyxk(|MAz{#!k^)r)MC-3jyZkSJ!Z`P;W(UU^@2C1%o1RL7L zqEbQAZIQ#vPCqyN$p)HJ8A!mDZWyn;s;s`yV|#=e7UJS3XNN1pMd1&&JOl{%ZgqcVVOIlZriG8q za6nJ|zbg`-I#}K-^t0auH||TBJA5m)Mfgb?pk(oN^{zfz@dp>tf5kU(Rvn2HxA~ zy=KokcS}a2cdyTICtlt0s@OPkiqxLA`uOF8%|pLjn3okKSUd|o^_*QaaF>vOckg_*Y@hIm zE-uw_Us!?GWA~M?m3t;rBlLT_^Vi0D0LEj-%y?Q*)7M72g1&c&3p%)+Sxt+ zFef|k_$qNin=70p9KCqCV!U*zLqY7p@u^ntKYQ+MX{KBvDHCdDDG6I$yTheZYqwbd YUmU>Ia^An#VE*4o5D57vqc@iQ7r?sB82|tP literal 0 HcmV?d00001 diff --git a/Forest_bomber game/explosion.ogg b/Forest_bomber game/explosion.ogg new file mode 100644 index 0000000000000000000000000000000000000000..d22b84cf081b337b08d2b8ce264c338d14c7716f GIT binary patch literal 37983 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 XzE|_u7wMt)*bmk1DsXn?R5bnz{~Pgc7MO$ zcfX(S_w#-2Y)@H90Y7wAC;$L_W1-%}tt+`ZE!dBHUMq<1^9oo)4O_uj*fzpN1GyAq zra_~fXrN6rLA7t3qq70PZ>O!YhOH?s(vXZ@LU?r~9=nr613>l~kCPyqXcjcn4K{}s zdic&|2((dJs9I5s6gzda)mGTyqANN|D#?x}5~rXwIbgO&!x^yCECG7#%?`K5qlKQ@ z)o^>SSPFqpRoEsi^o&$ZaT%y%Tr{YVC}9$nt3eemK^3@KhGl{>1XW5AT#8~af@%<4 zgP`Ej1##Y7ltp9G=P&uUI& zcC#k>e>7gG?XGNh(oz%cW?Eb%R}V|-GMLNVPdoA|a%?oEE*n=AqFK+7Eq2<$8ueO; zdn2K2ltxA%G8$3IU?rg-VT`b-VYS(U!72nxJ45RS_^Q!xS*3LNE(S zsAU97KvIsP)Z08iYNllo*P-6+^U>fA&xeb4a1-U?Mkl>t{#^j@*;-aqX(&HtLOaUW zj|K(B2P8I3`Udz3>(jG#uLDhF?r>!c9+On=pJ5JNe_9nG4%F`qPA+2v>jI*){1Xi2 zx)xIu5+Jm;=WUM?n&NpG{>G7g84YoQsxWLLFElw&f506azmhx~S~Hex80+M}ly3Ny zCb1~Q^oMa7C!LJ!m!IBX}94?lbChD?K-VGx*?@sN9%t)mY?AOC&opPuE9ROS;k@ zC@THqnW=P*__JnP{GIWlu%qKQI;XesPJdM)PqBQoaA+ZG=ySYl;cV*LuOA&9{l$}k z_=lTI?>u?q<0FD<>t@Hd^RH2}g_4iHKRor?Ma?2;SZtnG>OcL%^c-_}5MEhTg#N<~ z|L%6%+)#ht_Tcy7w5Weh7qsm{;)*`;dwJV^J$krvvHgPK_L&Vw&P7J`kM;={?1LF2 z@KjOzm62@KvB?vC*CbzePG5UVArTLkxbfY6{=Qp|UoPyt)i=ia54fkssYK<;PiMwo zt$+KwsZ%}2DCbFQ;(ta2|2ojL@oeVt$nB=P`>gFBKRNPdUd^U+=U6bR&SO5x3Z*+| z_B7u7L4N;(v@c^ibaaToSoEkb>FVcvh{t~Gb7gn{5Ka)^KR&2D^zMD?8(B9Gi0O#{ zuFg&JsA*I4iN{||>O)Xudw$A}^nwgvS9Xsx8GPf!>K%Cpa@J#m1*aZw$ytB(tG%ag zWcnv`trbek>q`w#+Rd~AbylzM&koCeJ^WsRPvMGv)sH?PF5#nj)!(Qq_KWt{#tLr7RNY%xXzm{D=ly;H zp?H(yjkR$T<0tNU)EECMSePLeoC@F5rUUq2ez??CH~NmQ7yV_{?iH~~CmW(0n>xqBr-`t-+Q+kZFWwoy mJCvOF{`9Rc)QhFB2P43mTOyBV@0`y2t6(&g=+ESB==v|7Fi#Tz literal 0 HcmV?d00001 diff --git a/Forest_bomber game/tree_explosion.ogg b/Forest_bomber game/tree_explosion.ogg new file mode 100644 index 0000000000000000000000000000000000000000..f9fa717c673bd552f4f599da02ce562c1b6b1c8f GIT binary patch literal 14900 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 literal 0 HcmV?d00001 diff --git a/tick_tok_toe/index01.html b/tick_tok_toe/index01.html index 4d47b4d..f897f32 100644 --- a/tick_tok_toe/index01.html +++ b/tick_tok_toe/index01.html @@ -28,6 +28,6 @@

    Tic Tac Toe

    - + From 24868dec236506b032ea475270aa2e0d3f719ce8 Mon Sep 17 00:00:00 2001 From: akhulisumit Date: Mon, 21 Oct 2024 18:45:21 +0530 Subject: [PATCH 30/73] trailing cursor --- index.html | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/index.html b/index.html index 0e5ac49..e0d7db8 100644 --- a/index.html +++ b/index.html @@ -6,10 +6,96 @@ Voice Assistant + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    - Voice Assistant Image + Voice Assistant Image

    Python Voice Assistant with Gemini AI

    A smart, AI-powered voice assistant that simplifies your living!

    diff --git a/frontend/style.css b/frontend/style.css index 37fb8a5..fabb286 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -55,6 +55,7 @@ body { width: 50px; height: 30px; margin-right: 10px; + mix-blend-mode: multiply; } nav { From 28c4b461014e1203f5c97c7ff68b9a1e9e5bbb1f Mon Sep 17 00:00:00 2001 From: Niraj Parmar <107384357+Niraj1608@users.noreply.github.com> Date: Wed, 23 Oct 2024 07:09:15 +0000 Subject: [PATCH 58/73] github --- Web-Scraping/github_repo_scraper/README.md | 25 + .../github_repo_scraper.ipynb | 2168 +++++++++++++++++ 2 files changed, 2193 insertions(+) create mode 100644 Web-Scraping/github_repo_scraper/README.md create mode 100644 Web-Scraping/github_repo_scraper/github_repo_scraper.ipynb diff --git a/Web-Scraping/github_repo_scraper/README.md b/Web-Scraping/github_repo_scraper/README.md new file mode 100644 index 0000000..40d5a97 --- /dev/null +++ b/Web-Scraping/github_repo_scraper/README.md @@ -0,0 +1,25 @@ + +# GitHub Topic and Repository Scraper + +This project is a Scrapy-based web scraper that extracts topics and repositories from GitHub and applies a summarization model for processing the scraped data. It can efficiently gather information about GitHub repositories, including the repository name, description, topics, and more. + +## Features + +- **Scrapes GitHub repositories**: Extracts key information such as repository name, description, and associated topics. +- **Proxy support**: Handles IP rotation and proxies to avoid getting blocked during scraping. +- **Summarization Model**: Utilizes a summarization model (like BERT) to condense repository descriptions for further analysis. +- **NLP Integration**: Processes the extracted content using NLP techniques, extracting relevant keywords and insights. + +## Requirements + +To run this project, you need the following: + +- Python 3.7+ +- Scrapy +- BeautifulSoup (for additional parsing) +- Hugging Face transformers (for NLP tasks) + +You can install the required packages using: + +```bash +pip install scrapy beautifulsoup4 transformers diff --git a/Web-Scraping/github_repo_scraper/github_repo_scraper.ipynb b/Web-Scraping/github_repo_scraper/github_repo_scraper.ipynb new file mode 100644 index 0000000..ce1e495 --- /dev/null +++ b/Web-Scraping/github_repo_scraper/github_repo_scraper.ipynb @@ -0,0 +1,2168 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "### Web Scraper of Trending Repositories on Github" + ], + "metadata": { + "id": "yK7-Rd374TiB" + } + }, + { + "cell_type": "code", + "source": [ + "import requests\n", + "from bs4 import BeautifulSoup\n", + "import pandas as pd\n", + "import base64" + ], + "metadata": { + "id": "96DYZj8q4qNK" + }, + "execution_count": 7, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "topics_url = 'https://github.com/topics'" + ], + "metadata": { + "id": "URtvE66M4sHb" + }, + "execution_count": 62, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "response = requests.get(topics_url)\n", + "content = response.text" + ], + "metadata": { + "id": "rwduGUCB4zFh" + }, + "execution_count": 63, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "content[:1000]" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 123 + }, + "id": "I--FZfK0KVbN", + "outputId": "5c3fb96b-90ac-4a1f-f879-0c95806b37da" + }, + "execution_count": 64, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'\\n\\n\\n\\n\\n\\n\\n \\n \\n \\n \\n \\n \\n \\n \\n\\n \\n\\n 3D

    ,\n", + "

    Ajax

    ,\n", + "

    Algorithm

    ,\n", + "

    Amp

    ,\n", + "

    Android

    ,\n", + "

    Angular

    ,\n", + "

    Ansible

    ,\n", + "

    API

    ,\n", + "

    Arduino

    ,\n", + "

    ASP.NET

    ,\n", + "

    Awesome Lists

    ,\n", + "

    Amazon Web Services

    ,\n", + "

    Azure

    ,\n", + "

    Babel

    ,\n", + "

    Bash

    ,\n", + "

    Bitcoin

    ,\n", + "

    Bootstrap

    ,\n", + "

    Bot

    ,\n", + "

    C

    ,\n", + "

    Chrome

    ,\n", + "

    Chrome extension

    ,\n", + "

    Command-line interface

    ,\n", + "

    Clojure

    ,\n", + "

    Code quality

    ,\n", + "

    Code review

    ,\n", + "

    Compiler

    ,\n", + "

    Continuous integration

    ,\n", + "

    C++

    ,\n", + "

    Cryptocurrency

    ,\n", + "

    Crystal

    ]" + ] + }, + "metadata": {}, + "execution_count": 67 + } + ] + }, + { + "cell_type": "code", + "source": [ + "a = topic_titles[0].parent.parent.find_all('a',{'class':'no-underline flex-grow-0'}, href=True)\n", + "a[0]['href']" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 36 + }, + "id": "JkiTvhzN6JOF", + "outputId": "13c3da33-176a-4dff-e84b-4456a5bc1b79" + }, + "execution_count": 68, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'/topics/3d'" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {}, + "execution_count": 68 + } + ] + }, + { + "cell_type": "code", + "source": [ + "topic_titles_ = []\n", + "topic_urls = []\n", + "for tag in topic_titles :\n", + " topic_titles_.append(tag.text)\n", + " topic_urls.append(\"https://github.com\"+tag.parent.parent.find_all('a',{'class':'no-underline flex-grow-0'}, href=True)[0]['href'])\n", + "topic_urls\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "GBxxo58Q8VOG", + "outputId": "e8394cf6-5c13-4c2d-ac87-07b752a4c98f" + }, + "execution_count": 69, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "['https://github.com/topics/3d',\n", + " 'https://github.com/topics/ajax',\n", + " 'https://github.com/topics/algorithm',\n", + " 'https://github.com/topics/amphp',\n", + " 'https://github.com/topics/android',\n", + " 'https://github.com/topics/angular',\n", + " 'https://github.com/topics/ansible',\n", + " 'https://github.com/topics/api',\n", + " 'https://github.com/topics/arduino',\n", + " 'https://github.com/topics/aspnet',\n", + " 'https://github.com/topics/awesome',\n", + " 'https://github.com/topics/aws',\n", + " 'https://github.com/topics/azure',\n", + " 'https://github.com/topics/babel',\n", + " 'https://github.com/topics/bash',\n", + " 'https://github.com/topics/bitcoin',\n", + " 'https://github.com/topics/bootstrap',\n", + " 'https://github.com/topics/bot',\n", + " 'https://github.com/topics/c',\n", + " 'https://github.com/topics/chrome',\n", + " 'https://github.com/topics/chrome-extension',\n", + " 'https://github.com/topics/cli',\n", + " 'https://github.com/topics/clojure',\n", + " 'https://github.com/topics/code-quality',\n", + " 'https://github.com/topics/code-review',\n", + " 'https://github.com/topics/compiler',\n", + " 'https://github.com/topics/continuous-integration',\n", + " 'https://github.com/topics/cpp',\n", + " 'https://github.com/topics/cryptocurrency',\n", + " 'https://github.com/topics/crystal']" + ] + }, + "metadata": {}, + "execution_count": 69 + } + ] + }, + { + "cell_type": "code", + "source": [ + "df = pd.DataFrame({'topic_title': topic_titles_, 'topic_url': topic_urls})" + ], + "metadata": { + "id": "e2wCmQOI9HIC" + }, + "execution_count": 70, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "df.head()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "id": "ebpMu1c99aM7", + "outputId": "34cd8b84-8cfc-4afb-9f46-7a24024fb787" + }, + "execution_count": 71, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " topic_title topic_url\n", + "0 3D https://github.com/topics/3d\n", + "1 Ajax https://github.com/topics/ajax\n", + "2 Algorithm https://github.com/topics/algorithm\n", + "3 Amp https://github.com/topics/amphp\n", + "4 Android https://github.com/topics/android" + ], + "text/html": [ + "\n", + "
    \n", + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    topic_titletopic_url
    03Dhttps://github.com/topics/3d
    1Ajaxhttps://github.com/topics/ajax
    2Algorithmhttps://github.com/topics/algorithm
    3Amphttps://github.com/topics/amphp
    4Androidhttps://github.com/topics/android
    \n", + "
    \n", + "
    \n", + "\n", + "
    \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
    \n", + "\n", + "\n", + "
    \n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
    \n", + "\n", + "
    \n", + "
    \n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "df", + "summary": "{\n \"name\": \"df\",\n \"rows\": 30,\n \"fields\": [\n {\n \"column\": \"topic_title\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 30,\n \"samples\": [\n \"C++\",\n \"Bitcoin\",\n \"Code quality\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"topic_url\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 30,\n \"samples\": [\n \"https://github.com/topics/cpp\",\n \"https://github.com/topics/bitcoin\",\n \"https://github.com/topics/code-quality\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 71 + } + ] + }, + { + "cell_type": "code", + "source": [ + "def get_info_from_topic(url) :\n", + " response = requests.get(url).text\n", + " content = BeautifulSoup(response,'html.parser')\n", + " usernames = []\n", + " repos = []\n", + " repo_urls = []\n", + " stars = []\n", + " repositories = content.find_all('h3',{'class': \"f3 color-fg-muted text-normal lh-condensed\"})\n", + " stars_raw = content.find_all('span', {'id' : \"repo-stars-counter-star\"})\n", + " for i in range(len(repositories)) :\n", + " repo = repositories[i]\n", + " usernames.append(repo.find_all('a')[0].text.strip())\n", + " repos.append(repo.find_all('a')[1].text.strip())\n", + " repo_urls.append(\"https://github.com\"+repo.find_all('a')[1]['href'])\n", + " star = stars_raw[i].text.strip()\n", + " if star[-1]=='k' :\n", + " star = star[:-1]\n", + " star = float(star)\n", + " star = int(star*1000)\n", + " else : star = int(star)\n", + " stars.append(star)\n", + " return {\n", + " \"usernames\" : usernames,\n", + " \"repos\" : repos,\n", + " \"stars\" : stars,\n", + " \"repo_urls\" : repo_urls,\n", + " }\n" + ], + "metadata": { + "id": "ILbICkQP9dCz" + }, + "execution_count": 72, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "df = pd.DataFrame(get_info_from_topic(\"https://github.com/topics/Android\"))\n", + "df.head()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "id": "KwBz9mYa-Zvn", + "outputId": "28828daa-bc02-4fd4-f1f9-d86786ccf2d7" + }, + "execution_count": 74, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " usernames repos stars \\\n", + "0 flutter flutter 165000 \n", + "1 facebook react-native 119000 \n", + "2 justjavac free-programming-books-zh_CN 111000 \n", + "3 Genymobile scrcpy 110000 \n", + "4 Hack-with-Github Awesome-Hacking 83900 \n", + "\n", + " repo_urls \n", + "0 https://github.com/flutter/flutter \n", + "1 https://github.com/facebook/react-native \n", + "2 https://github.com/justjavac/free-programming-... \n", + "3 https://github.com/Genymobile/scrcpy \n", + "4 https://github.com/Hack-with-Github/Awesome-Ha... " + ], + "text/html": [ + "\n", + "
    \n", + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    usernamesreposstarsrepo_urls
    0flutterflutter165000https://github.com/flutter/flutter
    1facebookreact-native119000https://github.com/facebook/react-native
    2justjavacfree-programming-books-zh_CN111000https://github.com/justjavac/free-programming-...
    3Genymobilescrcpy110000https://github.com/Genymobile/scrcpy
    4Hack-with-GithubAwesome-Hacking83900https://github.com/Hack-with-Github/Awesome-Ha...
    \n", + "
    \n", + "
    \n", + "\n", + "
    \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
    \n", + "\n", + "\n", + "
    \n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
    \n", + "\n", + "
    \n", + "
    \n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "df", + "summary": "{\n \"name\": \"df\",\n \"rows\": 20,\n \"fields\": [\n {\n \"column\": \"usernames\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 19,\n \"samples\": [\n \"flutter\",\n \"Solido\",\n \"android\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"repos\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 20,\n \"samples\": [\n \"flutter\",\n \"MPAndroidChart\",\n \"uni-app\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"stars\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 35876,\n \"min\": 35200,\n \"max\": 165000,\n \"num_unique_values\": 19,\n \"samples\": [\n 165000,\n 53400,\n 44300\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"repo_urls\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 20,\n \"samples\": [\n \"https://github.com/flutter/flutter\",\n \"https://github.com/PhilJay/MPAndroidChart\",\n \"https://github.com/dcloudio/uni-app\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 74 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "#save the data in to csv" + ], + "metadata": { + "id": "MwxOxZVSecOQ" + } + }, + { + "cell_type": "code", + "source": [ + "for i in range(len(topic_titles_)) :\n", + " df = pd.DataFrame(get_info_from_topic(topic_urls[i]))\n", + " df.to_csv(topic_titles_[i])" + ], + "metadata": { + "id": "byV3FAy6_KoI" + }, + "execution_count": 75, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "scrap the readme file of repo." + ], + "metadata": { + "id": "CAW7AIZqejOb" + } + }, + { + "cell_type": "code", + "source": [ + "import requests\n", + "from bs4 import BeautifulSoup\n", + "\n", + "# URL of the README page\n", + "url = \"https://github.com/bumptech/glide\"\n", + "\n", + "# Fetch the README page\n", + "response = requests.get(url)\n", + "soup = BeautifulSoup(response.text, 'html.parser')\n", + "\n", + "# Extract the title (usually in

    or

    )\n", + "title = soup.find('h1').get_text(strip=True)\n", + "\n", + "# Extract the description (first

    after title or within a specific section)\n", + "description = soup.find('p').get_text(strip=True)\n", + "\n", + "# Extract all paragraphs (for main content)\n", + "content_paragraphs = soup.find_all('p')\n", + "content = [para.get_text(strip=True) for para in content_paragraphs]\n", + "\n", + "# Extract links from the content\n", + "links = []\n", + "for link in soup.find_all('a', href=True):\n", + " links.append((link.get_text(strip=True), link['href']))\n", + "\n" + ], + "metadata": { + "id": "umk_RfvdGNqh" + }, + "execution_count": 76, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# Display the extracted content\n", + "print(\"Title:\", title)\n", + "\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "OPIcuUL1P3oa", + "outputId": "b3ffa345-b83c-41bf-bff2-ce86cc1b869c" + }, + "execution_count": 77, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Title: Search code, repositories, users, issues, pull requests...\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "print(\"Content:\", content)\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "S8gLnpZzP50m", + "outputId": "93a7ffd2-1ed2-405b-d304-a8cfb9e70587" + }, + "execution_count": 78, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Content: ['We read every piece of feedback, and take your input very seriously.', 'To see all available qualifiers, see ourdocumentation.', 'An image loading and caching library for Android focused on smooth scrolling', \"|View Glide's documentation|简体中文文档|Report an issue with Glide\", 'Glide is a fast and efficient open source media management and image loading framework for Android that wraps media\\ndecoding, memory and disk caching, and resource pooling into a simple and easy to use interface.', '', \"Glide supports fetching, decoding, and displaying video stills, images, and animated GIFs. Glide includes a flexible API\\nthat allows developers to plug in to almost any network stack. By default Glide uses a customHttpUrlConnectionbased\\nstack, but also includes utility libraries plug in to Google's Volley project or Square's OkHttp library instead.\", \"Glide's primary focus is on making scrolling any kind of a list of images as smooth and fast as possible, but Glide is\\nalso effective for almost any case where you need to fetch, resize, and display a remote image.\", \"For detailed instructions and requirements, see Glide'sdownload and setup docs page.\", \"You can download a jar from GitHub'sreleases page.\", 'Or use Gradle:', 'Or Maven:', 'For info on using the bleeding edge, see theSnapshotsdocs page.', 'The specific rules arealready bundledinto the aar which can be interpreted by R8 automatically', 'Check out thedocumentationfor pages on a variety of topics, and see thejavadocs.', 'For Glide v3, see thewiki.', 'Simple use cases will look something like this:', 'Version 4 is now released and stable. Updates are released periodically with new features and bug fixes.', 'Comments/bugs/questions/pull requests are always welcome! Please readCONTRIBUTING.mdon how to report issues.', 'If you need to support older versions of Android, consider staying onGlide v3, which works on API 10, but is not actively maintained.', 'Building Glide with gradle is fairly straight forward:', 'Note: Make sure yourAndroid SDKhas theAndroid Support Repositoryinstalled, and that your$ANDROID_HOMEenvironment\\nvariable is pointing at the SDK or add alocal.propertiesfile in the root project with asdk.dir=...line.', 'Follow the steps in theBuildsection to set up the project and then:', 'You may also find precompiled APKs on thereleases page.', \"Follow the steps in theBuildsection to setup the project and then edit the files however you wish.Android Studiocleanly imports both Glide's source and tests and is the recommended way to work with Glide.\", 'To open the project in Android Studio:', 'For more details, see theContributing docs page.', \"To report a specific problem or feature request,open a new issue on Github. For questions, suggestions, or\\nanything else, emailGlide's discussion group, or join our IRC channel:irc.freenode.net#glide-library.\", \"Before submitting pull requests, contributors must sign Google'sindividual contributor license agreement.\", 'Sam Judd - @sjudd on GitHub, @samajudd on Twitter', 'BSD, part MIT and Apache 2.0. See theLICENSEfile for details.', 'This is not an official Google product.', 'An image loading and caching library for Android focused on smooth scrolling']\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "print(\"Links:\", links)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Ul322fF_P8gZ", + "outputId": "eddd5810-7987-4e3e-b321-0a701a9e3cae" + }, + "execution_count": 79, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Links: [('Skip to content', '#start-of-content'), ('', '/'), ('Sign in', '/login?return_to=https%3A%2F%2Fgithub.com%2Fbumptech%2Fglide'), ('GitHub CopilotWrite better code with AI', 'https://github.com/features/copilot'), ('SecurityFind and fix vulnerabilities', 'https://github.com/features/security'), ('ActionsAutomate any workflow', 'https://github.com/features/actions'), ('CodespacesInstant dev environments', 'https://github.com/features/codespaces'), ('IssuesPlan and track work', 'https://github.com/features/issues'), ('Code ReviewManage code changes', 'https://github.com/features/code-review'), ('DiscussionsCollaborate outside of code', 'https://github.com/features/discussions'), ('Code SearchFind more, search less', 'https://github.com/features/code-search'), ('All features', 'https://github.com/features'), ('Documentation', 'https://docs.github.com'), ('GitHub Skills', 'https://skills.github.com'), ('Blog', 'https://github.blog'), ('Enterprise', 'https://github.com/enterprise'), ('Teams', 'https://github.com/team'), ('Startups', 'https://github.com/enterprise/startups'), ('Healthcare', 'https://github.com/solutions/industries/healthcare'), ('Financial services', 'https://github.com/solutions/industries/financial-services'), ('Manufacturing', 'https://github.com/solutions/industries/manufacturing'), ('CI/CD & Automation', 'https://github.com/solutions/ci-cd'), ('DevOps', 'https://github.com/solutions/devops'), ('DevSecOps', 'https://github.com/solutions/devsecops'), ('AI', '/resources/articles/ai'), ('DevOps', '/resources/articles/devops'), ('Security', '/resources/articles/security'), ('Software Development', '/resources/articles/software-development'), ('View all', '/resources/articles'), ('Learning Pathways', 'https://resources.github.com/learn/pathways'), ('White papers, Ebooks, Webinars', 'https://resources.github.com'), ('Customer Stories', 'https://github.com/customer-stories'), ('Partners', 'https://partner.github.com'), ('GitHub SponsorsFund open source developers', '/sponsors'), ('The ReadME ProjectGitHub community articles', 'https://github.com/readme'), ('Topics', 'https://github.com/topics'), ('Trending', 'https://github.com/trending'), ('Collections', 'https://github.com/collections'), ('Enterprise platformAI-powered developer platform', '/enterprise'), ('Advanced SecurityEnterprise-grade security features', 'https://github.com/enterprise/advanced-security'), ('GitHub CopilotEnterprise-grade AI features', '/features/copilot#enterprise'), ('Premium SupportEnterprise-grade 24/7 support', '/premium-support'), ('Pricing', 'https://github.com/pricing'), ('Search syntax tips', 'https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax'), ('documentation', 'https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax'), ('Sign in', '/login?return_to=https%3A%2F%2Fgithub.com%2Fbumptech%2Fglide'), ('Sign up', '/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E&source=header-repo&source_repo=bumptech%2Fglide'), ('Reload', ''), ('Reload', ''), ('Reload', ''), ('bumptech', '/bumptech'), ('glide', '/bumptech/glide'), ('Notifications', '/login?return_to=%2Fbumptech%2Fglide'), ('Fork6.1k', '/login?return_to=%2Fbumptech%2Fglide'), ('Star34.6k', '/login?return_to=%2Fbumptech%2Fglide'), ('bumptech.github.io/glide/', 'https://bumptech.github.io/glide/'), ('View license', '/bumptech/glide/blob/master/LICENSE'), ('34.6kstars', '/bumptech/glide/stargazers'), ('6.1kforks', '/bumptech/glide/forks'), ('Branches', '/bumptech/glide/branches'), ('Tags', '/bumptech/glide/tags'), ('Activity', '/bumptech/glide/activity'), ('Star', '/login?return_to=%2Fbumptech%2Fglide'), ('Notifications', '/login?return_to=%2Fbumptech%2Fglide'), ('Code', '/bumptech/glide'), ('Issues527', '/bumptech/glide/issues'), ('Pull requests22', '/bumptech/glide/pulls'), ('Actions', '/bumptech/glide/actions'), ('Projects0', '/bumptech/glide/projects'), ('Wiki', '/bumptech/glide/wiki'), ('Security', '/bumptech/glide/security'), ('Insights', '/bumptech/glide/pulse'), ('Code', '/bumptech/glide'), ('Issues', '/bumptech/glide/issues'), ('Pull requests', '/bumptech/glide/pulls'), ('Actions', '/bumptech/glide/actions'), ('Projects', '/bumptech/glide/projects'), ('Wiki', '/bumptech/glide/wiki'), ('Security', '/bumptech/glide/security'), ('Insights', '/bumptech/glide/pulse'), ('Branches', '/bumptech/glide/branches'), ('Tags', '/bumptech/glide/tags'), ('', '/bumptech/glide/branches'), ('', '/bumptech/glide/tags'), ('2,957 Commits', '/bumptech/glide/commits/master/'), ('', '/bumptech/glide/commits/master/'), ('.github', '/bumptech/glide/tree/master/.github'), ('.github', '/bumptech/glide/tree/master/.github'), ('.idea', '/bumptech/glide/tree/master/.idea'), ('.idea', '/bumptech/glide/tree/master/.idea'), ('annotation', '/bumptech/glide/tree/master/annotation'), ('annotation', '/bumptech/glide/tree/master/annotation'), ('benchmark', '/bumptech/glide/tree/master/benchmark'), ('benchmark', '/bumptech/glide/tree/master/benchmark'), ('exifsamples', '/bumptech/glide/tree/master/exifsamples'), ('exifsamples', '/bumptech/glide/tree/master/exifsamples'), ('glide', '/bumptech/glide/tree/master/glide'), ('glide', '/bumptech/glide/tree/master/glide'), ('gradle/wrapper', '/bumptech/glide/tree/master/gradle/wrapper'), ('gradle/wrapper', '/bumptech/glide/tree/master/gradle/wrapper'), ('instrumentation', '/bumptech/glide/tree/master/instrumentation'), ('instrumentation', '/bumptech/glide/tree/master/instrumentation'), ('integration', '/bumptech/glide/tree/master/integration'), ('integration', '/bumptech/glide/tree/master/integration'), ('library', '/bumptech/glide/tree/master/library'), ('library', '/bumptech/glide/tree/master/library'), ('mocks', '/bumptech/glide/tree/master/mocks'), ('mocks', '/bumptech/glide/tree/master/mocks'), ('samples', '/bumptech/glide/tree/master/samples'), ('samples', '/bumptech/glide/tree/master/samples'), ('scripts', '/bumptech/glide/tree/master/scripts'), ('scripts', '/bumptech/glide/tree/master/scripts'), ('static', '/bumptech/glide/tree/master/static'), ('static', '/bumptech/glide/tree/master/static'), ('testutil', '/bumptech/glide/tree/master/testutil'), ('testutil', '/bumptech/glide/tree/master/testutil'), ('third_party', '/bumptech/glide/tree/master/third_party'), ('third_party', '/bumptech/glide/tree/master/third_party'), ('.gitignore', '/bumptech/glide/blob/master/.gitignore'), ('.gitignore', '/bumptech/glide/blob/master/.gitignore'), ('.gitmodules', '/bumptech/glide/blob/master/.gitmodules'), ('.gitmodules', '/bumptech/glide/blob/master/.gitmodules'), ('CONTRIBUTING.md', '/bumptech/glide/blob/master/CONTRIBUTING.md'), ('CONTRIBUTING.md', '/bumptech/glide/blob/master/CONTRIBUTING.md'), ('ISSUE_TEMPLATE.md', '/bumptech/glide/blob/master/ISSUE_TEMPLATE.md'), ('ISSUE_TEMPLATE.md', '/bumptech/glide/blob/master/ISSUE_TEMPLATE.md'), ('LICENSE', '/bumptech/glide/blob/master/LICENSE'), ('LICENSE', '/bumptech/glide/blob/master/LICENSE'), ('PULL_REQUEST_TEMPLATE.md', '/bumptech/glide/blob/master/PULL_REQUEST_TEMPLATE.md'), ('PULL_REQUEST_TEMPLATE.md', '/bumptech/glide/blob/master/PULL_REQUEST_TEMPLATE.md'), ('README.md', '/bumptech/glide/blob/master/README.md'), ('README.md', '/bumptech/glide/blob/master/README.md'), ('build.gradle', '/bumptech/glide/blob/master/build.gradle'), ('build.gradle', '/bumptech/glide/blob/master/build.gradle'), ('checkstyle.xml', '/bumptech/glide/blob/master/checkstyle.xml'), ('checkstyle.xml', '/bumptech/glide/blob/master/checkstyle.xml'), ('checkstyle_suppressions.xml', '/bumptech/glide/blob/master/checkstyle_suppressions.xml'), ('checkstyle_suppressions.xml', '/bumptech/glide/blob/master/checkstyle_suppressions.xml'), ('debug.keystore', '/bumptech/glide/blob/master/debug.keystore'), ('debug.keystore', '/bumptech/glide/blob/master/debug.keystore'), ('gcloud-bumptech.json.enc', '/bumptech/glide/blob/master/gcloud-bumptech.json.enc'), ('gcloud-bumptech.json.enc', '/bumptech/glide/blob/master/gcloud-bumptech.json.enc'), ('gcloud-sjudd.json.enc', '/bumptech/glide/blob/master/gcloud-sjudd.json.enc'), ('gcloud-sjudd.json.enc', '/bumptech/glide/blob/master/gcloud-sjudd.json.enc'), ('gradle.properties', '/bumptech/glide/blob/master/gradle.properties'), ('gradle.properties', '/bumptech/glide/blob/master/gradle.properties'), ('gradlew', '/bumptech/glide/blob/master/gradlew'), ('gradlew', '/bumptech/glide/blob/master/gradlew'), ('gradlew.bat', '/bumptech/glide/blob/master/gradlew.bat'), ('gradlew.bat', '/bumptech/glide/blob/master/gradlew.bat'), ('renovate.json', '/bumptech/glide/blob/master/renovate.json'), ('renovate.json', '/bumptech/glide/blob/master/renovate.json'), ('settings.gradle', '/bumptech/glide/blob/master/settings.gradle'), ('settings.gradle', '/bumptech/glide/blob/master/settings.gradle'), ('README', '#'), ('License', '#'), ('', '#glide'), ('', 'https://maven-badges.herokuapp.com/maven-central/com.github.bumptech.glide/glide'), (\"View Glide's documentation\", 'https://bumptech.github.io/glide/'), ('简体中文文档', 'https://muyangmin.github.io/glide-docs-cn/'), ('Report an issue with Glide', 'https://github.com/bumptech/glide/blob/master/CONTRIBUTING.md'), ('', '/bumptech/glide/blob/master/static/glide_logo.png'), ('', '#download'), ('download and setup docs page', 'http://bumptech.github.io/glide/doc/download-setup.html'), ('releases page', 'https://github.com/bumptech/glide/releases'), ('Snapshots', 'http://bumptech.github.io/glide/dev/snapshots.html'), ('', '#r8--proguard'), ('already bundled', '/bumptech/glide/blob/master/library/proguard-rules.txt'), ('', '#how-do-i-use-glide'), ('documentation', 'https://bumptech.github.io/glide/'), ('javadocs', 'https://bumptech.github.io/glide/ref/javadocs.html'), ('wiki', 'https://github.com/bumptech/glide/wiki'), ('', '#status'), ('CONTRIBUTING.md', 'https://github.com/bumptech/glide/blob/master/CONTRIBUTING.md'), ('', '#compatibility'), ('Glide v3', 'https://github.com/bumptech/glide/tree/3.0'), ('docs page', 'http://bumptech.github.io/glide/int/okhttp3.html'), ('docs page', 'http://bumptech.github.io/glide/int/volley.html'), ('issues', 'https://github.com/bumptech/glide/issues?q=is%3Aissue+CircleImageView+OR+CircularImageView+OR+RoundedImageView'), ('BitmapTransformation', 'https://github.com/wasabeef/glide-transformations'), ('', '#build'), ('', '#samples'), ('Build', '#build'), ('releases page', 'https://github.com/bumptech/glide/releases'), ('', '#development'), ('Build', '#build'), ('Android Studio', 'https://developer.android.com/studio/index.html'), ('Contributing docs page', 'http://bumptech.github.io/glide/dev/contributing.html'), ('', '#getting-help'), ('open a new issue on Github', 'https://github.com/bumptech/glide/blob/master/CONTRIBUTING.md'), (\"Glide's discussion group\", 'https://groups.google.com/forum/#!forum/glidelibrary'), ('irc.freenode.net#glide-library', 'http://webchat.freenode.net/?channels=glide-library'), ('', '#contributing'), ('individual contributor license agreement', 'https://developers.google.com/open-source/cla/individual'), ('', '#thanks'), ('disk cache implementation', 'https://github.com/JakeWharton/DiskLruCache'), ('GIF decoder gist', 'https://gist.github.com/devunwired/4479231'), ('gradle-mvn-push', 'https://github.com/chrisbanes/gradle-mvn-push'), ('amazing logo', '/bumptech/glide/blob/master/static/glide_logo.png'), ('', '#author'), ('', '#license'), ('LICENSE', 'https://github.com/bumptech/glide/blob/master/LICENSE'), ('', '#disclaimer'), ('bumptech.github.io/glide/', 'https://bumptech.github.io/glide/'), ('android', '/topics/android'), ('gif', '/topics/gif'), ('glide', '/topics/glide'), ('disk-cache', '/topics/disk-cache'), ('imageloader', '/topics/imageloader'), ('Readme', '#readme-ov-file'), ('View license', '#License-1-ov-file'), ('Activity', '/bumptech/glide/activity'), ('Custom properties', '/bumptech/glide/custom-properties'), ('34.6kstars', '/bumptech/glide/stargazers'), ('1kwatching', '/bumptech/glide/watchers'), ('6.1kforks', '/bumptech/glide/forks'), ('Report repository', '/contact/report-content?content_url=https%3A%2F%2Fgithub.com%2Fbumptech%2Fglide&report=bumptech+%28user%29'), ('Releases47', '/bumptech/glide/releases'), ('Glide 5.0.0-rc01, Compose 1.0.0-beta01LatestSep 26, 2023', '/bumptech/glide/releases/tag/v5.0.0-rc01'), ('+ 46 releases', '/bumptech/glide/releases'), ('Packages0', '/orgs/bumptech/packages?repo_name=glide'), ('Contributors148', '/bumptech/glide/graphs/contributors'), ('', 'https://github.com/sjudd'), ('', 'https://github.com/glide-copybara-robot'), ('', 'https://github.com/TWiStErRob'), ('', 'https://github.com/SUPERCILEX'), ('', 'https://github.com/apps/renovate'), ('', 'https://github.com/jnlopar'), ('', 'https://github.com/vigneshvg'), ('', 'https://github.com/kanelbulle'), ('', 'https://github.com/timurrrr'), ('', 'https://github.com/savvasdalkitsis'), ('', 'https://github.com/Muyangmin'), ('', 'https://github.com/nanaze'), ('', 'https://github.com/xian'), ('', 'https://github.com/DavidWiesner'), ('+ 134 contributors', '/bumptech/glide/graphs/contributors'), ('Java92.5%', '/bumptech/glide/search?l=java'), ('Kotlin7.0%', '/bumptech/glide/search?l=kotlin'), ('', 'https://github.com'), ('Terms', 'https://docs.github.com/site-policy/github-terms/github-terms-of-service'), ('Privacy', 'https://docs.github.com/site-policy/privacy-policies/github-privacy-statement'), ('Security', 'https://github.com/security'), ('Status', 'https://www.githubstatus.com/'), ('Docs', 'https://docs.github.com/'), ('Contact', 'https://support.github.com?tags=dotcom-footer')]\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "merge both logic" + ], + "metadata": { + "id": "IIpGhaL1ew7n" + } + }, + { + "cell_type": "code", + "source": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "def scrape_readme(url):\n", + " response = requests.get(url)\n", + "\n", + " # Check if the request was successful\n", + " if response.status_code != 200:\n", + " print(f\"Failed to fetch {url}: {response.status_code}\")\n", + " return None, \"No description found\", [], []\n", + "\n", + " soup = BeautifulSoup(response.text, 'html.parser')\n", + "\n", + " # Extract the title (usually in

    )\n", + " title_tag = soup.find('h1')\n", + " title = title_tag.get_text(strip=True) if title_tag else \"No title found\"\n", + "\n", + " # Find the first

    after the title\n", + " content_paragraphs = soup.find_all('p')\n", + "\n", + " # Extract the description (first

    after title or within a specific section)\n", + " description = soup.find('p').get_text(strip=True)\n", + "\n", + " # Extract all paragraphs (for main content)\n", + "\n", + " content = [para.get_text(strip=True) for para in content_paragraphs]\n", + "\n", + " # Extract links from the README content\n", + " links = []\n", + " for link in soup.find_all('a', href=True):\n", + " links.append((link.get_text(strip=True), link['href']))\n", + "\n", + " return title, description, content, links\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "def scrape_trending_repositories(limit=100): # Set a default limit\n", + " topics_url = 'https://github.com/topics'\n", + " response = requests.get(topics_url)\n", + " content = response.text\n", + "\n", + " doc = BeautifulSoup(content, 'html.parser')\n", + " topic_titles = doc.find_all('p', {'class': 'f3 lh-condensed mb-0 mt-1 Link--primary'})\n", + "\n", + " topic_titles_ = []\n", + " topic_urls = []\n", + "\n", + " for tag in topic_titles:\n", + " topic_titles_.append(tag.text)\n", + " topic_urls.append(\"https://github.com\" + tag.parent.parent.find_all('a', {'class': 'no-underline flex-grow-0'}, href=True)[0]['href'])\n", + "\n", + " df_topics = pd.DataFrame({'topic_title': topic_titles_, 'topic_url': topic_urls})\n", + "\n", + " all_repo_data = []\n", + "\n", + " # Loop through each topic URL to get repository info\n", + " for topic_url in topic_urls:\n", + " response = requests.get(topic_url)\n", + " content = BeautifulSoup(response.text, 'html.parser')\n", + " repositories = content.find_all('h3', {'class': \"f3 color-fg-muted text-normal lh-condensed\"})\n", + "\n", + " for repo in repositories:\n", + " if len(all_repo_data) >= limit: # Check if the limit is reached\n", + " break\n", + "\n", + " user = repo.find_all('a')[0].text.strip()\n", + " repo_name = repo.find_all('a')[1].text.strip()\n", + " repo_url = \"https://github.com\" + repo.find_all('a')[1]['href']\n", + "\n", + " # Get the stars (if available)\n", + " star_tag = repo.find_next('span', {'id': 'repo-stars-counter-star'})\n", + " if star_tag:\n", + " star_text = star_tag.text.strip().replace(',', '')\n", + " if 'k' in star_text:\n", + " star_text = star_text.replace('k', '') # Remove the 'k'\n", + " stars = int(float(star_text) * 1000) # Convert to integer after multiplying by 1000\n", + " else:\n", + " stars = int(float(star_text)) # Convert to integer directly\n", + " else:\n", + " stars = 0\n", + "\n", + " # Scrape the README content for the repository\n", + " readme_title, readme_description, readme_content, readme_links = scrape_readme(repo_url)\n", + "\n", + " # Collect all data in a dictionary\n", + " repo_data = {\n", + " 'username': user,\n", + " 'repo': repo_name,\n", + " 'stars': stars,\n", + " 'repo_url': repo_url,\n", + " 'readme_content': readme_content,\n", + "\n", + "\n", + " 'readme_links': readme_links\n", + " }\n", + " all_repo_data.append(repo_data)\n", + "\n", + " return all_repo_data\n" + ], + "metadata": { + "id": "AgwcOtzYYRc7" + }, + "execution_count": 3, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "df_repos = pd.DataFrame(scrape_trending_repositories())\n", + "df_repos.head()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 3222 + }, + "id": "xIfY2FCDbDFb", + "outputId": "95a98bdf-b716-41b0-a105-290db1a66dd1" + }, + "execution_count": 117, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " username repo stars \\\n", + "0 mrdoob three.js 102000 \n", + "1 pmndrs react-three-fiber 27300 \n", + "2 libgdx libgdx 23300 \n", + "3 BabylonJS Babylon.js 23200 \n", + "4 ssloy tinyrenderer 20400 \n", + "\n", + " repo_url \\\n", + "0 https://github.com/mrdoob/three.js \n", + "1 https://github.com/pmndrs/react-three-fiber \n", + "2 https://github.com/libgdx/libgdx \n", + "3 https://github.com/BabylonJS/Babylon.js \n", + "4 https://github.com/ssloy/tinyrenderer \n", + "\n", + " readme_content \\\n", + "0 [We read every piece of feedback, and take you... \n", + "1 [We read every piece of feedback, and take you... \n", + "2 [We read every piece of feedback, and take you... \n", + "3 [We read every piece of feedback, and take you... \n", + "4 [We read every piece of feedback, and take you... \n", + "\n", + " readme_description \\\n", + "0 We read every piece of feedback, and take your... \n", + "1 We read every piece of feedback, and take your... \n", + "2 We read every piece of feedback, and take your... \n", + "3 We read every piece of feedback, and take your... \n", + "4 We read every piece of feedback, and take your... \n", + "\n", + " readme_links \n", + "0 [(Skip to content, #start-of-content), (, /), ... \n", + "1 [(Skip to content, #start-of-content), (, /), ... \n", + "2 [(Skip to content, #start-of-content), (, /), ... \n", + "3 [(Skip to content, #start-of-content), (, /), ... \n", + "4 [(Skip to content, #start-of-content), (, /), ... " + ], + "text/html": [ + "\n", + "

    \n", + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    usernamerepostarsrepo_urlreadme_contentreadme_descriptionreadme_links
    0mrdoobthree.js102000https://github.com/mrdoob/three.js[We read every piece of feedback, and take you...We read every piece of feedback, and take your...[(Skip to content, #start-of-content), (, /), ...
    1pmndrsreact-three-fiber27300https://github.com/pmndrs/react-three-fiber[We read every piece of feedback, and take you...We read every piece of feedback, and take your...[(Skip to content, #start-of-content), (, /), ...
    2libgdxlibgdx23300https://github.com/libgdx/libgdx[We read every piece of feedback, and take you...We read every piece of feedback, and take your...[(Skip to content, #start-of-content), (, /), ...
    3BabylonJSBabylon.js23200https://github.com/BabylonJS/Babylon.js[We read every piece of feedback, and take you...We read every piece of feedback, and take your...[(Skip to content, #start-of-content), (, /), ...
    4ssloytinyrenderer20400https://github.com/ssloy/tinyrenderer[We read every piece of feedback, and take you...We read every piece of feedback, and take your...[(Skip to content, #start-of-content), (, /), ...
    \n", + "
    \n", + "
    \n", + "\n", + "
    \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
    \n", + "\n", + "\n", + "
    \n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
    \n", + "\n", + "
    \n", + "
    \n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "df_repos", + "summary": "{\n \"name\": \"df_repos\",\n \"rows\": 100,\n \"fields\": [\n {\n \"column\": \"username\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 81,\n \"samples\": [\n \"noelboss\",\n \"mrdoob\",\n \"developit\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"repo\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 100,\n \"samples\": [\n \"scrcpy\",\n \"JavaScript\",\n \"socket\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"stars\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 50334,\n \"min\": 99,\n \"max\": 306000,\n \"num_unique_values\": 92,\n \"samples\": [\n 97000,\n 5200,\n 2800\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"repo_url\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 100,\n \"samples\": [\n \"https://github.com/Genymobile/scrcpy\",\n \"https://github.com/TheAlgorithms/JavaScript\",\n \"https://github.com/amphp/socket\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"readme_content\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"readme_description\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 1,\n \"samples\": [\n \"We read every piece of feedback, and take your input very seriously.\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"readme_links\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 117 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "summarization model\n" + ], + "metadata": { + "id": "Xz46VAs911_I" + } + }, + { + "cell_type": "code", + "source": [ + "from transformers import pipeline\n", + "\n", + "# Load the summarization model\n", + "summarization_model = pipeline(\"summarization\", model=\"facebook/bart-large-cnn\")\n", + "\n", + "# Sample README content as a single string (you can combine from your list)\n", + "readme_content = \"\"\"We read every piece of feedback, and take your input very seriously.\n", + "The aim of the project is to create an easy-to-use, lightweight, cross-browser, general-purpose 3D library.\n", + "The current builds only include a WebGL renderer but WebGPU (experimental), SVG, and CSS3D renderers are also available as addons.\n", + "This code creates a scene, a camera, and a geometric cube, and it adds the cube to the scene.\n", + "It then creates a WebGL renderer for the scene and camera, and it adds that viewport to the document.body element.\n", + "Finally, it animates the cube within the scene for the camera.\n", + "If everything goes well, you should see this.\n", + "Cloning the repo with all its history results in a ~2 GB download.\n", + "If you don't need the whole history you can use the depth parameter to significantly reduce download size.\n", + "JavaScript 3D Library.\"\"\"\n", + "\n", + "# Function to summarize the README content\n", + "def summarize_readme(text):\n", + " # Summarize the text using the summarization model\n", + " summary = summarization_model(text, max_length=300, min_length=30, do_sample=False)\n", + " return summary[0]['summary_text'] # Extract the summary text\n", + "\n", + "# Call the summarization function\n", + "summary = summarize_readme(readme_content)\n", + "print(\"Summary:\")\n", + "print(summary)\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "oAhwWR10xffy", + "outputId": "c002d258-0e2d-496e-8c1c-113bc707912f" + }, + "execution_count": 4, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "/usr/local/lib/python3.10/dist-packages/huggingface_hub/utils/_token.py:89: UserWarning: \n", + "The secret `HF_TOKEN` does not exist in your Colab secrets.\n", + "To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n", + "You will be able to reuse this secret in all of your notebooks.\n", + "Please note that authentication is recommended but still optional to access public models or datasets.\n", + " warnings.warn(\n", + "/usr/local/lib/python3.10/dist-packages/transformers/tokenization_utils_base.py:1601: FutureWarning: `clean_up_tokenization_spaces` was not set. It will be set to `True` by default. This behavior will be depracted in transformers v4.45, and will be then set to `False` by default. For more details check this issue: https://github.com/huggingface/transformers/issues/31884\n", + " warnings.warn(\n", + "Your max_length is set to 300, but your input_length is only 201. Since this is a summarization task, where outputs shorter than the input are typically wanted, you might consider decreasing max_length manually, e.g. summarizer('...', max_length=100)\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Summary:\n", + "The aim of the project is to create an easy-to-use, lightweight, cross-browser, general-purpose 3D library. Current builds only include a WebGL renderer but WebGPU (experimental), SVG, and CSS3D renderers are also available as addons.\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "#merge this logic" + ], + "metadata": { + "id": "dQStsnBF1HoH" + }, + "execution_count": 121, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# Function to summarize the README content\n", + "def summarize_readme(content):\n", + " if not content:\n", + " return \"No content to summarize.\"\n", + "\n", + " # Join all paragraphs to form a single string\n", + " full_text = \" \".join(content)\n", + "\n", + " # Check if the length of the full text exceeds a reasonable length\n", + " max_length = 1024 # Set a limit for the summarization model\n", + " if len(full_text) > max_length:\n", + " full_text = full_text[:max_length] # Truncate the text\n", + "\n", + " try:\n", + " # Summarize the text using the summarization model\n", + " summary = summarization_model(full_text, max_length=130, min_length=30, do_sample=False)\n", + " return summary[0]['summary_text'] # Extract the summary text\n", + " except Exception as e:\n", + " print(f\"Error during summarization: {e}\")\n", + " return \"Error occurred during summarization.\"\n", + "\n", + "# The rest of your existing code follows here...\n" + ], + "metadata": { + "id": "5JvYcAJZ1_6R" + }, + "execution_count": 5, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def scrape_readme(url):\n", + " response = requests.get(url)\n", + "\n", + " # Check if the request was successful\n", + " if response.status_code != 200:\n", + " print(f\"Failed to fetch {url}: {response.status_code}\")\n", + " return None, \"No description found\", [], []\n", + "\n", + " soup = BeautifulSoup(response.text, 'html.parser')\n", + "\n", + " # Extract the title (usually in

    )\n", + " title_tag = soup.find('h1')\n", + " title = title_tag.get_text(strip=True) if title_tag else \"No title found\"\n", + "\n", + " # Find the first

    after the title\n", + " content_paragraphs = soup.find_all('p')\n", + "\n", + " # Extract the description (first

    after title)\n", + " description = soup.find('p').get_text(strip=True) if soup.find('p') else \"No description found\"\n", + "\n", + " # Extract all paragraphs for main content\n", + " content = [para.get_text(strip=True) for para in content_paragraphs]\n", + "\n", + " # Extract links from the README content\n", + " links = []\n", + " for link in soup.find_all('a', href=True):\n", + " links.append((link.get_text(strip=True), link['href']))\n", + "\n", + " return title, description, content, links\n", + "\n" + ], + "metadata": { + "id": "91Ctgwym-POF" + }, + "execution_count": 6, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "# Scrape the trending repositories and extract README summaries\n", + "def scrape_trending_repositories(limit=10): # Set a default limit\n", + " topics_url = 'https://github.com/topics'\n", + " response = requests.get(topics_url)\n", + " content = response.text\n", + "\n", + " doc = BeautifulSoup(content, 'html.parser')\n", + " topic_titles = doc.find_all('p', {'class': 'f3 lh-condensed mb-0 mt-1 Link--primary'})\n", + "\n", + " topic_titles_ = []\n", + " topic_urls = []\n", + "\n", + " for tag in topic_titles:\n", + " topic_titles_.append(tag.text)\n", + " topic_urls.append(\"https://github.com\" + tag.parent.parent.find_all('a', {'class': 'no-underline flex-grow-0'}, href=True)[0]['href'])\n", + "\n", + " all_repo_data = []\n", + "\n", + " # Loop through each topic URL to get repository info\n", + " for topic_url in topic_urls:\n", + " response = requests.get(topic_url)\n", + " content = BeautifulSoup(response.text, 'html.parser')\n", + " repositories = content.find_all('h3', {'class': \"f3 color-fg-muted text-normal lh-condensed\"})\n", + "\n", + " for repo in repositories:\n", + " if len(all_repo_data) >= limit: # Check if the limit is reached\n", + " break\n", + "\n", + " user = repo.find_all('a')[0].text.strip()\n", + " repo_name = repo.find_all('a')[1].text.strip()\n", + " repo_url = \"https://github.com\" + repo.find_all('a')[1]['href']\n", + "\n", + " # Get the stars (if available)\n", + " star_tag = repo.find_next('span', {'id': 'repo-stars-counter-star'})\n", + " if star_tag:\n", + " star_text = star_tag.text.strip().replace(',', '')\n", + " if 'k' in star_text:\n", + " star_text = star_text.replace('k', '') # Remove the 'k'\n", + " stars = int(float(star_text) * 1000) # Convert to integer after multiplying by 1000\n", + " else:\n", + " stars = int(float(star_text)) # Convert directly to integer\n", + " else:\n", + " stars = 0\n", + "\n", + " # Scrape the README content for the repository\n", + " readme_title, readme_description, readme_content, readme_links = scrape_readme(repo_url)\n", + "\n", + " # Summarize the README content\n", + " readme_summary = summarize_readme(readme_content)\n", + "\n", + " # Collect all data in a dictionary\n", + " repo_data = {\n", + " 'username': user,\n", + " 'repo': repo_name,\n", + " 'stars': stars,\n", + " 'repo_url': repo_url,\n", + " 'readme_content': readme_content,\n", + " 'readme_summary': readme_summary,\n", + " 'readme_links': readme_links\n", + " }\n", + " all_repo_data.append(repo_data)\n", + "\n", + " return all_repo_data\n", + "\n", + "# Execute the scraping and save to CSV\n", + "repo_data = scrape_trending_repositories()\n", + "df_repos = pd.DataFrame(repo_data)\n", + "df_repos.to_csv('trending_repositories_with_readme_summary.csv', index=False)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ezO1ZiIL2C46", + "outputId": "40ba8bb9-b96d-455c-803c-6b96ca3300af" + }, + "execution_count": 8, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Your max_length is set to 130, but your input_length is only 125. Since this is a summarization task, where outputs shorter than the input are typically wanted, you might consider decreasing max_length manually, e.g. summarizer('...', max_length=62)\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "df_repos.head()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 3222 + }, + "id": "jiUyQk3j2TfO", + "outputId": "a40c9d06-7bdd-4bfd-c0f6-99d9b9479b1b" + }, + "execution_count": 9, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " username repo stars \\\n", + "0 mrdoob three.js 102000 \n", + "1 pmndrs react-three-fiber 27300 \n", + "2 libgdx libgdx 23300 \n", + "3 BabylonJS Babylon.js 23200 \n", + "4 ssloy tinyrenderer 20400 \n", + "\n", + " repo_url \\\n", + "0 https://github.com/mrdoob/three.js \n", + "1 https://github.com/pmndrs/react-three-fiber \n", + "2 https://github.com/libgdx/libgdx \n", + "3 https://github.com/BabylonJS/Babylon.js \n", + "4 https://github.com/ssloy/tinyrenderer \n", + "\n", + " readme_content \\\n", + "0 [We read every piece of feedback, and take you... \n", + "1 [We read every piece of feedback, and take you... \n", + "2 [We read every piece of feedback, and take you... \n", + "3 [We read every piece of feedback, and take you... \n", + "4 [We read every piece of feedback, and take you... \n", + "\n", + " readme_summary \\\n", + "0 The aim of the project is to create an easy-to... \n", + "1 react-three-fiber is aReact rendererfor three... \n", + "2 libGDX is a cross-platform Java game developm... \n", + "3 WARNING: The CDN should not be used in product... \n", + "4 Gitpod is a free online dev evironment for Git... \n", + "\n", + " readme_links \n", + "0 [(Skip to content, #start-of-content), (, /), ... \n", + "1 [(Skip to content, #start-of-content), (, /), ... \n", + "2 [(Skip to content, #start-of-content), (, /), ... \n", + "3 [(Skip to content, #start-of-content), (, /), ... \n", + "4 [(Skip to content, #start-of-content), (, /), ... " + ], + "text/html": [ + "\n", + "

    \n", + "
    \n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
    usernamerepostarsrepo_urlreadme_contentreadme_summaryreadme_links
    0mrdoobthree.js102000https://github.com/mrdoob/three.js[We read every piece of feedback, and take you...The aim of the project is to create an easy-to...[(Skip to content, #start-of-content), (, /), ...
    1pmndrsreact-three-fiber27300https://github.com/pmndrs/react-three-fiber[We read every piece of feedback, and take you...react-three-fiber is aReact rendererfor three...[(Skip to content, #start-of-content), (, /), ...
    2libgdxlibgdx23300https://github.com/libgdx/libgdx[We read every piece of feedback, and take you...libGDX is a cross-platform Java game developm...[(Skip to content, #start-of-content), (, /), ...
    3BabylonJSBabylon.js23200https://github.com/BabylonJS/Babylon.js[We read every piece of feedback, and take you...WARNING: The CDN should not be used in product...[(Skip to content, #start-of-content), (, /), ...
    4ssloytinyrenderer20400https://github.com/ssloy/tinyrenderer[We read every piece of feedback, and take you...Gitpod is a free online dev evironment for Git...[(Skip to content, #start-of-content), (, /), ...
    \n", + "
    \n", + "
    \n", + "\n", + "
    \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
    \n", + "\n", + "\n", + "
    \n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
    \n", + "\n", + "
    \n", + "
    \n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "df_repos", + "summary": "{\n \"name\": \"df_repos\",\n \"rows\": 10,\n \"fields\": [\n {\n \"column\": \"username\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 10,\n \"samples\": [\n \"blender\",\n \"pmndrs\",\n \"FreeCAD\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"repo\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 10,\n \"samples\": [\n \"blender\",\n \"react-three-fiber\",\n \"FreeCAD\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"stars\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 26541,\n \"min\": 12800,\n \"max\": 102000,\n \"num_unique_values\": 10,\n \"samples\": [\n 13000,\n 27300,\n 19500\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"repo_url\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 10,\n \"samples\": [\n \"https://github.com/blender/blender\",\n \"https://github.com/pmndrs/react-three-fiber\",\n \"https://github.com/FreeCAD/FreeCAD\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"readme_content\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"readme_summary\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 10,\n \"samples\": [\n \"Blender is the free and open source 3D creation suite. It supports the entirety of the 3D pipeline-modeling, rigging, animation, simulation, rendering, compositing,motion tracking and video editing.\",\n \" react-three-fiber is aReact rendererfor threejs. Build your scene declaratively with re-usable, self-contained components that react to state. It outperforms Threejs in scale due to React's scheduling abilities.\",\n \"FreeCAD is an open-source parametric 3D modeler made primarily to design real-life objects of any size. Parametric modeling allows you to easily modify your design by going back into your model history to change parameters.\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"readme_links\",\n \"properties\": {\n \"dtype\": \"object\",\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 9 + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "S-6SGBDd2reY" + }, + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file From 3bd1dcdf6e695103f7e8ccbc046c83c17e2f75da Mon Sep 17 00:00:00 2001 From: BHARDWAJ Date: Wed, 23 Oct 2024 20:30:20 +0530 Subject: [PATCH 59/73] add nav bar to the contact section --- frontend/contact.html | 407 +++++++++++++++++++++++++++--------------- 1 file changed, 268 insertions(+), 139 deletions(-) diff --git a/frontend/contact.html b/frontend/contact.html index 023e77a..0a077d0 100644 --- a/frontend/contact.html +++ b/frontend/contact.html @@ -1,158 +1,251 @@ + Contact Us - + - + -

    +
    +
    + + From ad9c5a0b6efc8f3e34545017c83b7b1d6e685358 Mon Sep 17 00:00:00 2001 From: DEEPANSHU BAGHEL <92099428+deepanshubaghel@users.noreply.github.com> Date: Wed, 23 Oct 2024 21:10:23 +0530 Subject: [PATCH 60/73] Twitter-Bot Added --- Twitter-Bot/README.md | 23 ++++++++++++ Twitter-Bot/config.py | 17 +++++++++ Twitter-Bot/credientials.py | 4 ++ Twitter-Bot/daily_tweets.png | Bin 0 -> 61780 bytes Twitter-Bot/result.png | Bin 0 -> 15967 bytes Twitter-Bot/twitterapp.py | 70 +++++++++++++++++++++++++++++++++++ 6 files changed, 114 insertions(+) create mode 100644 Twitter-Bot/README.md create mode 100644 Twitter-Bot/config.py create mode 100644 Twitter-Bot/credientials.py create mode 100644 Twitter-Bot/daily_tweets.png create mode 100644 Twitter-Bot/result.png create mode 100644 Twitter-Bot/twitterapp.py diff --git a/Twitter-Bot/README.md b/Twitter-Bot/README.md new file mode 100644 index 0000000..a9f7247 --- /dev/null +++ b/Twitter-Bot/README.md @@ -0,0 +1,23 @@ +# Twitter-Bot + +## Required Dependiencies + - Python 3.5 or above + - Tweepy + - And [Twitter developer account](developers.twitter.com) + - Get the Four keys from the developer account and update on the credientials.py file. + + ## Uses + - You can search for a hashtag and like,retweet,follow the users who tweeted. + - You can tweet on regularly basic by updating the format on the twitterapp.py file. + + ![daily_tweet](daily_tweets.png) + + - you can change your permissions by modifying config.py file. + - Change the SLEEP_TIME in config.py file to your need. + + ## To run + - Run the twitterapp.py file after updating the config.py and credientials.py file. + + ## Result + + ![result](result.png) diff --git a/Twitter-Bot/config.py b/Twitter-Bot/config.py new file mode 100644 index 0000000..6a9a83a --- /dev/null +++ b/Twitter-Bot/config.py @@ -0,0 +1,17 @@ +# replace the hastag with your own. +QUERY = "# twitter" + +# True if you need to like if you dont want to like the tweet give False +LIKE = True + +# True if you need to follow if you dont want to follow the tweet give False +FOLLOW = True + +# It is used to make your bot do the same in a repeated time constraint give the value more for sleeep_time. +SLEEP_TIME = 500 + +# True if you need to retweet if you dont want to retweet the tweet give False +RETWEET = True + +# True if you need to tweet daily if you dont want to tweet daily the tweet give False +EVERYDAY_TWEETS = True diff --git a/Twitter-Bot/credientials.py b/Twitter-Bot/credientials.py new file mode 100644 index 0000000..e83230a --- /dev/null +++ b/Twitter-Bot/credientials.py @@ -0,0 +1,4 @@ +CONSUMER_KEY = "ycFglnQqD8mxeSksv1tEOLhL2" +CONSUMER_SECRET = "tI9rnjB4IvxpQ9PafQUaxYHmHBYHIDrRFYUZzH9unXEeirLPJi" +ACCESS_KEY = "1182456728199106560-SyYxjrpHwzkD0Qoh2RGYqoNPvPjkAp" +ACCESS_SECRET = "LZJTF4biXjOAvwYpef2xCsibTWGQ3byx0T7KmeXi9mghS" diff --git a/Twitter-Bot/daily_tweets.png b/Twitter-Bot/daily_tweets.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7b7ec6571bc6f763423ee98ce495760c434fb8 GIT binary patch literal 61780 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 literal 0 HcmV?d00001 diff --git a/Twitter-Bot/result.png b/Twitter-Bot/result.png new file mode 100644 index 0000000000000000000000000000000000000000..e24b9c14b1d2e520cbf997e8eb9e78b35dbabab7 GIT binary patch literal 15967 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 Date: Wed, 23 Oct 2024 21:15:00 +0530 Subject: [PATCH 61/73] added icons on navbar --- frontend/image/contact_us.jpg | Bin 0 -> 9584 bytes frontend/image/features.png | Bin 0 -> 17798 bytes frontend/image/setup.png | Bin 0 -> 15746 bytes frontend/index.html | 12 +++++++++--- frontend/style.css | 6 ++++++ 5 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 frontend/image/contact_us.jpg create mode 100644 frontend/image/features.png create mode 100644 frontend/image/setup.png diff --git a/frontend/image/contact_us.jpg b/frontend/image/contact_us.jpg new file mode 100644 index 0000000000000000000000000000000000000000..020e8ce543ef51e52ee341f81ff45bbcfa1a3971 GIT binary patch literal 9584 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 literal 0 HcmV?d00001 diff --git a/frontend/image/features.png b/frontend/image/features.png new file mode 100644 index 0000000000000000000000000000000000000000..49e73af872b3cf71e850c00704e8e21b63f7054f GIT binary patch literal 17798 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 literal 0 HcmV?d00001 diff --git a/frontend/image/setup.png b/frontend/image/setup.png new file mode 100644 index 0000000000000000000000000000000000000000..2421bc664707dbd2cdcbc1b326e86fc0a820e589 GIT binary patch literal 15746 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
    diff --git a/frontend/style.css b/frontend/style.css index 757f37b..5bf999d 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -57,6 +57,11 @@ body { margin-right: 10px; } +.icon1{ + height: 40px; + width: 50px; +} + nav { background-color: var(--color4); display: flex; @@ -88,6 +93,7 @@ nav ul { nav ul li { margin: 0 10px; /* Add margin for spacing */ + display: flex; } nav ul li a { From d09d394e35366c0b556253c4e048e38bf5748614 Mon Sep 17 00:00:00 2001 From: Deanne Vaz Date: Thu, 24 Oct 2024 00:06:02 +0530 Subject: [PATCH 62/73] Add files via upload --- Personal Finance Tracker/README.md | 27 +++++ Personal Finance Tracker/finance_tracker.py | 128 ++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 Personal Finance Tracker/README.md create mode 100644 Personal Finance Tracker/finance_tracker.py diff --git a/Personal Finance Tracker/README.md b/Personal Finance Tracker/README.md new file mode 100644 index 0000000..6a5193e --- /dev/null +++ b/Personal Finance Tracker/README.md @@ -0,0 +1,27 @@ +# Personal Finance Assistant + +## Overview + +The Personal Finance Assistant is a voice-activated tool designed to help users manage their personal finances more effectively. Utilizing speech recognition and text-to-speech technology, this assistant allows users to log expenses, set budgets, and check their financial status hands-free. The application stores data persistently, ensuring users can track their financial activities over time. + +## What I've Done + +In this project, I have developed a voice-activated assistant that performs the following functions: +- **Log Expenses**: Users can verbally log their expenses by providing a category and amount. +- **Set Budgets**: Users can establish budgets for various categories, helping them stay on track financially. +- **Check Budgets**: The assistant can provide updates on remaining budget amounts and notify users if they exceed their budgets. +- **Voice Interaction**: The assistant communicates with users through text-to-speech, offering an interactive experience. +- **Data Persistence**: Expense and budget information is saved in a JSON file, allowing data to persist across sessions. + +## Libraries Needed + +To run the Personal Finance Assistant, you will need the following Python libraries: + +- `pyttsx3`: For converting text to speech. +- `speech_recognition`: For recognizing spoken commands. +- `json`: For handling data storage in JSON format. +- `os`: For file operations to manage data files. + +## Conclusion + +The Personal Finance Assistant is a simple yet effective tool for anyone looking to improve their financial management through voice interaction. By leveraging modern technologies like speech recognition and data persistence, this assistant aims to make personal finance tracking more accessible and engaging. \ No newline at end of file diff --git a/Personal Finance Tracker/finance_tracker.py b/Personal Finance Tracker/finance_tracker.py new file mode 100644 index 0000000..4326348 --- /dev/null +++ b/Personal Finance Tracker/finance_tracker.py @@ -0,0 +1,128 @@ +import asyncio +import pyttsx3 +import speech_recognition as sr +import json +import os + +# Initialize TTS engine +engine = pyttsx3.init() +engine.setProperty('rate', 150) + +# File to store expenses and budgets +DATA_FILE = "finance_data.json" + +# Global variables to store expenses and budgets +expenses = {} +budgets = {} + +# Load data from file +def load_data(): + global expenses, budgets + if os.path.exists(DATA_FILE): + try: + with open(DATA_FILE, 'r') as f: + data = json.load(f) + expenses = data.get("expenses", {}) + budgets = data.get("budgets", {}) + except json.JSONDecodeError: + expenses = {} + budgets = {} + print("Warning: Data file is corrupted. Starting fresh.") + +# Save data to file +def save_data(): + with open(DATA_FILE, 'w') as f: + json.dump({"expenses": expenses, "budgets": budgets}, f) + +# Function to convert text to speech asynchronously +async def speak_async(text): + engine.say(text) + engine.runAndWait() + await asyncio.sleep(0.5) + +# Function to get user input through speech recognition +async def voice_to_text_async(): + recognizer = sr.Recognizer() + await asyncio.sleep(0.5) + with sr.Microphone() as source: + print("Listening for your command...") + try: + audio = recognizer.listen(source, timeout=10) + command = recognizer.recognize_google(audio) + return command.lower() + except sr.UnknownValueError: + await speak_async("I didn't catch that. Could you please repeat?") + return None + except sr.RequestError: + await speak_async("The speech recognition service is unavailable at the moment.") + return None + +# Function to log expenses +async def log_expense(category, amount): + if category not in expenses: + expenses[category] = [] + expenses[category].append(amount) + save_data() # Save data after logging + await speak_async(f"Logged {amount} dollars for {category}.") + +# Function to set budget +async def set_budget(category, amount): + budgets[category] = amount + save_data() # Save data after setting budget + await speak_async(f"Set {category} budget to {amount} dollars.") + +# Function to check budgets +async def check_budget(): + for category, budget in budgets.items(): + total_expense = sum(expenses.get(category, [])) + remaining = budget - total_expense + if remaining < 0: + await speak_async(f"You have exceeded your budget for {category} by {-remaining} dollars.") + else: + await speak_async(f"You have {remaining} dollars left in your budget for {category}.") + +# Function to provide help +async def provide_help(): + await speak_async("You can log expenses by saying 'Log expense [category] [amount]', set budgets by saying 'Set budget [category] [amount]', and check budgets by saying 'Check budget'. To exit, say 'exit'.") + +# Main function for the assistant +async def main(): + load_data() # Load existing data at startup + await speak_async("Welcome to your personal finance assistant! How can I assist you today?") + + while True: + command = await voice_to_text_async() + + if command: + if "log expense" in command: + parts = command.split() + if len(parts) == 4 and parts[1] == "expense": + category = parts[2] + try: + amount = float(parts[3]) + await log_expense(category, amount) + except ValueError: + await speak_async("Please provide a valid amount.") + + elif "set budget" in command: + parts = command.split() + if len(parts) == 4 and parts[1] == "budget": + category = parts[2] + try: + amount = float(parts[3]) + await set_budget(category, amount) + except ValueError: + await speak_async("Please provide a valid budget amount.") + + elif "check budget" in command: + await check_budget() + + elif "help" in command: + await provide_help() + + elif "exit" in command: + await speak_async("Goodbye!") + break + +if __name__ == "__main__": + asyncio.run(main()) From f7b738352871b2f743cad163d3d78d85e6abf45c Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:11:19 +0530 Subject: [PATCH 63/73] Create gcd.py --- Simple-Python-Algorithms/gcd.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Simple-Python-Algorithms/gcd.py diff --git a/Simple-Python-Algorithms/gcd.py b/Simple-Python-Algorithms/gcd.py new file mode 100644 index 0000000..bf2d631 --- /dev/null +++ b/Simple-Python-Algorithms/gcd.py @@ -0,0 +1,9 @@ +def gcd(a, b): + while b: + a, b = b, a % b + return a + +# Get user input +a = int(input("Enter the first number: ")) +b = int(input("Enter the second number: ")) +print(f"The GCD of {a} and {b} is: {gcd(a, b)}") From cb39edb0fc6b7c139f580a7200a1bdcd9756b996 Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:13:57 +0530 Subject: [PATCH 64/73] Create lcm.py --- Simple-Python-Algorithms/lcm.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Simple-Python-Algorithms/lcm.py diff --git a/Simple-Python-Algorithms/lcm.py b/Simple-Python-Algorithms/lcm.py new file mode 100644 index 0000000..df1f957 --- /dev/null +++ b/Simple-Python-Algorithms/lcm.py @@ -0,0 +1,12 @@ +def gcd(a, b): + while b: + a, b = b, a % b + return a + +def lcm(a, b): + return abs(a * b) // gcd(a, b) + +# Get user input +a = int(input("Enter the first number: ")) +b = int(input("Enter the second number: ")) +print(f"The LCM of {a} and {b} is: {lcm(a, b)}") From c5e8961fb917cf4409ecd39099db79c69194fdbb Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:14:30 +0530 Subject: [PATCH 65/73] Create sieve_of_eratosthenes.py --- Simple-Python-Algorithms/sieve_of_eratosthenes.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Simple-Python-Algorithms/sieve_of_eratosthenes.py diff --git a/Simple-Python-Algorithms/sieve_of_eratosthenes.py b/Simple-Python-Algorithms/sieve_of_eratosthenes.py new file mode 100644 index 0000000..79da01b --- /dev/null +++ b/Simple-Python-Algorithms/sieve_of_eratosthenes.py @@ -0,0 +1,15 @@ +def sieve_of_eratosthenes(n): + primes = [] + is_prime = [True] * (n + 1) + is_prime[0] = is_prime[1] = False + + for i in range(2, n + 1): + if is_prime[i]: + primes.append(i) + for j in range(i * i, n + 1, i): + is_prime[j] = False + return primes + +# Get user input +n = int(input("Enter the upper limit to find prime numbers: ")) +print(f"Prime numbers up to {n} are: {sieve_of_eratosthenes(n)}") From 623ac66f95a653d4d695c82bcfe30da36718b291 Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:15:14 +0530 Subject: [PATCH 66/73] Create exponentiation_by_squaring.py --- .../exponentiation_by_squaring.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Simple-Python-Algorithms/exponentiation_by_squaring.py diff --git a/Simple-Python-Algorithms/exponentiation_by_squaring.py b/Simple-Python-Algorithms/exponentiation_by_squaring.py new file mode 100644 index 0000000..762713c --- /dev/null +++ b/Simple-Python-Algorithms/exponentiation_by_squaring.py @@ -0,0 +1,12 @@ +def exponentiation_by_squaring(base, exp): + if exp < 0: + return 1 / exponentiation_by_squaring(base, -exp) + if exp == 0: + return 1 + half = exponentiation_by_squaring(base, exp // 2) + return half * half if exp % 2 == 0 else base * half * half + +# Get user input +base = float(input("Enter the base: ")) +exp = int(input("Enter the exponent: ")) +print(f"{base} raised to the power {exp} is: {exponentiation_by_squaring(base, exp)}") From 2d89dea7f08bae12e3ef7dc045e69151b8b544ee Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:15:33 +0530 Subject: [PATCH 67/73] Create binary_exponentiation.py --- Simple-Python-Algorithms/binary_exponentiation.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Simple-Python-Algorithms/binary_exponentiation.py diff --git a/Simple-Python-Algorithms/binary_exponentiation.py b/Simple-Python-Algorithms/binary_exponentiation.py new file mode 100644 index 0000000..c8c107c --- /dev/null +++ b/Simple-Python-Algorithms/binary_exponentiation.py @@ -0,0 +1,13 @@ +def binary_exponentiation(base, exp): + result = 1 + while exp > 0: + if exp % 2 == 1: + result *= base + base *= base + exp //= 2 + return result + +# Get user input +base = float(input("Enter the base: ")) +exp = int(input("Enter the exponent: ")) +print(f"{base} raised to the power {exp} is: {binary_exponentiation(base, exp)}") From a834f95792215f14e68d27f64e988e81fef6410f Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:15:54 +0530 Subject: [PATCH 68/73] Create flood_fill.py --- Simple-Python-Algorithms/flood_fill.py | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Simple-Python-Algorithms/flood_fill.py diff --git a/Simple-Python-Algorithms/flood_fill.py b/Simple-Python-Algorithms/flood_fill.py new file mode 100644 index 0000000..2feb8d7 --- /dev/null +++ b/Simple-Python-Algorithms/flood_fill.py @@ -0,0 +1,36 @@ +def flood_fill(image, sr, sc, new_color): + original_color = image[sr][sc] + if original_color == new_color: + return image + + def fill(r, c): + if r < 0 or r >= len(image) or c < 0 or c >= len(image[0]): + return + if image[r][c] != original_color: + return + + image[r][c] = new_color + fill(r + 1, c) + fill(r - 1, c) + fill(r, c + 1) + fill(r, c - 1) + + fill(sr, sc) + return image + +# Get user input +rows = int(input("Enter the number of rows in the image: ")) +cols = int(input("Enter the number of columns in the image: ")) +image = [] +print("Enter the image row by row (space-separated values):") +for _ in range(rows): + image.append(list(map(int, input().split()))) + +sr = int(input("Enter the starting row: ")) +sc = int(input("Enter the starting column: ")) +new_color = int(input("Enter the new color: ")) + +flood_fill(image, sr, sc, new_color) +print("Updated image after flood fill:") +for row in image: + print(row) From 7ab5306bd2f4228a33f4d677f07b55f9fbd5d968 Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:16:13 +0530 Subject: [PATCH 69/73] Create two_pointer.py --- Simple-Python-Algorithms/two_pointer.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Simple-Python-Algorithms/two_pointer.py diff --git a/Simple-Python-Algorithms/two_pointer.py b/Simple-Python-Algorithms/two_pointer.py new file mode 100644 index 0000000..1611e05 --- /dev/null +++ b/Simple-Python-Algorithms/two_pointer.py @@ -0,0 +1,21 @@ +def two_pointer(arr, target): + left, right = 0, len(arr) - 1 + while left < right: + current_sum = arr[left] + arr[right] + if current_sum == target: + return (arr[left], arr[right]) + elif current_sum < target: + left += 1 + else: + right -= 1 + return None + +# Get user input +arr = list(map(int, input("Enter sorted numbers separated by spaces: ").split())) +target = int(input("Enter the target sum: ")) +result = two_pointer(arr, target) + +if result: + print(f"The pair that sums to {target} is: {result}") +else: + print("No pair found.") From 4fef74e7b2171146350e0702eae600f94a755694 Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:16:32 +0530 Subject: [PATCH 70/73] Create sliding_window.py --- Simple-Python-Algorithms/sliding_window.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Simple-Python-Algorithms/sliding_window.py diff --git a/Simple-Python-Algorithms/sliding_window.py b/Simple-Python-Algorithms/sliding_window.py new file mode 100644 index 0000000..428f64e --- /dev/null +++ b/Simple-Python-Algorithms/sliding_window.py @@ -0,0 +1,14 @@ +def max_sum_subarray(arr, k): + max_sum = sum(arr[:k]) + window_sum = max_sum + + for i in range(len(arr) - k): + window_sum = window_sum - arr[i] + arr[i + k] + max_sum = max(max_sum, window_sum) + + return max_sum + +# Get user input +arr = list(map(int, input("Enter numbers separated by spaces: ").split())) +k = int(input("Enter the size of the subarray: ")) +print(f"The maximum sum of a subarray of size {k} is: {max_sum_subarray(arr, k)}") From 7847dae01a52751d3a485370a480eb45df0f262a Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:16:53 +0530 Subject: [PATCH 71/73] Create kadane.py --- Simple-Python-Algorithms/kadane.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Simple-Python-Algorithms/kadane.py diff --git a/Simple-Python-Algorithms/kadane.py b/Simple-Python-Algorithms/kadane.py new file mode 100644 index 0000000..fec777f --- /dev/null +++ b/Simple-Python-Algorithms/kadane.py @@ -0,0 +1,13 @@ +def kadane(arr): + max_current = max_global = arr[0] + + for i in range(1, len(arr)): + max_current = max(arr[i], max_current + arr[i]) + if max_current > max_global: + max_global = max_current + + return max_global + +# Get user input +arr = list(map(int, input("Enter numbers separated by spaces: ").split())) +print(f"The maximum subarray sum is: {kadane(arr)}") From d24f6efc32fbf220f92ae9e7f12438dcad789306 Mon Sep 17 00:00:00 2001 From: ANIRUDDHA ADAK Date: Thu, 24 Oct 2024 00:17:12 +0530 Subject: [PATCH 72/73] Create longest_common_subsequence.py --- .../longest_common_subsequence.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Simple-Python-Algorithms/longest_common_subsequence.py diff --git a/Simple-Python-Algorithms/longest_common_subsequence.py b/Simple-Python-Algorithms/longest_common_subsequence.py new file mode 100644 index 0000000..e67ba49 --- /dev/null +++ b/Simple-Python-Algorithms/longest_common_subsequence.py @@ -0,0 +1,19 @@ +def lcs(X, Y): + m, n = len(X), len(Y) + dp = [[0] * (n + 1) for _ in range(m + 1)] + + for i in range(m + 1): + for j in range(n + 1): + if i == 0 or j == 0: + dp[i][j] = 0 + elif X[i - 1] == Y[j - 1]: + dp[i][j] = dp[i - 1][j - 1] + 1 + else: + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + + return dp[m][n] + +# Get user input +X = input("Enter the first string: ") +Y = input("Enter the second string: ") +print(f"The length of the longest common subsequence is: {lcs(X, Y)}") From b952f4b13ef0a87e722c1954459c949ef4810b71 Mon Sep 17 00:00:00 2001 From: Amiya Singh Date: Fri, 25 Oct 2024 00:30:53 +0530 Subject: [PATCH 73/73] Update README.md added Stargazers and Forkers section to readme.md --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index b4db589..f751cca 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,27 @@ We are grateful to all the contributors who have helped improve this project. Yo Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes. + +![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png) + +## Stargazers ❤️ + +
    + +[![Stargazers repo roster for @suryanshsk/Python-Voice-Assistant-Suryanshsk](https://reporoster.com/stars/dark/suryanshsk/Python-Voice-Assistant-Suryanshsk)](https://github.com/suryanshsk/Python-Voice-Assistant-Suryanshsk/stargazers) + + +
    + +## Forkers ❤️ + +[![Forkers repo roster for @suryanshsk/Python-Voice-Assistant-Suryanshsk](https://reporoster.com/forks/dark/suryanshsk/Python-Voice-Assistant-Suryanshsk)](https://github.com/suryanshsk/Python-Voice-Assistant-Suryanshsk/network/members) + + +![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png) + + + ## Contact For questions or feedback, reach out to [suryanshskcontact@gmail.com](mailto:suryanshskcontact@gmail.com).