diff --git a/.gitignore b/.gitignore index 2f0c8e5..7f0906c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ data/ .env .vscode .pytest_cache -app/assets/ \ No newline at end of file +app/assets/ +scratch/ \ No newline at end of file diff --git a/app/analytics/UserAnalytics.py b/app/analytics/UserAnalytics.py index 9251d98..38ec287 100644 --- a/app/analytics/UserAnalytics.py +++ b/app/analytics/UserAnalytics.py @@ -1,4 +1,5 @@ from datetime import datetime +from collections import defaultdict import json import os @@ -87,6 +88,27 @@ def build_user_summary_dict(self): return user_summary + def count_displayed_attributes(self): + profile_data = self.get_profile_data() + + categories = { + "identity": ["gender_identity_displayed", "ethnicities_displayed", "religions_displayed", "politics_displayed", "languages_spoken_displayed", "hometowns_displayed"], + "lifestyle": ["smoking_displayed", "drinking_displayed", "marijuana_displayed", "drugs_displayed", "vaccination_status_displayed", "pets_displayed", ], + "career": ["workplaces_displayed", "job_title_displayed", "schools_displayed"], + "future_plans": ["family_plans_displayed", "dating_intention_displayed", "children_displayed", "relationship_type_displayed"] + } + + # initialize counters + display_counts = defaultdict(lambda: {"true": 0, "false": 0}) + + for category, fields in categories.items(): + for field in fields: + if field in profile_data: + display_value = profile_data[field] + display_counts[category]["true" if display_value else "false"] += 1 + return dict(display_counts) + + def _convert_height(cm): inches = cm / 2.54 feet = int(inches // 12) # whole feet diff --git a/app/pages/UserPage.py b/app/pages/UserPage.py index b64c4f3..d02345e 100644 --- a/app/pages/UserPage.py +++ b/app/pages/UserPage.py @@ -2,12 +2,63 @@ import dash_mantine_components as dmc import plotly.express as px from dash.dependencies import Input, Output, State +import plotly.graph_objects as go from analytics.UserAnalytics import UserAnalytics +def disclosure_vs_privacy(): + category_counts = UserAnalytics().count_displayed_attributes() + + category_labels = { + "identity": "Identity & Demographics", + "career": "Work & Education", + "lifestyle": "Lifestyle & Habits", + "future_plans": "Dating Preferences & Intentions" + } + + # extract the category keys and T/F counts to pass to the graphs + cat_keys = [category_labels[cat] for cat in category_counts.keys()] + true_counts = [category_counts[cat]['true'] for cat in category_counts] + false_counts = [category_counts[cat]['false'] for cat in category_counts] + + fig = go.Figure() + + fig.add_trace(go.Bar( + x=cat_keys, + y=true_counts, + name="Displayed (True)", + marker_color='blue' + )) + + fig.add_trace(go.Bar( + x=cat_keys, + y=false_counts, + name="Not Displayed (False)", + marker_color='red' + )) + + fig.update_layout( + title="Profile Information Visibility: Displayed vs. Hidden", + xaxis_title="Profile Information Category", + yaxis_title="Number of Profile Fields", + barmode='group', + template="plotly_white" + ) + return dmc.Card( + children=[ + dmc.Space(h=10), + dmc.Text("How much information does this user choose to share vs. keep private?", weight=700, size="xl"), + dmc.Space(h=10), + dcc.Graph(figure=fig) + ], + withBorder=True, + shadow="sm", + radius="md", + style={"height": "520px"}, + ) + def user_photo_slideshow(): jpg_files = UserAnalytics().get_media_file_paths() - print(jpg_files) return dmc.Card( children=[ @@ -20,7 +71,7 @@ def user_photo_slideshow(): withBorder=True, shadow="sm", radius="md", - style={"width": "500px", "padding": "20px"}, + style={"width": "500px", "height": "520px", "padding": "20px"}, ) @callback( @@ -113,6 +164,7 @@ def create_user_summary_card(): span=4 ) ], - style={"height": "50vh"} -) + style={"height": "50vh"} ), + dmc.Space(h=120), + disclosure_vs_privacy() ]) diff --git a/pytest.ini b/pytest.ini index 3fdf542..9d22cd7 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,3 @@ [pytest] python_files = test_*.py *_test.py -addopts = --tb=short -ra \ No newline at end of file +addopts = -s \ No newline at end of file diff --git a/tests/analytics/test_UserAnalytics.py b/tests/analytics/test_UserAnalytics.py index 0667206..aef1217 100644 --- a/tests/analytics/test_UserAnalytics.py +++ b/tests/analytics/test_UserAnalytics.py @@ -35,7 +35,25 @@ "age": 99, "height_centimeters": 213, "gender": "female", + "gender_identity_displayed": false, + "ethnicities_displayed": false, + "religions_displayed": true, + "workplaces_displayed": false, + "schools_displayed": true, "job_title": "Astronaut", + "job_title_displayed": true, + "hometowns_displayed": false, + "smoking_displayed": false, + "drinking_displayed": true, + "marijuana_displayed": false, + "drugs_displayed": false, + "children_displayed": false, + "family_plans_displayed": true, + "politics_displayed": false, + "vaccination_status_displayed": true, + "dating_intention_displayed": false, + "languages_spoken_displayed": true, + "relationship_type_displayed": false, "education_attained": "Undergraduate", "languages_spoken": "English", "ethnicities": "Prefer Not to Say", @@ -62,6 +80,7 @@ } } ''' +COUNT_DISPLAYED_ATTRIB_OUTPUT = {'identity': {'true': 2, 'false': 4}, 'lifestyle': {'true': 2, 'false': 3}, 'career': {'true': 2, 'false': 1}, 'future_plans': {'true': 1, 'false': 3}} ######################################################################################### # pytest fixtures @@ -153,4 +172,7 @@ def test_build_user_location_dict(user_analytics): assert result["country"] == "Iceland" assert result["neighborhood"] == "Flatbush" assert result["locality"] == "New York" - \ No newline at end of file + +def test_count_displayed_attributes(user_analytics): + result = user_analytics.count_displayed_attributes() + assert result == COUNT_DISPLAYED_ATTRIB_OUTPUT \ No newline at end of file