Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback #1

Open
wants to merge 22 commits into
base: feedback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .gitignore
Binary file not shown.
29 changes: 24 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/AHFn7Vbn)
# Superjoin Hiring Assignment

### Welcome to Superjoin's hiring assignment! 🚀
Expand Down Expand Up @@ -44,11 +45,11 @@ Once you're done, make sure you **record a video** showing your project working.

We have a checklist at the bottom of this README file, which you should update as your progress with your assignment. It will help us evaluate your project.

- [ ] My code's working just fine! 🥳
- [ ] I have recorded a video showing it working and embedded it in the README ▶️
- [ ] I have tested all the normal working cases 😎
- [ ] I have even solved some edge cases (brownie points) 💪
- [ ] I added my very planned-out approach to the problem at the end of this README 📜
- [ 1] My code's working just fine! 🥳
- [ 1] I have recorded a video showing it working and embedded it in the README ▶️
- [ 1] I have tested all the normal working cases 😎
- [ 1] I have even solved some edge cases (brownie points) 💪
- [ 1] I added my very planned-out approach to the problem at the end of this README 📜

## Got Questions❓
Feel free to check the discussions tab, you might get some help there. Check out that tab before reaching out to us. Also, did you know, the internet is a great place to explore? 😛
Expand All @@ -59,3 +60,21 @@ All the best ✨.

## Developer's Section
*Add your video here, and your approach to the problem (optional). Leave some comments for us here if you want, we will be reading this :)*

Link to my video:
PART 1:Where I show changes made in the sheet refected in the database.
https://drive.google.com/file/d/1ZPTG-wu0tUdLDdQVFOPYpXcB56PvmbDJ/view?usp=sharing
PART 2: I forgot to show in the video how the changes made in the MySQL database is updated real time in the Google sheets, so adding part 2.
https://drive.google.com/file/d/1EOS9_-BsmHVXbCCuqtOoAT-7UYB2EAov/view?usp=sharing



APPROACH:
1)Used google sheets API to to read, write, and delete data in Google Sheets.
Howrver I wanted to write code from scratch to detect changes in the sheets, withput using API/App Script.The 2 functions used I have written below.
2)MySQL connector to connect to the MySQL database to perform CRUD operations
3)wrote 2 functions:
Google Sheets Watcher: To check the Google Sheet for changes (e.g., additions, updates, or deletions) and update the MySQL database accordingly.
MySQL Watcher: Continuously monitors the MySQL database and updates the Google Sheet whenever there are changes.
The two watchers run in separate threads to allow simultaneous monitoring and updating of both Google Sheets and the MySQL database.

Binary file not shown.
48 changes: 48 additions & 0 deletions database/mysql_connector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import mysql.connector

# Function to create a MySQL connection
def get_mysql_connection():
connection = mysql.connector.connect(
host='localhost', # Change to your MySQL host
user='root', # Replace with your MySQL username
password='DiapB2002', # Replace with your MySQL password
database='superjoin' # Replace with your database name
)
return connection

# Function to read data from the MySQL database
def read_mysql_data(query):
connection = get_mysql_connection()
cursor = connection.cursor()
cursor.execute(query)
result = cursor.fetchall()
cursor.close()
connection.close()
return result

# Function to write data to MySQL database
def write_mysql_data(query, values):
connection = get_mysql_connection()
cursor = connection.cursor()
cursor.execute(query, values)
connection.commit()
cursor.close()
connection.close()

# Update data in MySQL
def update_mysql_data(query, values):
connection = get_mysql_connection()
cursor = connection.cursor()
cursor.execute(query, values)
connection.commit()
cursor.close()
connection.close()

# Delete data in MySQL
def delete_mysql_data(query, params):
connection = get_mysql_connection() # Your connection details here
cursor = connection.cursor()
cursor.execute(query, params)
connection.commit()
cursor.close()
connection.close()
93 changes: 93 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from sheets.google_sheets_service import read_sheet_data, write_sheet_data, append_sheet_data, delete_sheet_data
from database.mysql_connector import read_mysql_data, write_mysql_data, update_mysql_data, delete_mysql_data
import time
from threading import Thread

# Define the Google Sheets ID and range
SPREADSHEET_ID = '1nQbDJhh8KLZbAW8iJh3zRokKrz52XJHQJ4sU-TDUMBE' # my google sheets ID
RANGE_NAME = 'Sheet1!A1:D' # The range of cells to read/write data

def clean_and_validate_data(row):
"""Clean and validate a row of data."""
id, name, age, city = row

# Ensure id is a string
id = str(id) if id else None

# Clean name and city (strip whitespace)
name = name.strip() if name else None
city = city.strip() if city else None

# Validate age: convert to int if possible, otherwise set to None
try:
age = int(age) if age else None
except ValueError:
age = None

return id, name, age, city

def watch_google_sheets():
last_known_state = {}
while True:
current_state = {row[0]: clean_and_validate_data(row) for row in read_sheet_data(SPREADSHEET_ID, RANGE_NAME)[1:] if len(row) >= 4}

# Check for changes
for id, row in current_state.items():
if id not in last_known_state or last_known_state[id] != row:
# Update or insert in MySQL
query = """
INSERT INTO your_table (id, name, age, city)
VALUES (%s, %s, %s, %s)
ON DUPLICATE KEY UPDATE name=%s, age=%s, city=%s
"""
write_mysql_data(query, (*row, row[1], row[2], row[3]))
print(f"Updated/Inserted row with id {id} in MySQL")

# Check for deletions
for id in set(last_known_state) - set(current_state):
delete_mysql_data("DELETE FROM your_table WHERE id=%s", (id,))
print(f"Deleted row with id {id} from MySQL")

# Update the last known state *after* processing
last_known_state = current_state.copy()

time.sleep(5) # Check every 5 seconds

def watch_mysql():
last_known_state = {}
while True:
mysql_query = "SELECT id, name, age, city FROM your_table"
current_state = {str(row[0]): clean_and_validate_data(row) for row in read_mysql_data(mysql_query)}

# Check for changes or additions
changes = []
for id, row in current_state.items():
if id not in last_known_state or last_known_state[id] != row:
changes.append(list(row))

if changes:
# Clear existing data in Google Sheets
delete_sheet_data(SPREADSHEET_ID, RANGE_NAME)

# Write headers
headers = [['id', 'name', 'age', 'city']]
write_sheet_data(SPREADSHEET_ID, f'{RANGE_NAME.split("!")[0]}!A1:D1', headers)

# Append all data (including changes)
all_data = [list(row) for row in current_state.values()]
append_sheet_data(SPREADSHEET_ID, RANGE_NAME, all_data)
print(f"Updated Google Sheets with latest MySQL data")

# Update the last known state *after* processing
last_known_state = current_state.copy()

time.sleep(5) # Check every 5 seconds

if __name__ == '__main__':
print("Starting real-time synchronization...")
Thread(target=watch_google_sheets).start()
Thread(target=watch_mysql).start()

# Keep the main thread alive
while True:
time.sleep(1)
Binary file not shown.
Binary file not shown.
47 changes: 47 additions & 0 deletions sheets/google_sheets_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from google.oauth2 import service_account
from googleapiclient.discovery import build

# Path to your downloaded service account JSON key
SERVICE_ACCOUNT_FILE = 'C:\\Users\\DHATRI C\\Desktop\\superjoin\\credentials.json'

# Define the scopes the application will use
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']

def get_google_sheets_service():
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = build('sheets', 'v4', credentials=credentials)
return service

# Read data from Google Sheets
def read_sheet_data(spreadsheet_id, range_name):
service = get_google_sheets_service()
sheet = service.spreadsheets()
result = sheet.values().get(spreadsheetId=spreadsheet_id, range=range_name).execute()
rows = result.get('values', [])
return rows

# Write data to Google Sheets
def write_sheet_data(spreadsheet_id, range_name, values):
service = get_google_sheets_service()
body = {'values': values}
result = service.spreadsheets().values().update(
spreadsheetId=spreadsheet_id, range=range_name,
valueInputOption='RAW', body=body).execute()
return result

# Append data to Google Sheets
def append_sheet_data(spreadsheet_id, range_name, values):
service = get_google_sheets_service()
body = {'values': values}
result = service.spreadsheets().values().append(
spreadsheetId=spreadsheet_id, range=range_name,
valueInputOption='RAW', body=body).execute()
return result

# Delete rows from Google Sheets (this requires clearing a range)
def delete_sheet_data(spreadsheet_id, range_name):
service = get_google_sheets_service()
result = service.spreadsheets().values().clear(
spreadsheetId=spreadsheet_id, range=range_name).execute()
return result
Binary file added superjoin video.mp4
Binary file not shown.