Skip to content
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 PythonTask.pdf
Binary file not shown.
103 changes: 102 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,102 @@
# UrbanMatch-PythonTask
# UrbanMatch-PythonTask
# Heartbeat - AI Dating Match

A modern dating web application powered by AI matching algorithms. Heartbeat helps users find compatible matches based on shared interests, age compatibility, and location.



## Features

- 🔐 Secure user authentication
- 👤 Detailed user profiles
- 💝 AI-powered match recommendations
- 🎯 Interest-based matching
- 📍 Location-based matching
- 💫 Modern, responsive UI

## Tech Stack

- **Backend**: FastAPI (Python)
- **Database**: SQLite with SQLAlchemy
- **Frontend**: HTML5, CSS3, JavaScript
- **Authentication**: JWT tokens
- **Security**: Bcrypt encryption


## File Descriptions

### Backend Files
- `main.py` - Core FastAPI application with all routes and endpoints
- `database.py` - SQLAlchemy models and database configuration
- `ai_matcher.py` - AI-powered matching algorithm implementation
- `reset_db.py` - Database initialization and reset script
- `requirements.txt` - List of Python package dependencies

### Frontend Templates
- `login.html` - User authentication interface
- `profile.html` - User profile creation and editing
- `index.html` - Main application interface showing matches



## Features

- **User Authentication**: Login and Signup functionality.
- **Profile Setup**: Users can create and update their profiles.
- **AI-Powered Matching**: Advanced AI algorithms to suggest the best matches for users.
- **Database Management**: Efficient storage and retrieval of user data.
- **Dynamic Web Pages**: Responsive HTML templates for user interactions.

---

## Directory Structure

```plaintext
heartbeat-dating/
├── main.py # FastAPI application
├── database.py # Database models and connections
├── ai_matcher.py # AI-powered matching algorithm
├── reset_db.py # Script to initialize/reset the database
├── requirements.txt # Python dependencies
└── templates/ # HTML templates for the application
├── login.html # Login/Signup page
├── profile.html # Profile setup page
└── index.html # Main matches page
```



## Installation

1. Clone the repository:
```bash
git clone https://github.com/yourusername/heartbeat-dating.git
cd heartbeat-dating
```

2. Set up a virtual environment and install dependencies:
```bash
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
```

3. Initialize the database:
```bash
python reset_db.py
```

4. Run the application:
```bash
uvicorn main:app --reload
```

5. Open the application in your browser at [http://127.0.0.1:8000](http://127.0.0.1:8000).

---
# LayOut:-
![Homepage Screenshot](https://github.com/AaryanAnand10/UrbanMatch-PythonTask/blob/main/images/MaIn.png)


![Login Screenshot](https://github.com/AaryanAnand10/UrbanMatch-PythonTask/blob/main/images/login.png)
![Profile Screenshot](https://github.com/AaryanAnand10/UrbanMatch-PythonTask/blob/main/images/profile.png)
Binary file added __pycache__/ai_matcher.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/database.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/main.cpython-312.pyc
Binary file not shown.
Binary file added __pycache__/schemas.cpython-312.pyc
Binary file not shown.
117 changes: 117 additions & 0 deletions ai_matcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
from typing import List, Dict
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

class AIMatcher:
def __init__(self):
# Predefined weights for different matching criteria
self.weights = {
'interests': 0.4,
'age': 0.3,
'location': 0.3
}

# Interest categories for better matching
self.interest_categories = {
'outdoor': ['hiking', 'nature', 'travel', 'sports', 'fitness'],
'creative': ['art', 'music', 'writing', 'photography', 'theater'],
'intellectual': ['reading', 'science', 'history', 'technology', 'languages'],
'lifestyle': ['cooking', 'fashion', 'food', 'meditation', 'yoga'],
'entertainment': ['movies', 'gaming', 'dancing', 'music', 'theater']
}

def calculate_interest_similarity(self, user1_interests: List[str], user2_interests: List[str]) -> float:
"""Calculate similarity between two users' interests using cosine similarity"""
# Convert interests to lowercase for comparison
user1_interests = [i.lower() for i in user1_interests]
user2_interests = [i.lower() for i in user2_interests]

# Create interest vectors
all_categories = list(self.interest_categories.keys())
user1_vector = self._create_interest_vector(user1_interests, all_categories)
user2_vector = self._create_interest_vector(user2_interests, all_categories)

# Calculate cosine similarity
similarity = cosine_similarity([user1_vector], [user2_vector])[0][0]
return float(similarity)

def _create_interest_vector(self, interests: List[str], categories: List[str]) -> List[float]:
"""Create a vector representation of interests based on categories"""
vector = []
for category in categories:
category_interests = self.interest_categories[category]
score = sum(1 for interest in interests if interest in category_interests)
vector.append(score / len(category_interests))
return vector

def calculate_age_compatibility(self, age1: int, age2: int) -> float:
"""Calculate age compatibility score"""
age_diff = abs(age1 - age2)
if age_diff <= 5:
return 1.0
elif age_diff <= 10:
return 0.7
elif age_diff <= 15:
return 0.4
else:
return 0.2

def calculate_location_match(self, location1: str, location2: str) -> float:
"""Calculate location match score"""
# Simple exact match for now, could be enhanced with geographic distance
return 1.0 if location1.lower() == location2.lower() else 0.0

def find_matches(self, user: Dict, potential_matches: List[Dict], limit: int = 10) -> List[Dict]:
"""Find and rank matches for a user"""
matches = []

for potential_match in potential_matches:
try:
# Calculate individual scores
interest_score = self.calculate_interest_similarity(
user['interests'],
potential_match['interests']
)

age_score = self.calculate_age_compatibility(
user['age'],
potential_match['age']
)

location_score = self.calculate_location_match(
user['location'],
potential_match['location']
)

# Calculate weighted total score
total_score = (
interest_score * self.weights['interests'] +
age_score * self.weights['age'] +
location_score * self.weights['location']
)

# Calculate match reasons
reasons = []
if interest_score > 0.6:
common_interests = set(user['interests']) & set(potential_match['interests'])
reasons.append(f"You share {len(common_interests)} interests")
if age_score > 0.7:
reasons.append("You're close in age")
if location_score == 1.0:
reasons.append("You're in the same location")

matches.append({
'user': potential_match,
'compatibility_score': int(total_score * 100),
'common_interests': list(set(user['interests']) & set(potential_match['interests'])),
'match_reasons': reasons
})

except Exception as e:
print(f"Error processing match: {str(e)}")
continue

# Sort matches by compatibility score
matches.sort(key=lambda x: x['compatibility_score'], reverse=True)

return matches[:limit]
32 changes: 32 additions & 0 deletions database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"

engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False}
)

SessionLocal = sessionmaker(bind=engine)
Base = declarative_base()

class UserModel(Base):
__tablename__ = "users"

id = Column(Integer, primary_key=True, index=True)
name = Column(String)
email = Column(String, unique=True, index=True)
hashed_password = Column(String)
age = Column(Integer, nullable=True)
location = Column(String, nullable=True)
bio = Column(String, nullable=True)
interests = Column(String, nullable=True)

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
Binary file added images/MaIn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/login.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/profile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions init_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from database import Base, engine

# Drop all existing tables
Base.metadata.drop_all(bind=engine)

# Create all tables fresh
Base.metadata.create_all(bind=engine)

print("Database initialized successfully!")
Loading