Skip to content
Merged
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
20 changes: 18 additions & 2 deletions app/analytics/UserAnalytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import pandas as pd
import json
import os
import shutil

class UserAnalytics:
def __init__(self):
self.assets_path = os.environ.get("ASSETS_PATH")
self.user_file_path = os.environ.get("USER_FILE_PATH")
self.geo_lite_db_path = os.environ.get("GEOLITE_DB_PATH")
self.media_path = os.environ.get("MEDIA_PATH")

# TODO: come back and fix this
# if self.geo_lite_db_path is None:
Expand All @@ -28,8 +30,10 @@ def __init__(self):
self.user_data = user_data

def get_media_file_paths(self):
assets_dir = self.assets_path
jpg_files = [f for f in os.listdir(assets_dir) if f.endswith(".jpg")]
# need to copy the files from the media_path to the assets_dir
_copy_files(self.media_path, self.assets_path)

jpg_files = [f for f in os.listdir(self.assets_path) if f.endswith(".jpg")]
return jpg_files

def get_account_data(self):
Expand Down Expand Up @@ -157,6 +161,18 @@ def collect_location_from_ip(self):
geolocation_data = [self._get_city_info(ip) for ip in ip_addresses if self._get_city_info(ip) is not None]

return pd.DataFrame(geolocation_data)

def _copy_files(src_dir, dest_dir):
os.makedirs(dest_dir, exist_ok=True)

# loop through all files in source directory
for file_name in os.listdir(src_dir):
src_path = os.path.join(src_dir, file_name)
dest_path = os.path.join(dest_dir, file_name)

# only copy files (not subdirectories)
if os.path.isfile(src_path):
shutil.copy2(src_path, dest_path) # copy2 preserves metadata

def _get_city_info(self, ip):
# initialize GeoLite2 reader & geocoder
Expand Down
18 changes: 6 additions & 12 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,16 @@
def get_additional_text(page_name):
"""Helper function to provide context about the different hyperlinks based on the page name."""
if page_name == "Info":
return "Discover detailed insights about the app's features and functionality. This section offers a comprehensive" \
" overview of how the project works, what data is available to the user, and how to navigate the app for the best experience."
return "Discover detailed insights about the app's features and functionality."
elif page_name == "Matches":
return "Explore in-depth analyses of the users matches and interactions. This section reveals patterns in the user's matching " \
"behavior, preferences, and key factors that influence successful connections with potential matches."
return "Explore in-depth analyses of the users matches and interactions."
elif page_name == "User":
return "Analyze the user's personal profile and preferences. This section contains insights into how the user's " \
"profile is presented, the preferences they've set, and how their interactions shape their experience on the app."

return "Analyze the user's personal profile and preferences."
app.layout = html.Div([
dmc.Title('Hinge Data Analysis', color="black", size="h1"),
dmc.Title('Hinge User Insights', align="center", color="black", size="h1"),
dmc.Space(h=10),
dmc.Text("Insights into a Hinge User's Experiences", align="center", style={"fontSize": 16}, weight=500, italic=True),
dmc.Space(h=20),
dmc.Text("Insights into a Hinge User's Experiences", style={"fontSize": 24}, weight=500),
dmc.Text("This project analyzes personal data exported from Hinge to provide valuable insights into the user's "
"experiences on the platform. By examining the user's profile, dating preferences, and interactions with other users, "
"the project aims to reveal patterns, trends, and meaningful statistics that enhance the understanding of how users "
Expand Down Expand Up @@ -75,9 +72,6 @@ def get_additional_text(page_name):

])




if __name__ == '__main__':
host = os.environ.get("HOST")
port = int(os.environ.get("PORT", 8050))
Expand Down
3 changes: 3 additions & 0 deletions app/pages/InfoPage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import dash_mantine_components as dmc

layout = html.Div([
dmc.Text("Info", align="center", style={"fontSize": 28}, weight=500),
dmc.Text("This section offers a comprehensive overview of how the project works, what data is available to the user, and how to navigate the app for the best experience."),
dmc.Space(h=20),
dmc.Space(h=10),
dmc.Text("What This Is", style={"fontSize": 28}, weight=500),
dmc.Text("This application is meant to help provide meaningful insights about interactions users had with "
Expand Down
4 changes: 2 additions & 2 deletions app/pages/MatchPage.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

def serve_layout():
return html.Div([
# TODO: need to remove the button, but it has dependencies with the charts so will leave it until I can redo the charts
html.Button('Reload Graphs', id='refresh-page', style={"fontSize": 16, 'font-family': "Open Sans, verdana, arial, sans-serif"}),
dmc.Space(h=20),

dmc.Text("Match Analytics", align="center", style={"fontSize": 28}, weight=500),
dmc.Text("This section contains insights about the interactions (likes, matches, chats, and unmatches) you've "
"had on Hinge."),
dmc.Text("This section reveals patterns in the user's matching behavior, preferences, and key factors that influence successful connections with potential matches."),
dmc.Space(h=20),

# funnel graph showing breakdown of interactions
Expand Down
14 changes: 8 additions & 6 deletions app/pages/UserPage.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def user_photo_slideshow():

return dmc.Card(
children=[
dmc.Text("Photos", weight=750, size="lg"),
dmc.Text("User Uploaded Photos", align="center", weight=750, size="xl"),
dmc.Space(h=10),
html.Img(id="slideshow-image", style={"width": "100%", "borderRadius": "10px"}), # Image placeholder
dcc.Interval(id="interval-component", interval=10000, n_intervals=0),
Expand Down Expand Up @@ -228,7 +228,7 @@ def create_user_location_card():
return dmc.Card(
children=[
dmc.Space(h=10),
dmc.Text("Location", weight=700, size="xl"),
dmc.Text("User Location", weight=700, align="center", size="xl"),
dmc.Text(f"Country: {user_location['country']}", size="lg"),
dmc.Text(f"Locality: {user_location['locality']}", size="lg"),
dmc.Text(f"City: {user_location['city']}", size="lg"),
Expand All @@ -248,10 +248,10 @@ def create_user_summary_card():

return dmc.Card(
children=[
dmc.Text(f"{user_summary['first_name']}", weight=750, size="xl"),
dmc.Text(f"{user_summary['first_name']}", align="center", weight=750, size="xl"),
dmc.Text(f"Age: {user_summary['age']}", size="lg", color="dimmed"),
dmc.Text(f"Height (ft, in): {user_summary['height_feet'], user_summary['height_inches']}", size="lg", color="dimmed"),
dmc.Text(f"Gender: {user_summary['gender']}", size="lg", color="dimmed"),
dmc.Text(f"Height (ft, in): {user_summary['height_feet'], user_summary['height_inches']}", size="lg"),
dmc.Text(f"Gender: {user_summary['gender']}", size="lg"),
dmc.Text(f"Ethnicities: {user_summary['ethnicities']}", size="lg"),
dmc.Text(f"Religions: {user_summary['religions']}", size="lg"),
dmc.Text(f"Job: {user_summary['job_title']}", size="lg"),
Expand All @@ -273,6 +273,8 @@ def create_user_summary_card():

layout = html.Div([
dmc.Text("User Analytics", align="center", style={"fontSize": 28}, weight=500),
dmc.Space(h=10),
dmc.Text("This section contains insights into how the user's profile is presented, the preferences they've set, and how their interactions shape their experience on the app."),
dmc.Space(h=20),
dmc.Grid(
children=[
Expand All @@ -293,7 +295,7 @@ def create_user_summary_card():
dmc.Space(h=120),
disclosure_vs_privacy(),
potential_misalignments(),
geolocation(),
# geolocation(), # TODO: this is causing issues with too many lookup calls
stringency_vs_flexibility(),
dmc.Space(h=50)
])