diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 00000000..5ca7c97a
Binary files /dev/null and b/.DS_Store differ
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/Python-Projects.iml b/.idea/Python-Projects.iml
new file mode 100644
index 00000000..07abf202
--- /dev/null
+++ b/.idea/Python-Projects.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+  <component name="PyDocumentationSettings">
+    <option name="format" value="PLAIN" />
+    <option name="myDocStringFormat" value="Plain" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..dc64fad4
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,26 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <option name="ignoredErrors">
+        <list>
+          <option value="E225" />
+        </list>
+      </option>
+    </inspection_tool>
+    <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <option name="ignoredErrors">
+        <list>
+          <option value="N802" />
+        </list>
+      </option>
+    </inspection_tool>
+    <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoredIdentifiers">
+        <list>
+          <option value="main.elseif" />
+        </list>
+      </option>
+    </inspection_tool>
+  </profile>
+</component>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 00000000..105ce2da
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..db8786c0
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Black">
+    <option name="sdkName" value="Python 3.12" />
+  </component>
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..c1b104bb
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/Python-Projects.iml" filepath="$PROJECT_DIR$/.idea/Python-Projects.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/AI_Attendence_Program/readme.md b/AI_Attendence_Program/readme.md
new file mode 100644
index 00000000..9880ef10
--- /dev/null
+++ b/AI_Attendence_Program/readme.md
@@ -0,0 +1,36 @@
+
+## Face Recognition Attendance System
+
+This is a Python script that uses the OpenCV and face_recognition libraries to create a simple face recognition attendance system. It captures images from a camera, recognizes faces, and logs attendance in a CSV file.
+
+
+## Prerequisites
+
+Before running the code, you need to install the required Python libraries. You can install them using pip:
+
+- pip install opencv-python
+- pip install numpy
+- pip install face-recognition
+
+
+## Usage
+
+- Create a folder named 'Images' in the same directory as this script.
+- Add images of the individuals you want to recognize in the 'Images' folder. 
+- The images should have only one face per image.
+- Run the script.
+
+
+## How it works
+
+- The script loads the known face encodings from the 'Images' folder.
+- It captures video from the default camera.
+- For each frame of video, it detects faces and encodes them.
+- It compares the encodings of detected faces with the known face encodings.
+- If a match is found, it records the name of the recognized person and the timestamp in the 'Attendance.csv' file.
+- The video stream is displayed with rectangles around the recognized faces and their names.
+
+## File Structure
+
+-- Images: Store images of individuals you want to recognize.
+-- Attendance.csv: Stores attendance records with name, time, and date.
diff --git a/AirCanvas/.idea/.gitignore b/AirCanvas/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/AirCanvas/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/AirCanvas/.idea/AirCanvas.iml b/AirCanvas/.idea/AirCanvas.iml
new file mode 100644
index 00000000..d0876a78
--- /dev/null
+++ b/AirCanvas/.idea/AirCanvas.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/AirCanvas/.idea/inspectionProfiles/Project_Default.xml b/AirCanvas/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..d2b3dc9e
--- /dev/null
+++ b/AirCanvas/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,14 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <option name="ignoredErrors">
+        <list>
+          <option value="E231" />
+          <option value="E302" />
+          <option value="E225" />
+        </list>
+      </option>
+    </inspection_tool>
+  </profile>
+</component>
\ No newline at end of file
diff --git a/AirCanvas/.idea/inspectionProfiles/profiles_settings.xml b/AirCanvas/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 00000000..105ce2da
--- /dev/null
+++ b/AirCanvas/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>
\ No newline at end of file
diff --git a/AirCanvas/.idea/misc.xml b/AirCanvas/.idea/misc.xml
new file mode 100644
index 00000000..ef780c9a
--- /dev/null
+++ b/AirCanvas/.idea/misc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (AirCanvas)" project-jdk-type="Python SDK" />
+</project>
\ No newline at end of file
diff --git a/AirCanvas/.idea/modules.xml b/AirCanvas/.idea/modules.xml
new file mode 100644
index 00000000..c0cf920b
--- /dev/null
+++ b/AirCanvas/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/AirCanvas.iml" filepath="$PROJECT_DIR$/.idea/AirCanvas.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/AirCanvas/main.py b/AirCanvas/main.py
new file mode 100644
index 00000000..5977f9ef
--- /dev/null
+++ b/AirCanvas/main.py
@@ -0,0 +1,207 @@
+import numpy as np
+import cv2
+from collections import deque
+
+
+
+# default called trackbar function
+def setValues():
+    print(" ")
+
+
+# Creating the trackbars needed for
+# adjusting the marker colour These
+# trackbars will be used for setting
+# the upper and lower ranges of the
+# HSV required for particular colour
+cv2.namedWindow("Color detectors")
+cv2.createTrackbar("Upper Hue", "Color detectors", 153, 180, setValues)
+cv2.createTrackbar("Upper Saturation", "Color detectors", 255, 255, setValues)
+cv2.createTrackbar("Upper Value", "Color detectors", 255, 255, setValues)
+cv2.createTrackbar("Lower Hue", "Color detectors", 64, 180, setValues)
+cv2.createTrackbar("Lower Saturation", "Color detectors", 72, 255, setValues)
+cv2.createTrackbar("Lower Value", "Color detectors", 49, 255, setValues)
+
+# Giving different arrays to handle colour
+# points of different colour These arrays
+# will hold the points of a particular colour
+# in the array which will further be used
+# to draw on canvas
+bpoints = [deque(maxlen=1024)]
+gpoints = [deque(maxlen=1024)]
+rpoints = [deque(maxlen=1024)]
+ypoints = [deque(maxlen=1024)]
+
+# These indexes will be used to mark position
+# of pointers in colour array
+blue_index = 0
+green_index = 0
+red_index = 0
+yellow_index = 0
+
+# The kernel to be used for dilation purpose
+kernel = np.ones((5, 5), np.uint16)
+
+# The colours which will be used as ink for
+# the drawing purpose
+colors = [(255, 0, 0), (0, 255, 0),(0, 0, 255), (0, 255, 255)]
+colorIndex = 0
+
+# Here is code for Canvas setup
+paintWindow = np.zeros((471, 636, 3)) + 255
+paintWindow = cv2.rectangle(paintWindow, (40,1), (140,65), (0,0,0), 2)
+paintWindow = cv2.rectangle(paintWindow, (160,1), (255,65), colors[0], -1)
+paintWindow = cv2.rectangle(paintWindow, (275,1), (370,65), colors[1], -1)
+paintWindow = cv2.rectangle(paintWindow, (390,1), (485,65), colors[2], -1)
+paintWindow = cv2.rectangle(paintWindow, (505,1), (600,65), colors[3], -1)
+
+cv2.putText(paintWindow, "CLEAR", (49, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 2, cv2.LINE_AA)
+cv2.putText(paintWindow, "BLUE", (185, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
+cv2.putText(paintWindow, "GREEN", (298, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
+cv2.putText(paintWindow, "RED", (420, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2, cv2.LINE_AA)
+cv2.putText(paintWindow, "YELLOW", (520, 33), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (150,150,150), 2, cv2.LINE_AA)
+cv2.namedWindow('Paint', cv2.WINDOW_AUTOSIZE)
+
+# Loading the default webcam of PC.
+cap = cv2.VideoCapture(0)
+
+# Keep looping
+while True:
+
+    # Reading the frame from the camera
+    ret, frame = cap.read()
+
+    # Flipping the frame to see same side of yours
+    frame = cv2.flip(frame, 1)
+    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
+
+    # Getting the updated positions of the trackbar
+    # and setting the HSV values
+    u_hue = cv2.getTrackbarPos("Upper Hue","Color detectors")
+    u_saturation = cv2.getTrackbarPos("Upper Saturation","Color detectors")
+    u_value = cv2.getTrackbarPos("Upper Value","Color detectors")
+    l_hue = cv2.getTrackbarPos("Lower Hue","Color detectors")
+    l_saturation = cv2.getTrackbarPos("Lower Saturation","Color detectors")
+    l_value = cv2.getTrackbarPos("Lower Value","Color detectors")
+    Upper_hsv = np.array([u_hue, u_saturation, u_value])
+    Lower_hsv = np.array([l_hue, l_saturation, l_value])
+
+    # Adding the colour buttons to the live frame
+    # for colour access
+    frame = cv2.rectangle(frame, (40, 1), (140, 65),(122, 122, 122), -1)
+    frame = cv2.rectangle(frame, (160, 1), (255, 65),colors[0], -1)
+    frame = cv2.rectangle(frame, (275, 1), (370, 65),colors[1], -1)
+    frame = cv2.rectangle(frame, (390, 1), (485, 65),colors[2], -1)
+    frame = cv2.rectangle(frame, (505, 1), (600, 65),colors[3], -1)
+
+    cv2.putText(frame, "CLEAR ALL", (49, 33),cv2.FONT_HERSHEY_SIMPLEX, 0.5,(255, 255, 255), 2, cv2.LINE_AA)
+
+    cv2.putText(frame, "BLUE", (185, 33),cv2.FONT_HERSHEY_SIMPLEX, 0.5,(255, 255, 255), 2, cv2.LINE_AA)
+
+    cv2.putText(frame, "GREEN", (298, 33),cv2.FONT_HERSHEY_SIMPLEX, 0.5,(255, 255, 255), 2, cv2.LINE_AA)
+
+    cv2.putText(frame, "RED", (420, 33),cv2.FONT_HERSHEY_SIMPLEX, 0.5,(255, 255, 255), 2, cv2.LINE_AA)
+
+    cv2.putText(frame, "YELLOW", (520, 33),cv2.FONT_HERSHEY_SIMPLEX, 0.5,(150, 150, 150), 2, cv2.LINE_AA)
+
+    # Identifying the pointer by making its
+    # mask
+    Mask = cv2.inRange(hsv, Lower_hsv, Upper_hsv)
+    Mask = cv2.erode(Mask, kernel, iterations=1)
+    Mask = cv2.morphologyEx(Mask, cv2.MORPH_OPEN, kernel)
+    Mask = cv2.dilate(Mask, kernel, iterations=1)
+
+    # Find contours for the pointer after
+    # identifying it
+    _,cnts,_ = cv2.findContours(Mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
+    center = None
+
+    # If the contours are formed
+    if len(cnts) > 0:
+        # sorting the contours to find biggest
+        cnt = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
+
+        # Get the radius of the enclosing circle
+        # around the found contour
+        ((x, y), radius) = cv2.minEnclosingCircle(cnt)
+
+        # Draw the circle around the contour
+        cv2.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2)
+
+        # Calculating the center of the detected contour
+        M = cv2.moments(cnt)
+        center = (int(M['m10'] / M['m00']), int(M['m01'] / M['m00']))
+
+        # Now checking if the user wants to click on
+        # any button above the screen
+        if center[1] <= 65:
+
+            # Clear Button
+            if 40 <= center[0] <= 140:
+                bpoints = [deque(maxlen=512)]
+                gpoints = [deque(maxlen=512)]
+                rpoints = [deque(maxlen=512)]
+                ypoints = [deque(maxlen=512)]
+
+                blue_index = 0
+                green_index = 0
+                red_index = 0
+                yellow_index = 0
+
+                paintWindow[67:, :, :] = 255
+            elif 160 <= center[0] <= 255:
+                colorIndex = 0  # Blue
+            elif 275 <= center[0] <= 370:
+                colorIndex = 1  # Green
+            elif 390 <= center[0] <= 485:
+                colorIndex = 2  # Red
+            elif 505 <= center[0] <= 600:
+                colorIndex = 3  # Yellow
+        else:
+            if colorIndex == 0:
+                bpoints[blue_index].appendleft(center)
+            elif colorIndex == 1:
+                gpoints[green_index].appendleft(center)
+            elif colorIndex == 2:
+                rpoints[red_index].appendleft(center)
+            elif colorIndex == 3:
+                ypoints[yellow_index].appendleft(center)
+
+    # Append the next deques when nothing is
+    # detected to avoid messing up
+    else:
+        bpoints.append(deque(maxlen=512))
+        blue_index += 1
+        gpoints.append(deque(maxlen=512))
+        green_index += 1
+        rpoints.append(deque(maxlen=512))
+        red_index += 1
+        ypoints.append(deque(maxlen=512))
+        yellow_index += 1
+
+    # Draw lines of all the colors on the
+    # canvas and frame
+    points = [bpoints, gpoints, rpoints, ypoints]
+    for i in range(len(points)):
+
+        for j in range(len(points[i])):
+
+            for k in range(1, len(points[i][j])):
+
+                if points[i][j][k - 1] is None or points[i][j][k] is None:
+                    continue
+
+                cv2.line(frame, points[i][j][k - 1], points[i][j][k], colors[i], 2)
+                cv2.line(paintWindow, points[i][j][k - 1], points[i][j][k], colors[i], 2)
+
+    # Show all the windows
+    cv2.imshow("Tracking", frame)
+    cv2.imshow("Paint", paintWindow)
+
+    if cv2.waitKey(4) & 0xFF == ord("q"):
+        break
+
+# Release the camera and all resources
+cap.release()
+cv2.destroyAllWindows()
+
diff --git a/AirCanvas/readme.md b/AirCanvas/readme.md
new file mode 100644
index 00000000..e43c2fc6
--- /dev/null
+++ b/AirCanvas/readme.md
@@ -0,0 +1,39 @@
+
+## Real-Time Color Drawing App
+
+
+This is a simple real-time color drawing application using OpenCV and Python. With this application, you can draw in various colors using your webcam. It detects the color of an object and allows you to draw with that color on the canvas.
+
+## Features
+
+- Choose from different colors (blue, green, red, and yellow) for drawing.
+- Clear the canvas with the "CLEAR" button.
+- Real-time color detection and drawing on the webcam feed.
+- Adjustable HSV (Hue, Saturation, Value) ranges for color detection.
+
+
+## Requirements
+
+- Python 3
+- OpenCV (cv2) library
+- NumPy
+- Webcam
+
+
+## Usage
+
+- Clone or download this repository to your local machine.
+
+- Make sure you have Python and the required libraries installed.
+
+- Run the Python script using the following command:
+
+
+python color_drawing_app.py
+
+
+A window will open showing your webcam feed and the color drawing options. You can use the "CLEAR" button to clear the canvas or select different colors for drawing.
+
+- Adjust the HSV (Hue, Saturation, Value) trackbars to change the color detection parameters.
+
+- To exit the application, press the "q" key.
\ No newline at end of file
diff --git a/Banking App/Readme.md b/Banking App/Readme.md
new file mode 100644
index 00000000..a2acce7d
--- /dev/null
+++ b/Banking App/Readme.md	
@@ -0,0 +1,4 @@
+## A Banking App
+
+
+A simple python program that uses luhn algorithm to verify card number, enables transfer and withdrawal of money It makes use of sqlite3 for database storage and therefore permits manipulation of our details and keeps them safe.
\ No newline at end of file
diff --git a/Banking App/banking.py b/Banking App/banking.py
new file mode 100644
index 00000000..b814999f
--- /dev/null
+++ b/Banking App/banking.py	
@@ -0,0 +1,186 @@
+
+import random
+import sys
+import sqlite3
+random.seed()
+
+
+conn = sqlite3.connect('card.s3db')
+cur = conn.cursor()
+# cur.execute("DROP TABLE card")
+cur.execute("CREATE TABLE IF NOT EXISTS card(id INTEGER PRIMARY KEY,number TEXT,pin TEXT,balance INTEGER DEFAULT 0);")
+conn.commit()
+
+
+class Card:
+
+    def __init__(self):
+        self.card = ''
+        self.pin = ''
+        self.login_card = ''
+        self.login_pin = ''
+        self.row = []
+        self.balance = 0
+        self.receiver_balance = 0
+        
+    def create_account(self):
+        print("Your card has been created")
+        print("Your card number:")
+        self.card = '400000' + str(random.randint(100000000, 999999999)) 
+        print(self.luhn())
+        print("Your card PIN:")
+        self.pin = str(random.randint(1000, 9999))
+        print(self.pin)
+        cur.execute(f"""INSERT INTO card (number, pin) VALUES ({self.card}, {self.pin});""")
+        conn.commit()
+        
+    def log_in(self):
+
+        self.login_card = input("Enter your card number:\n")
+        self.login_pin = input("Enter your PIN:\n")
+
+        cur.execute(f"""SELECT
+                            id,
+                            number,
+                            pin,
+                            balance
+                        FROM 
+                            card
+                        WHERE
+                            number = {self.login_card}
+                            AND pin = {self.login_pin}
+                        ;""")
+
+        self.row = cur.fetchone()
+        if self.row:
+            self.balance = self.row[3]
+            print('\nYou have successfully logged in')
+            self.success()
+
+        else:
+            print("wrong card number or pin")
+
+        '''elif not self.luhn_2(self.login_card):
+            print('Probably you made a mistake in the card number. Please try again!')'''
+            
+    def success(self):
+        while True:
+            print("""\n1. Balance
+2. Add income
+3. Do transfer
+4. Close account
+5. Log out
+0. Exit""")
+            i = int(input())
+            if i == 1:
+                print('\nBalance: ', self.balance)
+                print()
+            elif i == 2:
+                print('\nEnter income:')
+                amount = int(input())
+                self.balance += amount
+                cur.execute(f'UPDATE card SET balance = {self.balance} WHERE number = {self.login_card};')
+                conn.commit()
+                print('Income was added!')
+            elif i == 3:
+                print('\nTransfer\nEnter card number:')
+                receiver_card = input()
+                cur.execute(f'SELECT id, number,pin,balance FROM card WHERE number = {receiver_card};')
+
+                if not self.luhn_2(receiver_card):
+                    print('Probably you made a mistake in the card number. Please try again!')
+                elif not cur.fetchone():
+                    print('Such a card does not exist.')
+                else:
+                    transfer = int(input("Enter how much money you want to transfer:\n"))
+                    if transfer > self.balance:
+                        print("Not enough money!")
+                    else:
+                        self.balance -= transfer
+                        cur.execute(f'UPDATE card SET balance = {self.balance} WHERE number = {self.login_card};')
+                        self.receiver_balance += transfer
+                        cur.execute(f'UPDATE card SET balance = {self.receiver_balance} WHERE number = {receiver_card};')
+                        cur.execute(f'SELECT * FROM card WHERE number = {self.login_card}')
+                        print(cur.fetchone())
+                        print("Success!")
+                        conn.commit()
+
+            elif i == 4:
+                cur.execute(f"DELETE FROM card WHERE number = {self.login_card}")
+                conn.commit()
+                print('\nThe account has been closed!')
+                break
+            elif i == 5:
+                print("\nYou have successfully log out!")
+                break
+            elif i == 0:
+                print("\nBye!")
+                conn.close()
+                sys.exit()
+
+    def luhn_2(self, num):
+        num2 = num[:]
+        num2 = num2[::-1]
+        lst = [int(x) for x in num2]
+        s1 = sum(lst[::2])
+        for i in range(len(lst)):
+            if i % 2 != 0:
+                lst[i] = lst[i] * 2
+        for i in range(len(lst)):
+            if lst[i] > 9:
+                lst[i] -= 9
+        s2 = sum(lst[1:len(lst):2])
+
+        if (s1 + s2) % 10 == 0:
+            return True
+        return False
+                
+    # Defining my luhn algorithm for creating a new card number
+    def luhn(self):
+
+        lst2 = [int(x) for x in self.card]
+        lst3 = lst2[:]
+        
+        for i in range(len(lst3)):
+            if i % 2 == 0:
+                lst3[i] = lst3[i] * 2
+            else:
+                lst3[i] = lst3[i]
+    
+        for i in range(len(lst3)):
+            if lst3[i] > 9:
+                lst3[i] -= 9
+            
+        tot = sum(lst3)
+        count_sum = 0
+        while True:
+            if (tot + count_sum) % 10 == 0:
+                break
+            else:
+                count_sum += 1
+                
+        lst2.append(count_sum)
+        self.card = (''.join(map(str, lst2)))
+        
+        return self.card
+        
+    def menu(self):
+        while True:
+            print("""\n1. Create an account
+2. Log into account
+0. Exit""")
+            i = int(input())
+            if i == 1:
+                self.create_account()
+            elif i == 2:
+                self.log_in()
+            elif i == 0:
+                conn.close()
+                print("\nBye!")
+                break
+            else:
+                print("Invalid input")
+                
+
+card = Card()
+card.menu()
\ No newline at end of file
diff --git a/Car Racing Game/background_music.wav b/Car Racing Game/background_music.wav
new file mode 100644
index 00000000..85ac3c91
Binary files /dev/null and b/Car Racing Game/background_music.wav differ
diff --git a/Car Racing Game/car_nfs.png b/Car Racing Game/car_nfs.png
new file mode 100644
index 00000000..6c1e9f4c
Binary files /dev/null and b/Car Racing Game/car_nfs.png differ
diff --git a/Car Racing Game/main.py b/Car Racing Game/main.py
new file mode 100644
index 00000000..6623e2d7
--- /dev/null
+++ b/Car Racing Game/main.py	
@@ -0,0 +1,158 @@
+import pygame
+import random
+
+# Constants
+SCREEN_WIDTH = 1000
+SCREEN_HEIGHT = 700
+CAR_WIDTH = 80
+CAR_HEIGHT = 160
+ROAD_WIDTH = 600
+FPS = 60
+WHITE = (255, 255, 255)
+
+class Car:
+    def __init__(self):
+        self.x = SCREEN_WIDTH // 2 - CAR_WIDTH // 2
+        self.y = SCREEN_HEIGHT - CAR_HEIGHT - 10
+        self.speed_x = 0
+        self.speed_y = 0
+        self.image = pygame.transform.scale(pygame.image.load('car_nfs.png'), (CAR_WIDTH, CAR_HEIGHT))
+
+    def move_left(self):
+        if self.x > SCREEN_WIDTH // 4 - CAR_WIDTH:
+            self.speed_x = -5
+
+    def move_right(self):
+        if self.x < SCREEN_WIDTH // 2:
+            self.speed_x = 5
+
+    def move_forward(self):
+        self.speed_y = -5
+
+    def move_backward(self):
+        self.speed_y = 5
+
+    def stop_x(self):
+        self.speed_x = 0
+
+    def stop_y(self):
+        self.speed_y = 0
+
+    def update_position(self):
+        self.x += self.speed_x
+        self.y += self.speed_y
+
+    def draw(self):
+        screen.blit(self.image, (self.x, self.y))
+
+class Road:
+    def __init__(self):
+        self.y = 0
+        self.speed = 5
+        self.image = pygame.image.load('road_nfs.jpg')
+        self.image = pygame.transform.scale(self.image, (ROAD_WIDTH, SCREEN_HEIGHT))
+
+    def move(self):
+        self.y += self.speed
+        if self.y > SCREEN_HEIGHT:
+            self.y = 0
+
+    def draw(self):
+        screen.blit(self.image, (SCREEN_WIDTH // 4, self.y))
+        screen.blit(self.image, (SCREEN_WIDTH // 4, self.y - SCREEN_HEIGHT))
+
+class HurdleManager:
+    def __init__(self):
+        self.hurdles = []
+        self.speed = 5
+
+    def create_hurdle(self):
+        size = random.randint(20, 50)
+        x = random.randint(SCREEN_WIDTH // 4, SCREEN_WIDTH // 2 - size)
+        y = -size
+        self.hurdles.append(pygame.Rect(x, y, size, size))
+
+    def move_hurdles(self):
+        for hurdle in self.hurdles:
+            hurdle.y += self.speed
+            if hurdle.y > SCREEN_HEIGHT:
+                self.hurdles.remove(hurdle)
+
+class Game:
+    def __init__(self):
+        self.car = Car()
+        self.road = Road()
+        self.hurdle_manager = HurdleManager()
+        self.score = 0
+        self.play_background_music()
+
+    def handle_events(self):
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                pygame.quit()
+                quit()
+
+        keys = pygame.key.get_pressed()
+        if keys[pygame.K_LEFT]:
+            self.car.move_left()
+        if keys[pygame.K_RIGHT]:
+            self.car.move_right()
+        if keys[pygame.K_UP]:
+            self.car.move_forward()
+        if keys[pygame.K_DOWN]:
+            self.car.move_backward()
+
+        if not keys[pygame.K_LEFT] and not keys[pygame.K_RIGHT]:
+            self.car.stop_x()
+        if not keys[pygame.K_UP] and not keys[pygame.K_DOWN]:
+            self.car.stop_y()
+
+    def update_score(self):
+        self.score += 1
+
+    def display_score(self):
+        font = pygame.font.Font(None, 36)
+        score_text = font.render("Score: " + str(self.score), True, WHITE)
+        screen.blit(score_text, (10, 10))
+
+    def run(self):
+        clock = pygame.time.Clock()
+
+        while True:
+            self.handle_events()
+
+            self.road.move()
+
+            screen.fill((0, 0, 0))
+            self.road.draw()
+
+            self.hurdle_manager.create_hurdle()
+            self.hurdle_manager.move_hurdles()
+            self.car.update_position()
+            self.car.draw()
+            self.display_score()
+
+            self.car.speed_x = self.road.speed * 2
+            self.car.speed_y = self.road.speed * 2
+            self.hurdle_manager.speed = self.road.speed * 1.5
+
+            self.update_score()
+
+            pygame.display.update()
+            clock.tick(FPS)
+
+    def play_background_music(self):
+        pygame.mixer.init()
+        pygame.mixer.music.load('background_music.wav')
+        pygame.mixer.music.play(-1)  # -1 makes the music loop indefinitely
+
+# Initialize Pygame
+pygame.init()
+
+# Create the game window
+screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
+pygame.display.set_caption("Need for Speed - Car Racing Game")
+
+# Run the game
+game = Game()
+game.run()
diff --git a/Car Racing Game/road_nfs.jpg b/Car Racing Game/road_nfs.jpg
new file mode 100644
index 00000000..e687318a
Binary files /dev/null and b/Car Racing Game/road_nfs.jpg differ
diff --git a/Conway's Game of Life/game_of_life.py b/Conway's Game of Life/game_of_life.py
new file mode 100644
index 00000000..a34fd2e9
--- /dev/null
+++ b/Conway's Game of Life/game_of_life.py	
@@ -0,0 +1,75 @@
+import pygame
+import numpy as np
+
+COLOR_BG = (10,10,10)
+COLOR_GRID = (40,40,40)
+COLOR_DIE_NEXT = (170,170,170)
+COLOR_ALIVE_NEXT = (255,255,255)
+TICK_SPEED = 30
+
+clock = pygame.time.Clock()
+
+def update(screen, cells, size, with_progress = False):
+    updated_cells = np.zeros((cells.shape[0], cells.shape[1]))
+
+    for row,col in np.ndindex(cells.shape):
+        alive = np.sum(cells[row-1:row+2, col-1:col+2]) - cells[row, col]
+        color = COLOR_BG if cells[row, col] == 0 else COLOR_ALIVE_NEXT
+
+        if cells[row, col] == 1:
+            if alive < 2 or alive > 3:
+                if with_progress:
+                    color = COLOR_DIE_NEXT
+            elif 2 <= alive <= 3:
+                updated_cells[row, col] = 1
+                if with_progress:
+                    color = COLOR_ALIVE_NEXT
+        else:
+            if alive == 3:
+                    updated_cells[row, col] = 1
+                    if with_progress:
+                        color = COLOR_ALIVE_NEXT
+        
+        pygame.draw.rect(screen, color, (col*size, row*size, size - 1, size - 1))
+    
+    return updated_cells
+
+def main():
+    pygame.init()
+    screen = pygame.display.set_mode((800,600))
+    
+    cells = np.zeros((60, 80))
+    screen.fill(COLOR_GRID)
+
+    update(screen, cells, 10)
+
+    pygame.display.update()
+
+    running = False
+
+    while True:
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                pygame.quit()
+                return
+            elif event.type == pygame.KEYDOWN:
+                if event.key == pygame.K_SPACE:
+                    running = not running
+                    update(screen, cells, 10)
+                    pygame.display.update()
+            if pygame.mouse.get_pressed()[0]:
+                pos = pygame.mouse.get_pos()
+                cells[pos[1]//10, pos[0]//10] = 1 # cells = np.ones((cells.shape[0], cells.shape[1])) # -> fun line of code :p
+                update(screen, cells, 10)
+                pygame.display.update()
+        
+        screen.fill(COLOR_GRID)
+
+        if running:
+            cells = update(screen, cells, 10, with_progress = True)
+            pygame.display.update()
+
+        clock.tick(TICK_SPEED)
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/Conway's Game of Life/readme.md b/Conway's Game of Life/readme.md
new file mode 100644
index 00000000..57c4b1e3
--- /dev/null
+++ b/Conway's Game of Life/readme.md	
@@ -0,0 +1,44 @@
+
+## Conway's Game of Life in Python
+
+This is a simple implementation of Conway's Game of Life using Python and the Pygame library.
+
+## Description
+
+Conway's Game of Life is a cellular automaton devised by the British mathematician John Horton Conway in 1970. It is a zero-player game, meaning its evolution is determined by its initial state, requiring no further input. The game is played on a grid of cells, each of which can be alive or dead. The game progresses in steps, with each step following a set of rules to determine the state of each cell in the next generation.
+
+In this Python implementation, we've created a grid of cells on the screen. You can interact with the game by clicking on cells to bring them to life or kill them. Pressing the spacebar will start and stop the game's automatic progress. The game will evolve according to the rules of Conway's Game of Life.
+
+## Prerequisites
+
+- Python 3.x
+- Pygame library
+- You can install Pygame using pip:
+
+
+pip install pygame
+
+
+## Usage
+
+- Clone or download this repository to your local machine.
+- Open a terminal or command prompt and navigate to the directory containing the code.
+- Run the game by executing python conways_game_of_life.py.
+
+
+## Controls
+
+- Left mouse click: Toggle cell state (alive or dead).
+- Spacebar: Start or stop the automatic progression of the game.
+- Close the game window to exit.
+
+
+## Customization
+You can customize the game by modifying the following constants in the code:
+
+- COLOR_BG: Background color.
+- COLOR_GRID: Grid color.
+- COLOR_DIE_NEXT: Color of cells that will die in the next generation.
+- COLOR_ALIVE_NEXT: Color of cells that will survive in the next generation.
+- TICK_SPEED: Speed of the game's progression (frames per second).
+- cells = np.zeros((60, 80)): Initial state of the grid. You can change the grid size and initial configuration here.
\ No newline at end of file
diff --git a/Dice-Simulator/readme.md b/Dice-Simulator/readme.md
new file mode 100644
index 00000000..8ad1e0d9
--- /dev/null
+++ b/Dice-Simulator/readme.md
@@ -0,0 +1,3 @@
+## Dice Simulator
+
+This is a basic dice simluator implementation game.
\ No newline at end of file
diff --git a/Dictionary-App/readme.md b/Dictionary-App/readme.md
new file mode 100644
index 00000000..8b1e3305
--- /dev/null
+++ b/Dictionary-App/readme.md
@@ -0,0 +1,12 @@
+## Dictionary APP
+
+This is a basic implementation of the dictionary app.
+
+Note:
+
+Following freatures are to be added here:
+
+1- is to make this program in such a way that if word not exist then do something
+2- also if user enter wrong word by mistake (for example if user want to enter ""happy"" but type "Haappyy") then do something
+3- task number 2 is with get_close_matches() for difflib library
+4- then make GUI application of this
\ No newline at end of file
diff --git a/FaceRecgonition/.idea/.gitignore b/FaceRecgonition/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/FaceRecgonition/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/FaceRecgonition/.idea/.name b/FaceRecgonition/.idea/.name
new file mode 100644
index 00000000..11a5d8e1
--- /dev/null
+++ b/FaceRecgonition/.idea/.name
@@ -0,0 +1 @@
+main.py
\ No newline at end of file
diff --git a/FaceRecgonition/.idea/FaceRecgonition.iml b/FaceRecgonition/.idea/FaceRecgonition.iml
new file mode 100644
index 00000000..d0876a78
--- /dev/null
+++ b/FaceRecgonition/.idea/FaceRecgonition.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/FaceRecgonition/.idea/inspectionProfiles/Project_Default.xml b/FaceRecgonition/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..09c9f00a
--- /dev/null
+++ b/FaceRecgonition/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,24 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <option name="ignoredErrors">
+        <list>
+          <option value="E231" />
+          <option value="E302" />
+          <option value="E225" />
+          <option value="E305" />
+          <option value="W292" />
+          <option value="E303" />
+        </list>
+      </option>
+    </inspection_tool>
+    <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
+      <option name="ignoredErrors">
+        <list>
+          <option value="N802" />
+        </list>
+      </option>
+    </inspection_tool>
+  </profile>
+</component>
\ No newline at end of file
diff --git a/FaceRecgonition/.idea/inspectionProfiles/profiles_settings.xml b/FaceRecgonition/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 00000000..105ce2da
--- /dev/null
+++ b/FaceRecgonition/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>
\ No newline at end of file
diff --git a/FaceRecgonition/.idea/misc.xml b/FaceRecgonition/.idea/misc.xml
new file mode 100644
index 00000000..4a4df12f
--- /dev/null
+++ b/FaceRecgonition/.idea/misc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (FaceRecgonition)" project-jdk-type="Python SDK" />
+</project>
\ No newline at end of file
diff --git a/FaceRecgonition/.idea/modules.xml b/FaceRecgonition/.idea/modules.xml
new file mode 100644
index 00000000..cd268188
--- /dev/null
+++ b/FaceRecgonition/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/FaceRecgonition.iml" filepath="$PROJECT_DIR$/.idea/FaceRecgonition.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/FaceRecgonition/main.py b/FaceRecgonition/main.py
new file mode 100644
index 00000000..cf29c1b3
--- /dev/null
+++ b/FaceRecgonition/main.py
@@ -0,0 +1,26 @@
+import cv2
+import dlib
+
+cap = cv2.VideoCapture(0)
+detector = dlib.get_frontal_face_detector()
+
+while True:
+    ret, frame = cap.read()
+    frame = cv2.flip(frame,1)
+    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
+    faces = detector(gray)
+
+    i=0
+
+    for face in faces:
+        x, y = face.left(), face.top()
+        x1, y1 = face.right(), face.bottom()
+        cv2.rectangle(frame,(x,y),(x1,y1),(0,255,0),2)
+        i=i+1
+        cv2.putText(frame,'face num'+str(i),(x-10,y-10),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)
+        print(face,i)
+    cv2.imshow('frame',frame)
+    if cv2.waitKey(1) & 0xFF == ord('q'):
+        break
+cap.release()
+cv2.destroyAllWindows()
\ No newline at end of file
diff --git a/FaceRecgonition/readme.md b/FaceRecgonition/readme.md
new file mode 100644
index 00000000..98ee4978
--- /dev/null
+++ b/FaceRecgonition/readme.md
@@ -0,0 +1,39 @@
+
+## Real-Time Face Detection using OpenCV and dlib
+
+
+## Introduction
+
+This Python script captures video from your webcam and detects faces in real-time using the OpenCV library and the dlib face detection model.
+
+## Getting Started
+
+To get started, you'll need to have Python and the following libraries installed:
+
+- OpenCV
+- dlib
+
+You can install these libraries using pip:
+
+
+pip install opencv-python
+pip install dlib
+
+
+## Usage
+- Clone this repository or download the script to your local machine.
+- Ensure that your webcam is connected and accessible.
+- Open a terminal or command prompt and navigate to the directory containing the script.
+- Run the script using the following command:
+
+python face_detection.py
+
+The script will open your webcam and start detecting faces in real-time. Detected faces will be highlighted with rectangles, and a number will be displayed on each detected face to indicate its order.
+
+## Exiting the Application
+
+To exit the application, simply press the 'q' key on your keyboard while the window displaying the webcam feed is in focus.
+
+## Dependencies
+OpenCV
+dlib
\ No newline at end of file
diff --git a/Hangman Game/added.txt b/Hangman Game/added.txt
new file mode 100644
index 00000000..1b34c180
--- /dev/null
+++ b/Hangman Game/added.txt	
@@ -0,0 +1 @@
+I added extra features
\ No newline at end of file
diff --git a/Hangman Game/hangman.py b/Hangman Game/hangman.py
index 59b374c4..e55607ea 100644
--- a/Hangman Game/hangman.py	
+++ b/Hangman Game/hangman.py	
@@ -1,33 +1,62 @@
+# IMPORT ALL LIBRARIES
+import requests
 import random
+from lxml import etree
+
+alphabetChoice = random.choice(["a","b","c","d","e","f","g","h","i"])
+columnChoice = random.choice(range(1, 3))
+wordChoice = random.choice(range(1, 10))
+
+def checkName(name):
+    if name == "":
+        print("Sorry, you did not enter your name")
+        return 0
+    else:
+        print("\n--------------------------------------\n")
+        return 1
 
 def hangman():
-    WORD = random.choice(["pencil","pen","superman","glasses","mobile","calculator","laptop","book","person","animal"])
+    # Define the URL and XPath
+    url = f"https://randomword.com/words/{alphabetChoice}.html"
+    xpath = f"/html/body/div[1]/div[2]/div/div/div[1]/div[2]/ul[1]/li[{wordChoice}]"
+
+    # Send a GET request to the website
+    response = requests.get(url)
+    html_content = response.content
+
+    # Parse the HTML content
+    tree = etree.HTML(html_content)
+
+    # Extract the desired element using the XPath
+    word = tree.xpath(xpath)[0].text.strip()
     # print(WORD)
     alphabets = "abcdefghijklmnopqrstuvwxyz"
     chance = 10
     guess_made = ""
 
-    while len(WORD) > 0:
+    while len(word) > 0:
         main = ""
-        for letter in WORD:
+        for letter in word:
             if letter in guess_made:
                 main += letter
             else:
                 main = main +"_"+" "
 
-        if main == WORD:
+        if main == word:
             print("Letter is: "+ main)
             print("You win! ")
             break
 
-        guess = input("Guess the word "+ main)
+        print(f"Guess the word {main}")
+        guess = input("\n")
 
         if guess in alphabets:
             guess_made = guess_made + guess
         else:
-            guess = input("Enter the valid character: ")
+            guess = input("Enter the valid character:\n")
 
-        if guess not in WORD:
+        if guess not in word:
+            print(word)
             chance -= 1
 
             if chance == 9:
@@ -35,7 +64,7 @@ def hangman():
                 print("\n---------------------------- ")
 
             if chance == 8:
-                print("9 turns left")
+                print("8 turns left")
                 print("\n---------------------------- ")
                 print("      O     ")
             if chance == 7:
@@ -82,7 +111,7 @@ def hangman():
                 print("     / \     ")
 
             if chance == 0:
-                print("You loss that man")
+                print(f"You loss that man. The answer was {word}")
                 print("Game Over")
                 print("      O____|  ")
                 print("     /|\      ")
@@ -91,8 +120,10 @@ def hangman():
                 break
 
 
-
 name = input("Hey there! What is your name: ")
-print(name+" lets play a game")
-print("\n--------------------------------------\n")
-hangman()
+
+if checkName(name):
+    print(name+" lets play a game")
+    hangman()
+else:
+    pass
\ No newline at end of file
diff --git a/Language Detector/Readme.md b/Language Detector/Readme.md
new file mode 100644
index 00000000..ba80a44c
--- /dev/null
+++ b/Language Detector/Readme.md	
@@ -0,0 +1,15 @@
+# Language Detector
+
+This is a simple Python project that uses the `langdetect` library to detect the language of a given text.
+
+## Setup
+
+1. Clone the repository.
+2. Install the dependencies:
+
+   ```bash
+   pip install -r requirements.txt
+3. Run the main script:
+
+   ```bash
+   python main.py
diff --git a/Language Detector/main.py b/Language Detector/main.py
new file mode 100644
index 00000000..bff53e01
--- /dev/null
+++ b/Language Detector/main.py	
@@ -0,0 +1,18 @@
+# Language Detector
+from langdetect import detect
+
+# Detecting languages from input text
+language1 = detect('¿Qué te gusta hacer')  
+language2 = detect('Nyasae no omuya') 
+
+# Mapping of language codes to human-readable names
+language_mapping = {
+    'es': 'Spanish',
+    'en': 'English',
+    'sw': 'Swahili',
+    'ek': 'Kisii'  
+}
+
+# Print the detected language in a more user-friendly format
+print(f'This is the {language_mapping.get(language1, language1)} language shortened by: {language1}')
+print(f'This is the {language_mapping.get(language2, language2)} language shortened by: {language2}')
diff --git a/Language Detector/requirements.txt b/Language Detector/requirements.txt
new file mode 100644
index 00000000..084b89b2
--- /dev/null
+++ b/Language Detector/requirements.txt	
@@ -0,0 +1 @@
+langdetect==1.0.9
diff --git a/Local-Chat/README.md b/Local-Chat/README.md
new file mode 100644
index 00000000..5d9c057c
--- /dev/null
+++ b/Local-Chat/README.md
@@ -0,0 +1,47 @@
+# Local Chat
+
+This program allows you to create a channel in the local network for communication between users through the use of a secret key that is generated when a server is created at the host.
+
+# Usage
+
+1. Install the required libraries listed in `requirements.txt` file using `pip`:
+
+```
+pip3 install -r requirements.txt
+```
+
+2. Run `main.py` to create server.
+
+```
+python3 main.py
+```
+after running the script print S parameter(to create server)
+
+!!! be sure to save the key that the program will give you !!!
+
+
+<img src="https://github.com/p4sh4bsc/Python-Projects/blob/local_chat/Local-Chat/src/Server.gif" width="500" height="300" />
+
+
+
+3. Also run `main.py`, but now we gonna connetct to the server as client.
+```
+python3 main.py
+```
+after running the script print C parameter(for connection to the server)
+
+
+
+<img src="https://github.com/p4sh4bsc/Python-Projects/blob/local_chat/Local-Chat/src/Client.gif" width="500" height="300" />
+
+
+
+4. Start chatting with your friends!
+<img src="https://github.com/p4sh4bsc/Python-Projects/blob/local_chat/Local-Chat/src/GUI.png" width="500" height="300" />
+
+
+
+# TODO list
+1. check users by ip
+2. create ports for chat by some hash func
+3. create secure connection between users(for sure every non chat user can listening chat by Wireshark)
diff --git a/Local-Chat/main.py b/Local-Chat/main.py
new file mode 100644
index 00000000..591a3214
--- /dev/null
+++ b/Local-Chat/main.py
@@ -0,0 +1,387 @@
+import socket
+import sys
+import os
+import time
+from art import *
+import random
+import string
+import hashlib
+import threading
+from _thread import *
+
+import multiprocessing
+import tkinter as tk
+import time
+
+
+characters = string.ascii_letters + string.digits
+
+
+
+
+
+class Server():
+    
+    def __init__(self, ip_adr, port, key, nickname):
+        
+        self.ip_adr = ip_adr
+        self.port = port
+        self.key = key
+        self.nickname = nickname
+        self.socket = None
+        self.socketConnection = None
+        self.connectionAddress = None
+        self.clients = []
+        self.nicknames = []
+
+
+    def handle_client(self, client):
+        while True:
+            try:
+                message = client.recv(1024)
+                self.broadcast(message)
+            except:
+                index = self.clients.index(client)
+                self.clients.remove(client)
+                client.close()
+                nickname = self.nicknames[index]
+                self.broadcast(f'{nickname} has left the chat room!'.encode('utf-8'))
+                self.nicknames.remove(nickname)
+                break
+
+
+   
+
+    def broadcast(self, message):
+        for client in self.clients:
+            print(message)
+            client.send(message)
+
+    def runServer(self):
+
+        self.socket = socket.socket()
+        self.socket.bind((self.ip_adr, self.port))
+        self.socket.listen()
+        print(f'Server is running and listening on port {self.port} by private key {self.key}...')
+        while True:
+            print(self.clients, self.nickname)
+            self.socketConnection, self.connectionAddress = self.socket.accept()
+            print(f'connection is established with {str(self.connectionAddress)}')
+
+            receivedMsg = self.socketConnection.recv(128)
+
+            receivedString = receivedMsg.decode('utf-8')
+
+            nickname = receivedString[-16::]
+            nickname.replace("\x00", "")
+
+            if nickname not in self.nicknames:
+                self.nicknames.append(nickname)
+            
+            if self.socketConnection not in self.clients:
+                self.clients.append(self.socketConnection)
+
+            nickname_for_send = nickname.replace("\x00", "")
+            self.broadcast(f'\xaa{nickname_for_send} has connected to chat'.encode('utf-8'))
+            thread = threading.Thread(target=self.handle_client, args=(self.socketConnection,))
+            thread.start()
+
+        
+
+    def closeConnection(self):
+        self.socketConnection.close()
+        self.socket.close()
+        self.connectionAddress = None
+
+
+
+class Client():
+
+    def __init__(self, ip_adr, port, key, nickname, queue, queue_send):
+        self.ip_adr = ip_adr
+        self.port = port 
+        self.key = key
+        self.nickname = nickname
+        self.socket = None
+        self.root = None
+        self.label1 = None
+        self.button1 = None
+        self.scrollbar = None
+        self.text_output = None
+        self.full_recieved_msg = ''
+        self.queue = queue
+        self.queue_send = queue_send
+        #TODO: queue v __init__ (param) a dalshe hz
+
+
+    def connect_to_server(self):
+        self.socket = socket.socket()
+        count_of_connection = 0
+        while True:
+            try:
+                self.socket.connect((self.ip_adr, self.port))
+                break
+            except socket.error as error:
+                print("Error while connecting to server")
+                print(error)
+                count_of_connection += 1
+                if count_of_connection > 4:
+                    print("You try it for 5+ times, we gonna close your connection")
+                    self.socket.close()
+                    return False
+                time.sleep(1)
+        list_for_join = []
+        nickname_enc = self.nickname.encode('utf-8')
+        need_bytes_of_zero = 16 - len(nickname_enc)
+
+        list_for_join.append(b'\x00'*need_bytes_of_zero)
+        list_for_join.append(nickname_enc)
+
+        messageToSend = b''.join(list_for_join)
+
+        try:
+            self.socket.send(messageToSend)
+        except socket.error as error:
+            print("Sorry, we can't send your message")
+            print(error)
+        return True
+    
+    def sendMsg(self):
+        while True:
+            if not self.queue_send.empty():
+                keyboardInput = self.queue_send.get()
+                list_for_join = []
+
+                message_enc = keyboardInput.encode("utf-8")
+
+                nickname_enc = self.nickname.encode('utf-8')
+                need_bytes_of_zero = 16 - len(nickname_enc)
+
+                list_for_join.append(message_enc)
+                list_for_join.append(b'\x00'*need_bytes_of_zero)
+                list_for_join.append(nickname_enc)
+
+                messageToSend = b''.join(list_for_join)
+
+                try:
+                    self.socket.send(messageToSend)
+                except socket.error as error:
+                    print("Sorry, we can't send your message")
+                    print(error)
+
+    def recieveMsg(self):
+
+        while True:
+            receivedMsg = self.socket.recv(128)
+            
+            if receivedMsg[0] == 194:
+                receivedString = receivedMsg.decode("utf-8")
+
+            else:
+                receivedString = receivedMsg.decode("utf-8")
+
+                nickname = receivedString[-16::]
+                nickname.replace("\x00", "")
+
+
+                if nickname.replace("\x00", "") != self.nickname.replace("\x00", ""):
+                    message = receivedString[0:-16]
+                    self.full_recieved_msg = f"{nickname}: {message}"
+                    self.queue.put(self.full_recieved_msg)
+
+    
+
+
+    def add_lines(self):
+
+        try:
+           
+            if not self.queue.empty():
+                recieved_msg_from_queue = self.queue.get()
+                kastil = "".join(map(str, list(recieved_msg_from_queue))).replace('\x00', '')
+
+                self.text_output.insert("end", kastil + "\n") 
+                self.text_output.see("end")  # Scroll to the end of the Text widget
+            self.root.after(100, self.add_lines)  # Schedule the next update
+        except Exception as ex:
+            print(ex)
+    
+    def send_msg_button(self):
+        msg_for_send = self.entry1.get()
+        self.queue.put(f'{self.nickname} : {msg_for_send}')
+        self.queue_send.put(msg_for_send)
+        self.entry1.delete(0, 'end')
+
+
+    def run_gui(self):
+        self.root= tk.Tk()
+
+        self.label1 = tk.Label(self.root, text='Anon chat')
+        self.label1.config(font=('helvetica', 14))
+        self.label1.place(x=220, y=15)
+
+        self.entry1 = tk.Entry(self.root) 
+        self.entry1.place(x=15, y=400, width=450, height=50)
+
+        self.button1 = tk.Button(self.root, text='send', command=self.send_msg_button)
+        self.button1.place(x=400, y=450)
+
+
+
+        self.scrollbar = tk.Scrollbar(self.root)
+        self.scrollbar.pack(side="right", fill="none", expand=True)
+        self.text_output = tk.Text(self.root, yscrollcommand=self.scrollbar.set)
+        self.text_output.place(x=15, y=50, width=450, height=300)
+        self.scrollbar.config(command=self.text_output.yview)
+
+        self.root.minsize(500, 500)
+        self.root.maxsize(500, 500)
+
+
+        self.root.after(0, self.add_lines)
+        self.root.mainloop()
+
+
+    def runClient(self):
+        
+        
+        guiThread = multiprocessing.Process(target=self.run_gui)
+        sendThread = threading.Thread(target=self.sendMsg)
+        receiveThread = threading.Thread(target=self.recieveMsg)
+
+        guiThread.start()
+        sendThread.start()
+        receiveThread.start()
+        
+
+        sendThread.join()
+        receiveThread.join()
+
+        
+        
+        
+
+    def closeConnection(self):
+        self.socket.close()
+
+
+
+class Start():
+    def main_start():
+
+
+        #### read open ports ####
+        list_of_ports = []
+
+        for i in range(65536):
+            s = socket.socket()
+            s.settimeout(1)
+            try:
+                s.connect(('127.0.0.1', i))
+            except socket.error:
+                pass
+            else:
+                s.close
+                list_of_ports.append(i)
+        #########################
+
+        os.system("clear")
+        tprint("Anon    chat")
+
+
+
+
+        command = str(input("Are you [S]erver or [C]lient?\n"))
+
+        if command == "S":
+            key_is_correct = False
+            ip_adr = "localhost"
+            nickname = None
+            while not key_is_correct:
+                os.system("clear")
+                tprint("Anon    chat")
+                private_key = "?" + ''.join(random.choice(characters) for i in range(6))
+                print(f"checking key {private_key} for unic.")
+                time.sleep(0.75)
+                os.system("clear")
+                tprint("Anon    chat")
+                print(f"checking key {private_key} for unic..")
+                time.sleep(0.75)
+                os.system("clear")
+                tprint("Anon    chat")
+                print(f"checking key {private_key} for unic...")
+                time.sleep(0.75)
+                
+                hash_object = hashlib.sha256(bytes(private_key.encode('utf-8')))
+                hash_dig = hash_object.hexdigest()
+                numbers = ''.join(i for i in hash_dig if not i.isalpha())
+                port_for_key = int(sum(list(map(int, numbers)))**1.64)
+                time.sleep(0.3)
+
+                if port_for_key not in list_of_ports or port_for_key > 2000:
+                    try:
+                        
+                        os.system("clear")
+                        tprint("Anon    chat")
+                        print(f"trying to create server by private key {private_key}")
+                        server = Server(ip_adr, port_for_key, private_key, nickname)
+                        server.runServer()
+                        
+                        
+                        key_is_correct = True
+                    except:
+
+                        key_is_correct = False
+            
+
+
+        elif command == "C":
+            queue = multiprocessing.Queue()
+            queue_send = multiprocessing.Queue()
+            
+            ip_adr = "localhost"
+
+            private_key_for_client = input("Enter the key: ")
+            
+            hash_object = hashlib.sha256(bytes(private_key_for_client.encode('utf-8')))
+            hash_dig = hash_object.hexdigest()
+            numbers = ''.join(i for i in hash_dig if not i.isalpha())
+            port_for_key = int(sum(list(map(int, numbers)))**1.64)
+            time.sleep(0.3)
+
+            if port_for_key not in list_of_ports or port_for_key < 2000:
+                key_is_correct = True
+                os.system("clear")
+                tprint("Anon    chat")
+                print(f"done! {private_key_for_client} is correct")
+            nickname = input("Enter your nickname for chat (max len 16): ")
+
+            client = Client(ip_adr, port_for_key, private_key_for_client, nickname, queue, queue_send)
+
+            isConnected = client.connect_to_server()
+
+            if isConnected:
+                
+
+                client.runClient()
+                
+
+                
+                
+            else:
+                print("Error while connecting to server")
+                exit()
+
+        else:
+            print("wrong input, restarting software")
+            Start.main_start()
+
+
+
+if __name__ == "__main__":
+    
+    Start.main_start()
+    
+    #TODO: 1. check users by ip
+    #      2. create ports for chat by some hash func
+   
\ No newline at end of file
diff --git a/Local-Chat/requirements.txt b/Local-Chat/requirements.txt
new file mode 100644
index 00000000..1c8b6d5f
--- /dev/null
+++ b/Local-Chat/requirements.txt
@@ -0,0 +1,2 @@
+art
+tk
\ No newline at end of file
diff --git a/Local-Chat/src/Client.gif b/Local-Chat/src/Client.gif
new file mode 100644
index 00000000..227bbcda
Binary files /dev/null and b/Local-Chat/src/Client.gif differ
diff --git a/Local-Chat/src/GUI.png b/Local-Chat/src/GUI.png
new file mode 100644
index 00000000..da5f2de5
Binary files /dev/null and b/Local-Chat/src/GUI.png differ
diff --git a/Local-Chat/src/Server.gif b/Local-Chat/src/Server.gif
new file mode 100644
index 00000000..f1482fc1
Binary files /dev/null and b/Local-Chat/src/Server.gif differ
diff --git a/Networking-Tools/README.md b/Networking-Tools/README.md
new file mode 100644
index 00000000..563e03e8
--- /dev/null
+++ b/Networking-Tools/README.md
@@ -0,0 +1,11 @@
+# Networking Tools
+A set of simple networking tools created in Python
+
+## How To Use
+⚠️ **Please consider using port scanner for educational purposes only. Using it to scan websites or IP addresses without permission can be seen as a crime.**
+
+Install the requirements using Git: 
+
+`pip install -r requirements.txt`
+
+Run `tools_main.py`
\ No newline at end of file
diff --git a/Networking-Tools/requirements.txt b/Networking-Tools/requirements.txt
new file mode 100644
index 00000000..999704a3
--- /dev/null
+++ b/Networking-Tools/requirements.txt
@@ -0,0 +1,2 @@
+requests
+pyfiglet
\ No newline at end of file
diff --git a/Networking-Tools/tools.py b/Networking-Tools/tools.py
new file mode 100644
index 00000000..fc92bb44
--- /dev/null
+++ b/Networking-Tools/tools.py
@@ -0,0 +1,213 @@
+"""
+This module contains tools such as IP Locator, IP Finder,
+Pinging and Port Scanner.
+DISCLAIMER: Please consider using Port Scanner in educational purposes only.
+
+
+## TOOLS DESCRIPTION
+### IP Locater
+Takes the IP address and with the help of an [API](https://ip-api.com/), extracts data about the IP address.
+Then writes the extracted data in two different files with the same name "ip_data". One of the files is a JSON file. The other one is 
+a text file. These files will be saved on the system's desktop.
+
+### IP Finder
+Takes the domain name and extracts the IPs that are relevant with the domain name.
+It uses windows `nslookup` command to get IPs.
+
+### Pinging
+Takes the domain name or IP address and then pings it.
+It uses `ping` command to ping the domain name or IP address.
+
+### Port Scanner
+Takes the domain name or IP address. After that, it gets the range of the ports to scan.
+Then it starts scanning to look for open ports. The Port Scanner will only look for open ports.
+So if a port is not open, it will not show it on the screen.
+"""
+
+
+# Import necessary modules
+import subprocess
+import platform
+import requests
+import pyfiglet
+import datetime
+import socket
+import json
+import os
+import re
+
+
+# Make the foreground color of the terminal green.
+subprocess.call("color A", shell=True)
+
+# A pattern to validate an IP address.
+ip_pattern = r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$"
+
+
+# Tools
+def locate_ip():
+    """
+    Locate an IP address using an API.
+    """
+    # Clear up the terminal.
+    subprocess.call("cls", shell=True)
+    # Banner of the tool.
+    banner = pyfiglet.figlet_format("IP LOCATER")
+    print(banner)
+    # Get the IP address. Check the input whether it is a valid IP address.
+    # This while loop will run until it gets a valid IP address that matches the IP pattern.
+    while True:
+        IP_address = input("\nEnter a valid IP address: ")
+        # Check if the given input whether it is 'q'.
+        # If it is, then it will abort operation and quit program.
+        if IP_address.lower() == 'q':
+            quit()
+        # Validating the given IP address.
+        if not re.match(ip_pattern, IP_address):
+            print("Invalid IP address")
+            continue
+        else:
+            break
+    # Change current working directory to system's desktop
+    os.chdir(rf"C:\Users\{os.getlogin()}\Desktop")
+    # File names containing data of the IP address.
+    file_name_json = "ip_data.json"
+    file_name_text = "ip_data.txt"
+    # The files containing IP data will have these fields.
+    fields = "status,message,continent,continentCode,country,countryCode,region,regionName,city,district,zip,lat,lon,timezone,currency,isp,org,as,mobile,proxy,hosting,query"
+    # Sending a request to extract data.
+    url = f"http://ip-api.com/json/{IP_address}?fields={fields}"
+    response = requests.get(url)
+    # Write the extracted data in the files.
+    # Write on both JSON file and text file.
+    with open(file_name_json, 'w') as ip_data_file_json:
+        json.dump(response.json(), ip_data_file_json, indent=4)
+    with open(file_name_text, 'w') as ip_data_file_text:
+        ip_data_file_text.write(response.text)
+    # Let the user know that files created on the system's desktop.
+    print("You got the files containing data about the given IP address.")
+    print("Please check your system desktop.")
+    input("\nPress any key to continue...")
+
+
+def get_ip():
+    """
+    Get the IP address of a certain domain name.
+    """
+    subprocess.call("cls", shell=True)
+    # Banner of the tool.
+    banner = pyfiglet.figlet_format("IP FINDER")
+    print(banner)
+    # Get the domain name.
+    # Check if the given input whether it is 'q'.
+    # If it is, then it will abort operation and quit program.
+    domain_name = input("\nEnter a valid domain name: ")
+    if domain_name.lower() == 'q':
+        quit()
+    # Get the IP of the domain name.
+    command = f"nslookup {domain_name}"
+    subprocess.call(command) == 0
+    input("\nPress any key to continue...")
+
+
+def ping():
+    """
+    Ping a domain or website or IP address.
+    """
+    subprocess.call("cls", shell=True)
+    # Banner of the tool.
+    banner = pyfiglet.figlet_format("PING")
+    print(banner)
+    # Get the host to ping.
+    # Host can be a domain name or an IP address.
+    # Check the given input whether it is 'q'.
+    # If it is, then abort operation and quit program.
+    host = input("Enter a valid domain name or IP address: ")
+    if host.lower() == 'q':
+        quit()
+    # If the os is Windows, then the parameter is "-n".
+    # If not, the parameter is "-c"
+    if platform.system().lower() == "windows":
+        parameter = "-n"
+    else:
+        parameter = "-c"
+    # It will send 5 packages to ping the host.
+    command = f"ping {parameter} 5 {host}"
+    subprocess.call(command) == 0
+    input("\nPress any key to continue...")
+
+
+def port_scanner():
+    """
+    Scan ports on a certain host.
+    """
+    subprocess.call("cls", shell=True)
+    # Banner of the tool.
+    banner = pyfiglet.figlet_format("PORT SCANNER")
+    print(banner)
+    print("For scanning using a domain, enter <domain>.\nFor scanning using an IP, enter <ip>")
+    # All this terrifying while loop does is to check the given input at "scan_type".
+    # If it is "q", then it will abort operation and quit program.
+    # If it is "ip", then it will validate the IP address. If it is valid, then it will break the loop.
+    # If it is "domain", then it will get the domain name and break the loop.
+    # If it is none of the above, it will let the user know that the input is not valid.
+    while True:
+        scan_type = input(">>> ")
+        if scan_type.lower() == 'q':
+            quit()
+        if scan_type.lower() == 'ip':
+            while True:
+                host = input("Enter IP for scanning:\n>>> ")
+                if host.lower() == 'q':
+                    quit()
+                if not re.match(ip_pattern, host):
+                    print("Invalid IP address.\n")
+                    continue
+                else:
+                    break
+            break
+        elif scan_type.lower() == 'domain':
+            host = input("Enter domain for scanning:\n>>> ")
+            if host.lower() == 'q':
+                quit()
+            break
+        else:
+            print("Invalid input.\n")
+            continue
+    # Get the IP address of the domain name if a domain name is given.
+    hostIP = socket.gethostbyname(host)
+    # Get the port range.
+    port_range = input("Enter port range in format <start>-<end> (ex: 20-80):\n>>> ")
+    # Split the starting port and the ending port.
+    port_range = port_range.split("-")
+    # Make a neat banner again containing IP address and the time that scanning started.
+    print("_"*60)
+    print("Scanning ports on host: ", hostIP)
+    start_time = datetime.datetime.now()
+    print("Scan started at ", start_time)
+    print("_"*60)
+    print("\nPort\t\t\tStatus\n")
+    # Start scanning ports
+    for port in range(int(port_range[0]), int(port_range[1])+1):
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        # Timeout time for scanning each port is half a second.
+        s.settimeout(0.5)
+        connection = s.connect_ex((hostIP, port))
+        # Check whether the port is open or not.
+        # If it is open, print it.
+        # If it is not open, pass the closed port.
+        if connection == 0:
+            print(f"{port}\t----------\tOpen")
+        else:
+            pass
+        s.close()
+    # Scan ending time.
+    end_time = datetime.datetime.now()
+    # Time taken to scan.
+    time_taken = end_time - start_time
+    # Make a neat banner again containing the time that scanning ended and the time taken to scan.
+    print("_"*60)
+    print("Scan ended at ", end_time)
+    print("Time taken: ", time_taken)
+    print("_"*60)
+    input("\nPress any key to continue...")
diff --git a/Networking-Tools/tools_main.py b/Networking-Tools/tools_main.py
new file mode 100644
index 00000000..b9ffd1b1
--- /dev/null
+++ b/Networking-Tools/tools_main.py
@@ -0,0 +1,125 @@
+# Import necessary modules
+import subprocess
+import tools
+
+
+# Function for displaying menu
+def Display_Menu():
+    header = """
+    ___________________________
+    |                          |
+    |  Basic Networking Tools  |
+    |_____________   __________|
+                  \  \                 
+                    ^_ _^              
+                    (o o)\_________    
+                    (_ _)\         )/\/
+                      U   ||----W||    
+                          ||     ||    
+
+    ### Available Tools:
+        [1] Locate an IP address
+        [2] Get the IP address of a domain
+        [3] Ping a host or IP address
+        [4] Port Scanner
+        [5] Exit
+    
+    * Type <clear> to clear previous commands
+    * Type <q> or to abort operation of a tool
+
+    """
+    print(header)
+
+
+# Functionality of every option
+# Each option operates the tool related to the option number.
+def option_1():
+    """
+    Option 1 --> IP Locater
+    """
+    tools.locate_ip()
+    Display_Menu()
+    Home()
+
+
+def option_2():
+    """
+    Option 2 --> IP Finder
+    """
+    tools.get_ip()
+    Display_Menu()
+    Home()
+
+
+def option_3():
+    """
+    Option 3 --> Pinging
+    """
+    tools.ping()
+    Display_Menu()
+    Home()
+
+
+def option_4():
+    """
+    Option 4 --> Port Scanner
+    """
+    tools.port_scanner()
+    Display_Menu()
+    Home()
+
+
+def option_5():
+    """
+    Option 5 --> Exit
+    """
+    quit()
+
+
+# Function for selecting options
+def Home():
+    """
+    Home of the program is selecting an option from available options.
+    """
+    # Available options' numbers as shown in the menu
+    available_options = (1, 2, 3, 4, 5)
+    # Get the option's number.
+    # If it is wrong, this while loop will run unless it gets
+    # a proper number that is related with one of the available options.
+    while True:
+        try:
+            selected_option = input("\nEnter your option\n>>> ")
+            # In order to clear the mess created by the previous commands,
+            # we define 'clear' command to clear up the screen from previous commands.
+            if selected_option == 'clear':
+                subprocess.call('cls', shell=True)
+                Display_Menu()
+                continue
+            else:
+                selected_option = int(selected_option)
+        except ValueError:
+            print("Please enter the number of the option")
+            continue
+        else:
+            # If the given option number is not available, try to get an available option number.
+            if selected_option not in available_options:
+                print("The option is not available.\nTry another one.")
+                continue
+            else:
+                break
+    # Operate the option related to the given number
+    if selected_option == 1:
+        option_1()
+    elif selected_option == 2:
+        option_2()
+    elif selected_option == 3:
+        option_3()
+    elif selected_option == 4:
+        option_4()
+    elif selected_option == 5:
+        option_5()
+
+
+if __name__ == "__main__":
+    Display_Menu()
+    Home()
diff --git a/Number Guessing Game/main.py b/Number Guessing Game/main.py
index 00af59d2..6901e1cb 100644
--- a/Number Guessing Game/main.py	
+++ b/Number Guessing Game/main.py	
@@ -1,43 +1,76 @@
 import random
 
-"""
- Funtion start() create the magic number, number of attemps, and ask user for input
-"""
 def start():
-    global magic_number
-    magic_number = random.randint(1, 100)
-
-    global attempts
+    """
+    Creates the magic number, number of attempts, and asks the user for input.
+    """
+    global magic_number, attempts
+    magic_number = choose_difficulty()
     attempts = 0
-
     print('---------------------------')
-    print('Guess a number between 1 and 100')
+    print('Guess the magic number!')
+    print('Try to guess the number in as few attempts as possible.')
+
+def choose_difficulty():
+    """
+    Allows the user to select the difficulty level and returns the corresponding range for the magic number.
+    """
+    print("Choose difficulty level:")
+    print("1. Easy (1-50)")
+    print("2. Medium (1-100)")
+    print("3. Hard (1-200)")
+
+    while True:
+        level = input("Enter 1, 2, or 3: ")
+        if level == '1':
+            return random.randint(1, 50)
+        elif level == '2':
+            return random.randint(1, 100)
+        elif level == '3':
+            return random.randint(1, 200)
+        else:
+            print("Invalid choice. Please enter 1, 2, or 3.")
 
-# Function that checks if player won, if it won, returns True
 def check_win(player_guess):
+    """
+    Checks if the player’s guess is correct, too high, or too low.
+    """
     if player_guess > magic_number:
-        print('Too big...')
+        print('Too high! Try a smaller number.')
     elif player_guess < magic_number:
-        print('Too small')
+        print('Too low! Try a larger number.')
     elif player_guess == magic_number:
         return True
 
-start()
-
-# Game loop
-while True:
-    # Take the player input
-    guess = int(input())
-    attempts += 1
-
-    if check_win(guess):
-        print('You won! - Number of attempts: ' + str(attempts))
-
-        keep_playing = input('Keep playing?(y\\n)')
-        # If player want to keep the game, reset the number of attempts
-        if keep_playing == 'y':
-            attempts = 0
-            start()
-        # If player don't want to keep playing, quit the game
-        elif keep_playing == 'n':
-            quit()
+def play_game():
+    """
+    Main game loop that starts the game, processes user input, and checks for win conditions.
+    """
+    global attempts
+    start()
+
+    while True:
+        try:
+            guess = int(input('Enter your guess: '))
+            if guess < 1 or guess > 200:
+                print("Please enter a number between 1 and 200.")
+                continue
+        except ValueError:
+            print("Invalid input. Please enter a valid number.")
+            continue
+
+        attempts += 1
+
+        if check_win(guess):
+            print(f'Congratulations! You guessed the number in {attempts} attempts.')
+            keep_playing = input('Would you like to play again? (y/n): ')
+            if keep_playing.lower() == 'y':
+                play_game()
+            elif keep_playing.lower() == 'n':
+                print("Thanks for playing! Have a great day!")
+                break
+            else:
+                print("Invalid input. Exiting the game.")
+                break
+
+play_game()
diff --git a/Number Guessing Game/readme.md b/Number Guessing Game/readme.md
new file mode 100644
index 00000000..39556e61
--- /dev/null
+++ b/Number Guessing Game/readme.md	
@@ -0,0 +1,3 @@
+## Number Guessing Game
+
+This is a basic Number Guessing Game implementation .
\ No newline at end of file
diff --git a/Pictures Organizer/images/attractive-g3e98a5913_640.jpg b/Pictures Organizer/images/attractive-g3e98a5913_640.jpg
new file mode 100644
index 00000000..b843d0d7
Binary files /dev/null and b/Pictures Organizer/images/attractive-g3e98a5913_640.jpg differ
diff --git a/Pictures Organizer/images/beard-g42aa0992e_640.jpg b/Pictures Organizer/images/beard-g42aa0992e_640.jpg
new file mode 100644
index 00000000..d04ffe1e
Binary files /dev/null and b/Pictures Organizer/images/beard-g42aa0992e_640.jpg differ
diff --git a/Pictures Organizer/images/family-g9f80a310a_640.jpg b/Pictures Organizer/images/family-g9f80a310a_640.jpg
new file mode 100644
index 00000000..8a5d78d1
Binary files /dev/null and b/Pictures Organizer/images/family-g9f80a310a_640.jpg differ
diff --git a/Pictures Organizer/images/people-g159624022_640.jpg b/Pictures Organizer/images/people-g159624022_640.jpg
new file mode 100644
index 00000000..f5d87536
Binary files /dev/null and b/Pictures Organizer/images/people-g159624022_640.jpg differ
diff --git a/Pictures Organizer/main.py b/Pictures Organizer/main.py
new file mode 100644
index 00000000..ccc43043
--- /dev/null
+++ b/Pictures Organizer/main.py	
@@ -0,0 +1,40 @@
+""" Symple code for organizing pictures based on the number of faces"""
+import argparse
+import glob
+import os
+
+import cv2
+
+parser = argparse.ArgumentParser()
+parser.add_argument("path", help="Folder with images")
+parser.add_argument("extension", help="Valid image extension (.png, .jpg, .jpeg)")
+args = parser.parse_args()
+
+current_path = os.getcwd()
+
+# Load the cascade
+face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
+
+imagens = glob.glob(f"{args.path}*.{args.extension}")
+n_folders = 0
+total_images = len(imagens)
+
+for j, img_path in enumerate(imagens):
+    img = cv2.imread(img_path)
+    # Convert into grayscale
+    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+    # Detect faces
+    faces = face_cascade.detectMultiScale(gray, 1.1, 4)
+    n_faces = len(faces)
+    if n_faces>0:
+        folder = f"{n_faces}_face"
+        dest_path = os.path.join(args.path,folder)
+        try:
+            os.mkdir(dest_path)
+            n_folders+=1
+        except:
+            pass
+        os.system(f"mv {img_path} {dest_path}")
+    print (f"Done: {j}/{total_images}", end='\r')
+
+print (f"Nº of folders created: {n_folders}")
\ No newline at end of file
diff --git a/Pictures Organizer/readme.md b/Pictures Organizer/readme.md
new file mode 100644
index 00000000..84fedec6
--- /dev/null
+++ b/Pictures Organizer/readme.md	
@@ -0,0 +1,22 @@
+# Pictures Organizer
+
+This is a symple Python program to organize pictures inside a folder based on the number of face each pictures has. The code uses an opencv pre-trained [model](https://github.com/kipr/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml), so some pictures maybe placed on the wrong folder.
+
+# Usage
+
+Example code using some pictures (The pictures are from [Pixabay](https://pixabay.com/) and are free to use):
+
+``python3 main.py images/ jpg``
+
+**Expected result**
+
+Three folders should have been created inside the 'images' folder: 1_face/ 2_face/ 4_face
+
+# Contributing
+
+If you'd like to contribute to this project, feel free to fork the repository and submit a pull request. You can also open an issue if you find a bug or have a suggestion for improvement.
+
+# Future features
+
+- Add a simple GUI
+- Use other model to organize the pictures.
\ No newline at end of file
diff --git a/QR Code/readem.md b/QR Code/readem.md
new file mode 100644
index 00000000..8a43f2d5
--- /dev/null
+++ b/QR Code/readem.md	
@@ -0,0 +1,3 @@
+## QR Code generator
+
+This is a basic QR generator code implementation.
\ No newline at end of file
diff --git a/README.md b/README.md
index 0b704713..e86d05e7 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,79 @@
-# Python-Projects 🐍
-## These are some cool Basic Python Projects For Beginners.
 
-### Basics python projects for beginners, include *Miscellaneous Games* like-  
-1. Tic-Tac-Toe
-2. Hangman game
-3. Turtle crossing Capstone Game
-4. Student Management System
-5. QR Code generator
+# Python Projects <a href="https://emoji.gg/emoji/1887_python"><img src="https://cdn3.emoji.gg/emojis/1887_python.png" width="40px" height="40px" alt="python"></a>
+A Hub of Python Projects for Beginners.
 
-***You can also schedule Whatsapp messages by using one of the projects in this repository.***
+
+
+
+## Description
+
+Welcome aboard fellow developer, this repository is intended for beginners who can use it for project building, open source contribution and get the most from it.
+If you are new to open source then do consider this repository to start with.
+
+There are various projects under this repository which will be helpful for you get familiar with Python programming.
+
+
+
+## Projects
+
+This repository has the following Projects.
+### Basic Projects along with *Miscellaneous Games* like- 
+- [Tic-Tac-Toe](https://github.com/Shahrayar123/Python-Projects/tree/master/Tic-Tac-Toe)
+- [Towers of Hanoi](https://github.com/Shahrayar123/Python-Projects/tree/master/Towers%20of%20Hanoi)
+- [Hangman game](https://github.com/Shahrayar123/Python-Projects/tree/master/Hangman%20Game)
+- [Turtle crossing Capstone Game](https://github.com/Shahrayar123/Python-Projects/tree/master/Turtle%20Crossing%20Capstone%20Game)
+- [SNAKE](https://github.com/Shahrayar123/Python-Projects/tree/master/SNAKE)
+- [Number Guessing Game](https://github.com/Shahrayar123/Python-Projects/tree/master/Number%20Guessing%20Game)
+- [Rock Paper Scissors Game](https://github.com/Shahrayar123/Python-Projects/tree/master/Rock%20Paper%20Scissors%20Game)
+- [Sudoku-Solver](https://github.com/Shahrayar123/Python-Projects/tree/master/Sudoku-Solver)
+
+### OpenCV projects.
+
+- [AI_Attendence_Program](https://github.com/Shahrayar123/Python-Projects/tree/master/AI_Attendence_Program)
+- [FaceRecognition](https://github.com/Shahrayar123/Python-Projects/tree/master/FaceRecgonition)
+- [QR Code generator](https://github.com/Shahrayar123/Python-Projects/tree/master/QR%20Code)
+
+### Other projects (not yet validated).
+- [AirCanvas](https://github.com/Shahrayar123/Python-Projects/tree/master/AirCanvas)
+- [Conway's Game of Life](https://github.com/Shahrayar123/Python-Projects/tree/master/Conway's%20Game%20of%20Life)
+- [Dice-Simulator](https://github.com/Shahrayar123/Python-Projects/tree/master/Dice-Simulator)
+- [Dictionary-App](https://github.com/Shahrayar123/Python-Projects/tree/master/Dictionary-App)
+- [Riddle](https://github.com/Shahrayar123/Python-Projects/tree/master/Riddle)
+- [SchduledMessageWhatsApp](https://github.com/Shahrayar123/Python-Projects/tree/master/SchduledMessageWhatsApp)
+- [Screen_Recording_App](https://github.com/Shahrayar123/Python-Projects/tree/master/Screen_Recording_App)
+- [Student Management System](https://github.com/Shahrayar123/Python-Projects/tree/master/Student%20Management%20System)
+- [Web_Automation](https://github.com/Shahrayar123/Python-Projects/tree/master/Web_Automation)
+- [Youtube Searching Script](https://github.com/Shahrayar123/Python-Projects/tree/master/Youtube%20Searching%20Script)
+- [pokemone_battle](https://github.com/Shahrayar123/Python-Projects/tree/master/pokemone_battle.py)
+- [Text-to-Speech](https://github.com/Shahrayar123/Python-Projects/tree/master/Text-to-Speech)
+
+
+## Contribution
+
+Contributions are always welcome!
+
+
+
+### Instructions
+1. Fork this repository
+
+2. Clone your forked repository
+
+3. Add your scripts along with description
+
+4. Commit and push
+
+5. Create a pull request
+
+6. Star this repository
+
+7. Wait for pull request to merge
+
+
+
+
+#### Celebrate your first step into the open source world and contribute more.
+
+See [GitHub Contribution Documentation](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) for more reference.
 
 
diff --git a/Riddle/readme.md b/Riddle/readme.md
new file mode 100644
index 00000000..f32a51e7
--- /dev/null
+++ b/Riddle/readme.md
@@ -0,0 +1,20 @@
+# Random Riddle Game
+
+This is a Python program that presents a series of riddles to the user in a random order. The program uses a dictionary to store the riddles and their corresponding answers, and the `random` module to present the questions in a random order.
+
+## Getting Started
+
+To run the program, you'll need to have Python installed on your computer. You can download Python from the official website: https://www.python.org/downloads/
+
+Once you have Python installed, you can run the program by opening a terminal or command prompt, navigating to the directory where you saved the `random_riddle_game.py` file, and typing:
+
+
+## Usage
+
+When you run the program, it will present a series of riddles to the user. The user must enter their answer for each riddle, and the program will tell them whether their answer was correct or not. At the end of the game, the user's score will be displayed.
+
+You can customize the program by adding more riddles to the `riddles` dictionary in the code. Each riddle should be a key in the dictionary, with the corresponding answer as the value.
+
+## Contributing
+
+If you'd like to contribute to this project, feel free to fork the repository and submit a pull request. You can also open an issue if you find a bug or have a suggestion for improvement.
diff --git a/Riddle/riddle.py b/Riddle/riddle.py
new file mode 100644
index 00000000..32fbbd40
--- /dev/null
+++ b/Riddle/riddle.py
@@ -0,0 +1,28 @@
+import random
+
+# Riddle game
+
+riddles = {
+    "I have cities but no houses, forests but no trees, and water but no fish. What am I?": "A map",
+    "I am always hungry, I must always be fed. The finger I touch, will soon turn red. What am I?": "Fire",
+    "I am not alive, but I grow. I don't have lungs, but I need air. I don't have a mouth, but water kills me. What am I?": "Fire",
+    "What has a heart that doesn't beat?": "Artichoke",
+    "What is so fragile that saying its name breaks it?": "Silence"
+}
+
+riddle_keys = list(riddles.keys())  # Convert the dictionary keys into a list.
+
+random.shuffle(riddle_keys)  # Shuffle the list of riddle keys.
+
+score = 0
+
+for riddle_key in riddle_keys:
+    print(riddle_key)
+    user_answer = input("Answer: ").lower()
+    if user_answer == riddles[riddle_key].lower():
+        print("Correct!")
+        score += 1
+    else:
+        print("Wrong answer. Correct answer: " + riddles[riddle_key])
+
+print("Game over! Your score is: " + str(score))
diff --git a/Rock Paper Scissors Game/main.py b/Rock Paper Scissors Game/main.py
new file mode 100644
index 00000000..f6052faa
--- /dev/null
+++ b/Rock Paper Scissors Game/main.py	
@@ -0,0 +1,87 @@
+#Rock Paper Scissors game by marsian
+print("\n\n\nRock Paper Scissors by marsian83\n\npresss Ctrl+. when you feel like exitting the game.")
+input("\n\n<<PRESS ENTER TO BEGIN>>\n")
+print("\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
+
+#Framework declaration
+from time import sleep
+from random import choice
+def game():
+    print("\n\n\n\n\n\n\n\nDecide your move, enter \"R\" for Rock, \"S\" for Scissors and \"P\"for Paper")
+    tempVal=input()
+    while tempVal != 'R' and tempVal != 'S' and tempVal != 'P' and tempVal != 'r' and tempVal != 's' and tempVal != 'p':
+        print("Decide your move, enter \"R\" for Rock, \"S\" for Scissors and \"P\"for Paper")
+        tempVal=input();
+    sleep(0.13)
+    if tempVal == "R" or tempVal == "r":
+        Pmove=1
+    elif tempVal == "P" or tempVal == "p":
+        Pmove=2
+    elif tempVal == "S" or tempVal == "s":
+        Pmove=3
+    else:
+        print("Custom_ERROR-01 : can't recognize user's input")
+        raise SystemExit(0);
+    sleep(0.13)
+    Cmove=choice(MoveSet)
+    if Cmove == 1:
+        cpumove='Rock'
+    elif Cmove == 2:
+        cpumove='Paper'
+    elif Cmove == 3:
+        cpumove='Scissor'
+    else:
+        print("Custom_ERROR-00 : CPU's move unrecognizable")
+        raise SystemExit(0)
+    del tempVal;
+    sleep(0.038)
+    return Cmove, Pmove, cpumove
+def decisive(Cmove,Pmove):
+    if [Cmove,Pmove] == [1,3] or [Cmove,Pmove] == [2,1] or [Cmove,Pmove] == [3,2]:
+        winner=1
+    elif [Cmove,Pmove] == [1,2] or [Cmove,Pmove] == [2,3] or [Cmove,Pmove] == [3,1]:
+        winner=2
+    elif [Cmove,Pmove] == [1,1] or [Cmove,Pmove] == [2,2] or [Cmove,Pmove] == [3,3]:
+        winner=0
+    else:
+        print("Custom_ERROR-03 : Set [cpumove,playermove] was assigned an unexpected value")
+        raise SystemExit(0)
+    return winner
+def Scoreboard(winner,cm,cs,ps):
+    if winner == 1:
+        print("\nCPU won the round by choosing",cm)
+        cs=cs+1
+    elif winner == 2:
+        print("\nPlayer won the round!")
+        ps=ps+1
+    else:
+        print("Custom_ERROR-02 : Scoreboard function recieved explicit values")
+        raise SystemExit(0)
+    print("\nSession Score:")
+    print("Player : ",ps)
+    print("CPU : ",cs)
+    return cs, ps
+
+#Variable declaration
+MoveSet = [1,2,3]
+Cmove=0
+Pmove=0
+Cscore=0
+Pscore=0
+
+#Driver Code
+while True:
+    Cmove,Pmove,cpumove=game()
+    winner=decisive(Cmove,Pmove)
+    while winner == 0:
+        print("WoW! A Draw!\nBoth Player and CPU have chosen",cpumove)
+        print("let's go again")
+        Cmove,Pmove,cpumove=game()
+        winner=decisive(Cmove,Pmove)
+    sleep(0.13)
+    cmCache=cpumove;
+    print("CPU - ",cmCache)
+    RoundWinner=winner
+    cs,ps=Scoreboard(RoundWinner,cmCache,Cscore,Pscore)
+    Cscore=cs; Pscore=ps
+    input("<<< PRESS ENTER TO CONTINUE >>>");
diff --git a/Rock Paper Scissors Game/readem.md b/Rock Paper Scissors Game/readem.md
new file mode 100644
index 00000000..5d116fa1
--- /dev/null
+++ b/Rock Paper Scissors Game/readem.md	
@@ -0,0 +1,3 @@
+## Rock Paper Scissor Game
+
+This is a basic Rock Paper Scissor Game implementation.
\ No newline at end of file
diff --git a/SNAKE/readme.md b/SNAKE/readme.md
new file mode 100644
index 00000000..60d3a2b3
--- /dev/null
+++ b/SNAKE/readme.md
@@ -0,0 +1,3 @@
+## Snake game
+
+This is a basic snake game implementation
\ No newline at end of file
diff --git a/SNAKE/snake_game.py b/SNAKE/snake_game.py
new file mode 100644
index 00000000..4812c98b
--- /dev/null
+++ b/SNAKE/snake_game.py
@@ -0,0 +1,132 @@
+import turtle as t
+import random
+ 
+w = 500 # Width of box
+h = 500 # Height of box
+food_size = 10 # Size of food
+delay = 100 # in millisecond
+
+# Values by which snake will move in direction when given direction
+offsets = {
+    "up": (0, 20),
+    "down": (0,-20),
+    "left": (-20,0),
+    "right": (20,0)
+}
+
+global SCORE
+SCORE = 0
+# Default postion of game scene
+
+def reset():
+    global snake, snake_dir, food_position, pen
+ 
+    snake = [[0,0],[0,20],[0,40],[0,60],[0,80]]
+    snake_dir = "up" #default snake direction
+    food_position = get_random_food_position()
+    food.goto(food_position) # render food on scene
+    move_snake()
+
+def move_snake():
+    global snake_dir,SCORE
+ 
+    new_head = snake[-1].copy()
+    new_head[0] = snake[-1][0] + offsets[snake_dir][0]
+    new_head[1] = snake[-1][1] + offsets[snake_dir][1]
+    
+    if new_head in snake[:-1]:
+        print(SCORE)
+        reset()
+    else:
+        snake.append(new_head)
+ 
+     
+        if not food_collision():
+            snake.pop(0)
+ 
+        if snake[-1][0] > w / 2:
+            snake[-1][0] -= w
+        elif snake[-1][0] < - w / 2:
+            snake[-1][0] += w
+        elif snake[-1][1] > h / 2:
+            snake[-1][1] -= h
+        elif snake[-1][1] < -h / 2:
+            snake[-1][1] += h
+
+        pen.clearstamps()
+      
+        for segment in snake:
+            pen.goto(segment[0], segment[1])
+            pen.stamp()
+       
+        screen.update() 
+        t.ontimer(move_snake, delay)
+ 
+# If snake collides with food
+def food_collision():
+    global food_position, SCORE
+    if get_distance(snake[-1], food_position) < 20:
+        SCORE += 10
+        food_position = get_random_food_position()
+        food.goto(food_position)
+        return True
+    return False
+ 
+# Random position for food
+def get_random_food_position():
+    x = random.randint(- w / 2 + food_size, w / 2 - food_size)
+    y = random.randint(- h / 2 + food_size, h / 2 - food_size)
+    return (x, y)
+ 
+
+def get_distance(pos1, pos2):
+    x1, y1 = pos1
+    x2, y2 = pos2
+    distance = ((y2 - y1) ** 2 + (x2 - x1) ** 2) ** 0.5
+    return distance
+  
+# Control
+def go_up():
+    global snake_dir
+    if snake_dir != "down":
+        snake_dir = "up"
+def go_down():
+    global snake_dir
+    if snake_dir != "up":
+        snake_dir = "down"
+def go_left():
+    global snake_dir
+    if snake_dir != "right":
+        snake_dir = "left"
+def go_right():
+    global snake_dir
+    if snake_dir != "left":
+        snake_dir = "right"
+
+#define screen setup
+screen = t.Screen()
+screen.setup(w, h)
+screen.title("Snake Game")
+screen.bgcolor("lightgrey")
+screen.tracer(0)
+
+#define snake setup
+pen = t.Turtle("square")
+pen.penup()
+
+#define food setup
+food = t.Turtle()
+food.shape("circle")
+food.color("red")
+food.shapesize(food_size / 20)
+food.penup()
+
+#define control setup
+screen.listen()
+screen.onkey(go_up, "Up")
+screen.onkey(go_right, "Right")
+screen.onkey(go_down, "Down")
+screen.onkey(go_left, "Left")
+
+reset()
+t.done()
diff --git a/Screen_Recording_App/main.py b/Screen_Recording_App/main.py
new file mode 100644
index 00000000..77c732f1
--- /dev/null
+++ b/Screen_Recording_App/main.py
@@ -0,0 +1,30 @@
+import cv2
+import numpy as np
+import pyautogui
+
+SCREEN_SIZE = tuple(pyautogui.size())
+
+# Define the codec and create VideoWriter object
+fourcc = cv2.VideoWriter_fourcc(*'XVID')
+out = cv2.VideoWriter('video.avi', fourcc, 20.0, (SCREEN_SIZE))
+webcam = cv2.VideoCapture(0)
+
+while True:
+    img = pyautogui.screenshot()
+    img = np.array(img)
+    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
+
+    _, frame = webcam.read()
+    fr_height, fr_width, _ = frame.shape
+
+    img[0:fr_height, 0: fr_width, :] = frame[0:fr_height, 0: fr_width, :]
+    cv2.imshow('frame', img)
+    out.write(img)
+
+    # Press 'q' to quit
+    if cv2.waitKey(1) & 0xFF == ord('q'):
+        print("Recording Stopped")
+        break
+
+out.release()
+cv2.destroyAllWindows()
diff --git a/Screen_Recording_App/readme.md b/Screen_Recording_App/readme.md
new file mode 100644
index 00000000..7cbd9b1f
--- /dev/null
+++ b/Screen_Recording_App/readme.md
@@ -0,0 +1,36 @@
+
+## Screen Recording with Webcam Overlay
+
+This Python script allows you to record your screen while overlaying the webcam feed. It uses OpenCV for screen recording and capturing the webcam feed, and PyAutoGUI for taking screenshots.
+
+## Prerequisites
+
+Make sure you have the following libraries installed:
+
+- OpenCV (cv2)
+- NumPy (numpy)
+- PyAutoGUI (pyautogui)
+
+You can install these libraries using pip:
+
+
+pip install opencv-python numpy pyautogui
+
+
+## How to Use
+
+Run the script by executing python screen_recorder.py.
+
+The script will start recording your screen with a webcam overlay. You can adjust the parameters as needed in the script, such as the output file name ('video.avi'), codec ('XVID'), frame rate (20.0), and screen size.
+
+To stop the recording, press 'q'.
+
+The recorded video will be saved as video.avi in the current directory.
+
+## Customization
+
+You can customize the following parameters in the script:
+
+out: Change the output file name and codec.
+SCREEN_SIZE: Modify the screen size to match your display.
+frame rate: Adjust the frame rate to control the video quality and size.
\ No newline at end of file
diff --git a/Sudoku-Solver/LICENSE b/Sudoku-Solver/LICENSE
new file mode 100644
index 00000000..a7058b31
--- /dev/null
+++ b/Sudoku-Solver/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Dhruv Panchal
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Sudoku-Solver/README.md b/Sudoku-Solver/README.md
new file mode 100644
index 00000000..5f901772
--- /dev/null
+++ b/Sudoku-Solver/README.md
@@ -0,0 +1,7 @@
+<h1>A Sudoku Solver using Python.</h1>
+
+Run the SudokuGUI file directly in your Terminal using 
+
+--> python SudokuGUI.py
+        or
+--> python3 SudokuGUI.py
\ No newline at end of file
diff --git a/Sudoku-Solver/SudokuGUI.py b/Sudoku-Solver/SudokuGUI.py
new file mode 100644
index 00000000..10b4d950
--- /dev/null
+++ b/Sudoku-Solver/SudokuGUI.py
@@ -0,0 +1,316 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+from sudokutools import valid, solve, find_empty
+from copy import deepcopy
+from sys import exit
+import pygame
+import time
+import random
+pygame.init()
+
+
+def generate():
+
+    while True:  
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                exit()
+        board = [[0 for i in range(9)] for j in range(9)]
+
+        for i in range(9):
+            for j in range(9):
+                if random.randint(1, 10) >= 5:
+                    board[i][j] = random.randint(1, 9) 
+                    if valid(board, (i, j), board[i][j]):
+                        continue
+                    else:
+                        board[i][j] = 0
+        partialBoard = deepcopy(board)  
+        if solve(board):
+            return partialBoard
+
+
+class Board:
+
+    def __init__(self, window):
+        self.board = generate()
+        self.solvedBoard = deepcopy(self.board)
+        solve(self.solvedBoard)
+        self.tiles = [[Tile(self.board[i][j], window, i * 60, j * 60)
+                      for j in range(9)] for i in range(9)]
+        self.window = window
+
+    def draw_board(self):
+
+        for i in range(9):
+            for j in range(9):
+                if j % 3 == 0 and j != 0:  
+                    pygame.draw.line(self.window, (0, 0, 0), (j // 3
+                            * 180, 0), (j // 3 * 180, 540), 4)
+
+                if i % 3 == 0 and i != 0: 
+                    pygame.draw.line(self.window, (0, 0, 0), (0, i // 3
+                            * 180), (540, i // 3 * 180), 4)
+
+                self.tiles[i][j].draw((0, 0, 0), 1)
+
+                if self.tiles[i][j].value != 0:  
+                    self.tiles[i][j].display(self.tiles[i][j].value,
+                            (21 + j * 60, 16 + i * 60), (0, 0, 0))  
+
+
+        pygame.draw.line(self.window, (0, 0, 0), (0, (i + 1) // 3
+                         * 180), (540, (i + 1) // 3 * 180), 4)
+
+    def deselect(self, tile):
+
+        for i in range(9):
+            for j in range(9):
+                if self.tiles[i][j] != tile:
+                    self.tiles[i][j].selected = False
+
+    def redraw(
+        self,
+        keys,
+        wrong,
+        time,
+        ):
+
+        self.window.fill((255, 255, 255))
+        self.draw_board()
+        for i in range(9):
+            for j in range(9):
+                if self.tiles[j][i].selected: 
+                    self.tiles[j][i].draw((50, 205, 50), 4)
+                elif self.tiles[i][j].correct:
+
+                    self.tiles[j][i].draw((34, 139, 34), 4)
+                elif self.tiles[i][j].incorrect:
+
+                    self.tiles[j][i].draw((255, 0, 0), 4)
+
+        if len(keys) != 0:  
+            for value in keys:
+                self.tiles[value[0]][value[1]].display(keys[value], (21
+                        + value[0] * 60, 16 + value[1] * 60), (128,
+                        128, 128))
+
+        if wrong > 0:
+            font = pygame.font.SysFont('Bauhaus 93', 30) 
+            text = font.render('X', True, (255, 0, 0))
+            self.window.blit(text, (10, 554))
+
+            font = pygame.font.SysFont('Bahnschrift', 40)  
+            text = font.render(str(wrong), True, (0, 0, 0))
+            self.window.blit(text, (32, 542))
+
+        font = pygame.font.SysFont('Bahnschrift', 40)  
+        text = font.render(str(time), True, (0, 0, 0))
+        self.window.blit(text, (388, 542))
+        pygame.display.flip()
+
+    def visualSolve(self, wrong, time):
+
+        for event in pygame.event.get():  
+            if event.type == pygame.QUIT:
+                exit()
+
+        empty = find_empty(self.board)
+        if not empty:
+            return True
+
+        for nums in range(9):
+            if valid(self.board, (empty[0], empty[1]), nums + 1):
+                self.board[empty[0]][empty[1]] = nums + 1
+                self.tiles[empty[0]][empty[1]].value = nums + 1
+                self.tiles[empty[0]][empty[1]].correct = True
+                pygame.time.delay(63)  
+                self.redraw({}, wrong, time)
+
+                if self.visualSolve(wrong, time):
+                    return True
+
+                self.board[empty[0]][empty[1]] = 0
+                self.tiles[empty[0]][empty[1]].value = 0
+                self.tiles[empty[0]][empty[1]].incorrect = True
+                self.tiles[empty[0]][empty[1]].correct = False
+                pygame.time.delay(63)
+                self.redraw({}, wrong, time)
+
+    def hint(self, keys):
+
+        while True: 
+            i = random.randint(0, 8)
+            j = random.randint(0, 8)
+            if self.board[i][j] == 0:  
+                if (j, i) in keys:
+                    del keys[(j, i)]
+                self.board[i][j] = self.solvedBoard[i][j]
+                self.tiles[i][j].value = self.solvedBoard[i][j]
+                return True
+            elif self.board == self.solvedBoard:
+
+                return False
+
+
+class Tile:
+
+
+    def __init__(
+        self,
+        value,
+        window,
+        x1,
+        y1,
+        ):
+        self.value = value
+        self.window = window
+        self.rect = pygame.Rect(x1, y1, 60, 60)  
+        self.selected = False
+        self.correct = False
+        self.incorrect = False
+
+    def draw(self, color, thickness):
+
+        pygame.draw.rect(self.window, color, self.rect, thickness)
+
+    def display(
+        self,
+        value,
+        position,
+        color,
+        ):
+
+        font = pygame.font.SysFont('lato', 45)
+        text = font.render(str(value), True, color)
+        self.window.blit(text, position)
+
+    def clicked(self, mousePos):
+
+        if self.rect.collidepoint(mousePos):
+            self.selected = True
+        return self.selected
+
+
+def main():
+
+    screen = pygame.display.set_mode((540, 590))
+    screen.fill((255, 255, 255))
+    pygame.display.set_caption('Sudoku Solver')
+    icon = pygame.image.load('assets/thumbnail.png')
+    pygame.display.set_icon(icon)
+
+    font = pygame.font.SysFont('Bahnschrift', 40)
+    text = font.render('Generating', True, (0, 0, 0))
+    screen.blit(text, (175, 245))
+
+    font = pygame.font.SysFont('Bahnschrift', 40)
+    text = font.render('Random Grid', True, (0, 0, 0))
+    screen.blit(text, (156, 290))
+    pygame.display.flip()
+
+    wrong = 0
+    board = Board(screen)
+    selected = (-1, -1)  
+    keyDict = {}
+    running = True
+    startTime = time.time()
+    while running:
+        elapsed = time.time() - startTime
+        passedTime = time.strftime('%H:%M:%S', time.gmtime(elapsed))
+
+        if board.board == board.solvedBoard:  
+            for i in range(9):
+                for j in range(9):
+                    board.tiles[i][j].selected = False
+                    running = False
+
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                exit()  
+            elif event.type == pygame.MOUSEBUTTONUP:
+
+                mousePos = pygame.mouse.get_pos()
+                for i in range(9):
+                    for j in range(9):
+                        if board.tiles[i][j].clicked(mousePos):
+                            selected = (i, j)
+                            board.deselect(board.tiles[i][j])  
+            elif event.type == pygame.KEYDOWN:
+
+                if board.board[selected[1]][selected[0]] == 0 \
+                    and selected != (-1, -1):
+                    if event.key == pygame.K_1:
+                        keyDict[selected] = 1
+
+                    if event.key == pygame.K_2:
+                        keyDict[selected] = 2
+
+                    if event.key == pygame.K_3:
+                        keyDict[selected] = 3
+
+                    if event.key == pygame.K_4:
+                        keyDict[selected] = 4
+
+                    if event.key == pygame.K_5:
+                        keyDict[selected] = 5
+
+                    if event.key == pygame.K_6:
+                        keyDict[selected] = 6
+
+                    if event.key == pygame.K_7:
+                        keyDict[selected] = 7
+
+                    if event.key == pygame.K_8:
+                        keyDict[selected] = 8
+
+                    if event.key == pygame.K_9:
+                        keyDict[selected] = 9
+                    elif event.key == pygame.K_BACKSPACE or event.key \
+                        == pygame.K_DELETE:
+
+                        if selected in keyDict:
+                            board.tiles[selected[1]][selected[0]].value = \
+                                0
+                            del keyDict[selected]
+                    elif event.key == pygame.K_RETURN:
+
+                        if selected in keyDict:
+                            if keyDict[selected] \
+                                != board.solvedBoard[selected[1]][selected[0]]:  
+                                wrong += 1
+                                board.tiles[selected[1]][selected[0]].value = \
+                                    0
+                                del keyDict[selected]
+                                break
+
+                            board.tiles[selected[1]][selected[0]].value = \
+                                keyDict[selected]  
+                            board.board[selected[1]][selected[0]] = \
+                                keyDict[selected] 
+                            del keyDict[selected]
+
+                if event.key == pygame.K_h:
+                    board.hint(keyDict)
+
+                if event.key == pygame.K_SPACE:
+                    for i in range(9):
+                        for j in range(9):
+                            board.tiles[i][j].selected = False
+                    keyDict = {}  
+                    board.visualSolve(wrong, passedTime)
+                    for i in range(9):
+                        for j in range(9):
+                            board.tiles[i][j].correct = False
+                            board.tiles[i][j].incorrect = False 
+                    running = False
+
+        board.redraw(keyDict, wrong, passedTime)
+    while True:  
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                return
+
+
+main()
+pygame.quit()
\ No newline at end of file
diff --git a/Sudoku-Solver/__pycache__/sudokutools.cpython-310.pyc b/Sudoku-Solver/__pycache__/sudokutools.cpython-310.pyc
new file mode 100644
index 00000000..d7c14659
Binary files /dev/null and b/Sudoku-Solver/__pycache__/sudokutools.cpython-310.pyc differ
diff --git a/Sudoku-Solver/assets/Entering Values.gif b/Sudoku-Solver/assets/Entering Values.gif
new file mode 100644
index 00000000..6461a95c
Binary files /dev/null and b/Sudoku-Solver/assets/Entering Values.gif differ
diff --git a/Sudoku-Solver/assets/Visualizer.gif b/Sudoku-Solver/assets/Visualizer.gif
new file mode 100644
index 00000000..a4bdecef
Binary files /dev/null and b/Sudoku-Solver/assets/Visualizer.gif differ
diff --git a/Sudoku-Solver/assets/thumbnail.png b/Sudoku-Solver/assets/thumbnail.png
new file mode 100644
index 00000000..98174f6f
Binary files /dev/null and b/Sudoku-Solver/assets/thumbnail.png differ
diff --git a/Sudoku-Solver/requirements.txt b/Sudoku-Solver/requirements.txt
new file mode 100644
index 00000000..7c36c822
--- /dev/null
+++ b/Sudoku-Solver/requirements.txt
@@ -0,0 +1 @@
+pygame==2.0.1
diff --git a/Sudoku-Solver/sudokutools.py b/Sudoku-Solver/sudokutools.py
new file mode 100644
index 00000000..435b76e4
--- /dev/null
+++ b/Sudoku-Solver/sudokutools.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+
+def print_board(board):
+    '''Prints the board'''
+
+    boardString = ''
+    for i in range(9):
+        for j in range(9):
+            boardString += str(board[i][j]) + ' '
+            if (j + 1) % 3 == 0 and j != 0 and j + 1 != 9:
+                boardString += '| '
+
+            if j == 8:
+                boardString += '\n'
+
+            if j == 8 and (i + 1) % 3 == 0 and i + 1 != 9:
+                boardString += '- - - - - - - - - - - \n'
+    print(boardString)
+
+
+def find_empty(board):
+    '''Finds an empty cell and returns its position as a tuple'''
+
+    for i in range(9):
+        for j in range(9):
+            if board[i][j] == 0:
+                return (i, j)
+
+
+def valid(board, pos, num):
+    '''Whether a number is valid in that cell, returns a bool'''
+
+    for i in range(9):
+        if board[i][pos[1]] == num and (i, pos[1]) != pos:  # make sure it isn't the same number we're checking for by comparing coords
+            return False
+
+    for j in range(9):
+        if board[pos[0]][j] == num and (pos[0], j) != pos:  # Same row but not same number
+            return False
+
+    start_i = pos[0] - pos[0] % 3  # ex. 5-5%3 = 3 and thats where the grid starts
+    start_j = pos[1] - pos[1] % 3
+    for i in range(3):
+        for j in range(3):  # adds i and j as needed to go from start of grid to where we need to be
+            if board[start_i + i][start_j + j] == num and (start_i + i,
+                    start_j + j) != pos:
+                return False
+    return True
+
+
+def solve(board):
+    '''Solves the Sudoku board via the backtracking algorithm'''
+
+    empty = find_empty(board)
+    if not empty:  # no empty spots are left so the board is solved
+        return True
+
+    for nums in range(9):
+        if valid(board, empty, nums + 1):
+            board[empty[0]][empty[1]] = nums + 1
+
+            if solve(board):  # recursive step
+                return True
+            board[empty[0]][empty[1]] = 0  # this number is wrong so we set it back to 0
+    return False
+
+
+if __name__ == '__main__':
+    board =  [
+        [0, 0, 0, 0, 0, 0, 2, 0, 0],
+        [0, 8, 0, 0, 0, 7, 0, 9, 0],
+        [6, 0, 2, 0, 0, 0, 5, 0, 0],
+        [0, 7, 0, 0, 6, 0, 0, 0, 0],
+        [0, 0, 0, 9, 0, 1, 0, 0, 0],
+        [0, 0, 0, 0, 2, 0, 0, 4, 0],
+        [0, 0, 5, 0, 0, 0, 6, 0, 3],
+        [0, 9, 0, 4, 0, 0, 0, 7, 0],
+        [0, 0, 6, 0, 0, 0, 0, 0, 0]
+    ]
+    solve(board)
+    print_board(board)
diff --git a/Text-to-Speech/Demo.png b/Text-to-Speech/Demo.png
new file mode 100644
index 00000000..bcac60a4
Binary files /dev/null and b/Text-to-Speech/Demo.png differ
diff --git a/Text-to-Speech/Text-to-speech.py b/Text-to-Speech/Text-to-speech.py
new file mode 100644
index 00000000..f86c3268
--- /dev/null
+++ b/Text-to-Speech/Text-to-speech.py
@@ -0,0 +1,32 @@
+import tkinter as tk
+from tkinter import * 
+import pyttsx3
+
+engine = pyttsx3.init(driverName='espeak')
+
+
+def speaknow():
+    engine.say(textv.get())
+    engine.runAndWait()
+    engine.stop()
+
+root=Tk()
+
+textv=StringVar()
+
+obj=LabelFrame(root,text="Text to speech",font=20,bd=1)
+obj.pack(fill="both",expand="yes",padx=10,pady=10)
+
+lb1=Label(obj,text="Text",font=30)
+lb1.pack(side=tk.LEFT,padx=5)
+
+text=Entry(obj,textvariable=textv,font=30,width=25,bd=5)
+text.pack(side=tk.LEFT,padx=10)
+
+btn=Button(obj,text="Speak",font=20,bg="green",fg="white",command=speaknow)
+btn.pack(side=tk.LEFT,padx=10)
+
+root.title("Text to speech")
+root.geometry("480x200")
+root.resizable(False,False)
+root.mainloop()
\ No newline at end of file
diff --git a/Text-to-Speech/requirements.txt b/Text-to-Speech/requirements.txt
new file mode 100644
index 00000000..8973ac8b
--- /dev/null
+++ b/Text-to-Speech/requirements.txt
@@ -0,0 +1,4 @@
+tkinter
+pyttsx3
+espeak-ng  # Only if using the espeak driver
+
diff --git a/Tkinter Clock/README.md b/Tkinter Clock/README.md
new file mode 100644
index 00000000..622252f3
--- /dev/null
+++ b/Tkinter Clock/README.md	
@@ -0,0 +1,35 @@
+<h1> Tkinter Alarm Clock </h1>
+<h3>Introduction</h3>
+<p>Tkinter Alarm Clock is a simple desktop application built using the Tkinter library in Python. It allows users to set alarms and receive notifications when the alarm time is reached.</p>
+
+<h3>Requirements</h3>
+
+<p>To run the Tkinter Alarm Clock application, ensure that you have the following installed:</p>
+
+<ul style="list-style-type:circle">
+<li>Python (version 3.x)</li>
+<li>Tkinter library</li>
+<li>winsound library (for sound playback on Windows)</li>
+</ul>
+
+<h3>Usage</h3>
+
+<p>Once the Tkinter Alarm Clock application is running, follow these steps to set an alarm:</p>
+<ul style= "list-style-type:circle">
+
+<li>Enter the desired alarm time in the format HH:MM:SS (24-hour format) in the corresponding text fields for hours, minutes, and seconds.</li><
+
+<li>Click the "Set Your Alarm" button to set the alarm.</li>
+
+<li>The application will continuously check the current time against the set alarm time. When the alarm time is reached, it will play a sound (if available) and display the current time in the terminal.</li>
+
+<li>To stop the alarm, close the application window.</li>
+
+</ul>
+
+<h3>Conclusion</h3>
+
+<p>The Tkinter Alarm Clock application provides a simple and convenient way to set alarms and receive notifications. You can use it as is or customize it to suit your specific requirements. Enjoy using the Tkinter Alarm Clock!</p>
+
+
+
diff --git a/Tkinter Clock/main.py.py b/Tkinter Clock/main.py.py
new file mode 100644
index 00000000..ae1aee03
--- /dev/null
+++ b/Tkinter Clock/main.py.py	
@@ -0,0 +1,34 @@
+from tkinter import *
+import datetime
+import time
+import winsound
+
+def Alarm(set_alarm_timer):
+    while True:
+        time.sleep(1)
+        actual_time = datetime.datetime.now()
+        cur_time = actual_time.strftime("%H:%M:%S")
+        cur_date = actual_time.strftime("%d/%m/%Y")
+        msg="Current Time: "+str(cur_time)
+        if cur_time == set_alarm_timer:
+            winsound.PlaySound("Music.wav",winsound.SND_ASYNC)
+            break
+def get_alarm_time():
+    alarm_set_time = f"{hour.get()}:{min.get()}:{sec.get()}"
+    Alarm(alarm_set_time)
+window = Tk()
+window.title("Alarm Clock")
+window.geometry("400x160")
+window.config(bg="#922B21")
+window.resizable(width=False,height=False)
+time_format=Label(window, text= "Remember to set time in 24 hour format!", fg="white",bg="#922B21",font=("Arial",15)).place(x=20,y=120) 
+addTime = Label(window,text = "Hour     Min     Sec",font=60,fg="white",bg="black").place(x = 210)
+setYourAlarm = Label(window,text = "Set Time for Alarm: ",fg="white",bg="#922B21",relief = "solid",font=("Helevetica",15,"bold")).place(x=10, y=40)
+hour = StringVar()
+min = StringVar()
+sec = StringVar()
+hourTime= Entry(window,textvariable = hour,bg = "#48C9B0",width = 4,font=(20)).place(x=210,y=40)
+minTime= Entry(window,textvariable = min,bg = "#48C9B0",width = 4,font=(20)).place(x=270,y=40)
+secTime = Entry(window,textvariable = sec,bg = "#48C9B0",width = 4,font=(20)).place(x=330,y=40)
+submit = Button(window,text = "Set Your Alarm",fg="Black",bg="#D4AC0D",width = 15,command = get_alarm_time,font=(20)).place(x =100,y=80)
+window.mainloop()
\ No newline at end of file
diff --git a/Turtle Crossing Capstone Game/__pycache__/car_manager.cpython-310.pyc b/Turtle Crossing Capstone Game/__pycache__/car_manager.cpython-310.pyc
new file mode 100644
index 00000000..2ea11ea4
Binary files /dev/null and b/Turtle Crossing Capstone Game/__pycache__/car_manager.cpython-310.pyc differ
diff --git a/Turtle Crossing Capstone Game/__pycache__/player.cpython-310.pyc b/Turtle Crossing Capstone Game/__pycache__/player.cpython-310.pyc
new file mode 100644
index 00000000..0cfa842c
Binary files /dev/null and b/Turtle Crossing Capstone Game/__pycache__/player.cpython-310.pyc differ
diff --git a/Turtle Crossing Capstone Game/__pycache__/scoreboard.cpython-310.pyc b/Turtle Crossing Capstone Game/__pycache__/scoreboard.cpython-310.pyc
new file mode 100644
index 00000000..da4279e8
Binary files /dev/null and b/Turtle Crossing Capstone Game/__pycache__/scoreboard.cpython-310.pyc differ
diff --git a/pokemone_battle.py/README b/pokemone_battle.py/README
new file mode 100644
index 00000000..479369dc
--- /dev/null
+++ b/pokemone_battle.py/README
@@ -0,0 +1,2 @@
+A simple pokemon battle game with type advantages.
+add more pokemon and moves if you want!
\ No newline at end of file
diff --git a/pokemone_battle.py/main.py b/pokemone_battle.py/main.py
new file mode 100644
index 00000000..4cd9ab6e
--- /dev/null
+++ b/pokemone_battle.py/main.py
@@ -0,0 +1,159 @@
+import time
+import numpy as np
+import sys
+
+# Delay printing
+
+def delay_print(s):
+    # print one character at a time
+    # https://stackoverflow.com/questions/9246076/how-to-print-one-character-at-a-time-on-one-line
+    for c in s:
+        sys.stdout.write(c)
+        sys.stdout.flush()
+        time.sleep(0.05)
+
+# Create the class
+class Pokemon:
+    def __init__(self, name, types, moves, EVs, health='==================='):
+        # save variables as attributes
+        self.name = name
+        self.types = types
+        self.moves = moves
+        self.attack = EVs['ATTACK']
+        self.defense = EVs['DEFENSE']
+        self.health = health
+        self.bars = 20 # Amount of health bars
+
+
+    def fight(self, Pokemon2):
+        # Allow two pokemon to fight each other
+
+        # Print fight information
+        print("-----POKEMONE BATTLE-----")
+        print(f"\n{self.name}")
+        print("TYPE/", self.types)
+        print("ATTACK/", self.attack)
+        print("DEFENSE/", self.defense)
+        print("LVL/", 3*(1+np.mean([self.attack,self.defense])))
+        print("\nVS")
+        print(f"\n{Pokemon2.name}")
+        print("TYPE/", Pokemon2.types)
+        print("ATTACK/", Pokemon2.attack)
+        print("DEFENSE/", Pokemon2.defense)
+        print("LVL/", 3*(1+np.mean([Pokemon2.attack,Pokemon2.defense])))
+
+        time.sleep(2)
+
+        # Consider type advantages
+        version = ['Fire', 'Water', 'Grass']
+        for i,k in enumerate(version):
+            if self.types == k:
+                # Both are same type
+                if Pokemon2.types == k:
+                    string_1_attack = '\nIts not very effective...'
+                    string_2_attack = '\nIts not very effective...'
+
+                # Pokemon2 is STRONG
+                if Pokemon2.types == version[(i+1)%3]:
+                    Pokemon2.attack *= 2
+                    Pokemon2.defense *= 2
+                    self.attack /= 2
+                    self.defense /= 2
+                    string_1_attack = '\nIts not very effective...'
+                    string_2_attack = '\nIts super effective!'
+
+                # Pokemon2 is WEAK
+                if Pokemon2.types == version[(i+2)%3]:
+                    self.attack *= 2
+                    self.defense *= 2
+                    Pokemon2.attack /= 2
+                    Pokemon2.defense /= 2
+                    string_1_attack = '\nIts super effective!'
+                    string_2_attack = '\nIts not very effective...'
+
+
+        # Now for the actual fighting...
+        # Continue while pokemon still have health
+        while (self.bars > 0) and (Pokemon2.bars > 0):
+            # Print the health of each pokemon
+            print(f"\n{self.name}\t\tHLTH\t{self.health}")
+            print(f"{Pokemon2.name}\t\tHLTH\t{Pokemon2.health}\n")
+
+            print(f"Go {self.name}!")
+            for i, x in enumerate(self.moves):
+                print(f"{i+1}.", x)
+            index = int(input('Pick a move: '))
+            delay_print(f"\n{self.name} used {self.moves[index-1]}!")
+            time.sleep(1)
+            delay_print(string_1_attack)
+
+            # Determine damage
+            Pokemon2.bars -= self.attack
+            Pokemon2.health = ""
+
+            # Add back bars plus defense boost
+            for j in range(int(Pokemon2.bars+.1*Pokemon2.defense)):
+                Pokemon2.health += "="
+
+            time.sleep(1)
+            print(f"\n{self.name}\t\tHLTH\t{self.health}")
+            print(f"{Pokemon2.name}\t\tHLTH\t{Pokemon2.health}\n")
+            time.sleep(.5)
+
+            # Check to see if Pokemon fainted
+            if Pokemon2.bars <= 0:
+                delay_print("\n..." + Pokemon2.name + ' fainted.')
+                break
+
+            # Pokemon2s turn
+
+            print(f"Go {Pokemon2.name}!")
+            for i, x in enumerate(Pokemon2.moves):
+                print(f"{i+1}.", x)
+            index = int(input('Pick a move: '))
+            delay_print(f"\n{Pokemon2.name} used {Pokemon2.moves[index-1]}!")
+            time.sleep(1)
+            delay_print(string_2_attack)
+
+            # Determine damage
+            self.bars -= Pokemon2.attack
+            self.health = ""
+
+            # Add back bars plus defense boost
+            for j in range(int(self.bars+.1*self.defense)):
+                self.health += "="
+
+            time.sleep(1)
+            print(f"{self.name}\t\tHLTH\t{self.health}")
+            print(f"{Pokemon2.name}\t\tHLTH\t{Pokemon2.health}\n")
+            time.sleep(.5)
+
+            # Check to see if Pokemon fainted
+            if self.bars <= 0:
+                delay_print("\n..." + self.name + ' fainted.')
+                break
+
+        money = np.random.choice(5000)
+        delay_print(f"\nOpponent paid you ${money}.\n")
+
+
+
+
+
+
+if __name__ == '__main__':
+    #Create Pokemon
+    Charizard = Pokemon('Charizard', 'Fire', ['Flamethrower', 'Fly', 'Blast Burn', 'Fire Punch'], {'ATTACK':12, 'DEFENSE': 8})
+    Blastoise = Pokemon('Blastoise', 'Water', ['Water Gun', 'Bubblebeam', 'Hydro Pump', 'Surf'],{'ATTACK': 10, 'DEFENSE':10})
+    Venusaur = Pokemon('Venusaur', 'Grass', ['Vine Wip', 'Razor Leaf', 'Earthquake', 'Frenzy Plant'],{'ATTACK':8, 'DEFENSE':12})
+
+    Charmander = Pokemon('Charmander', 'Fire', ['Ember', 'Scratch', 'Tackle', 'Fire Punch'],{'ATTACK':4, 'DEFENSE':2})
+    Squirtle = Pokemon('Squirtle', 'Water', ['Bubblebeam', 'Tackle', 'Headbutt', 'Surf'],{'ATTACK': 3, 'DEFENSE':3})
+    Bulbasaur = Pokemon('Bulbasaur', 'Grass', ['Vine Wip', 'Razor Leaf', 'Tackle', 'Leech Seed'],{'ATTACK':2, 'DEFENSE':4})
+
+    Charmeleon = Pokemon('Charmeleon', 'Fire', ['Ember', 'Scratch', 'Flamethrower', 'Fire Punch'],{'ATTACK':6, 'DEFENSE':5})
+    Wartortle = Pokemon('Wartortle', 'Water', ['Bubblebeam', 'Water Gun', 'Headbutt', 'Surf'],{'ATTACK': 5, 'DEFENSE':5})
+    Ivysaur = Pokemon('Ivysaur\t', 'Grass', ['Vine Wip', 'Razor Leaf', 'Bullet Seed', 'Leech Seed'],{'ATTACK':4, 'DEFENSE':6})
+
+
+    Charizard.fight(Squirtle) # Get them to fight
\ No newline at end of file
