Update app.py
Browse files
app.py
CHANGED
|
@@ -16,7 +16,6 @@ def build_dataframe_from_inputs(values):
|
|
| 16 |
for name, minutes, variety in values:
|
| 17 |
minutes = 0.0 if minutes is None else float(minutes)
|
| 18 |
variety = None if variety is None else float(variety)
|
| 19 |
-
# Keep row if there is any meaningful input
|
| 20 |
if minutes > 0 or (variety is not None and not np.isnan(variety)):
|
| 21 |
rows.append(
|
| 22 |
{
|
|
@@ -63,7 +62,6 @@ def analyze_user_data(
|
|
| 63 |
if df.empty:
|
| 64 |
return "Please enter at least one platform with some weekly minutes.", pd.DataFrame()
|
| 65 |
|
| 66 |
-
# Call core model
|
| 67 |
scores = cear_analyzer.calculate_scores(
|
| 68 |
df, satisfaction=feed_satisfaction, fomo=fomo_level
|
| 69 |
)
|
|
@@ -76,11 +74,11 @@ def analyze_user_data(
|
|
| 76 |
fomo = scores.get("FOMO", None)
|
| 77 |
per_eff = scores.get("Per_Platform_Efficiency", [])
|
| 78 |
|
| 79 |
-
#
|
| 80 |
if c >= 70 and a >= 70:
|
| 81 |
profile = (
|
| 82 |
"You are highly plugged into online culture, but that comes with high "
|
| 83 |
-
"algorithmic risk and a heavy concentration of attention."
|
| 84 |
)
|
| 85 |
elif c >= 70 and a < 70:
|
| 86 |
profile = (
|
|
@@ -90,15 +88,15 @@ def analyze_user_data(
|
|
| 90 |
elif c < 40 and a >= 70:
|
| 91 |
profile = (
|
| 92 |
"You give a lot of attention to a narrow set of feeds without gaining much cultural exposure. "
|
| 93 |
-
"This is a
|
| 94 |
)
|
| 95 |
else:
|
| 96 |
profile = (
|
| 97 |
"You currently have relatively low exposure to viral trends and also keep algorithmic risk low. "
|
| 98 |
-
"You are either deliberately detached or under-invested in
|
| 99 |
)
|
| 100 |
|
| 101 |
-
#
|
| 102 |
if avg_variety is None:
|
| 103 |
variety_text = (
|
| 104 |
"You did not provide variety ratings, so this analysis focuses only on time and platform mix."
|
|
@@ -106,7 +104,7 @@ def analyze_user_data(
|
|
| 106 |
elif avg_variety < 4:
|
| 107 |
variety_text = (
|
| 108 |
f"Your average variety rating is **{avg_variety:.1f} / 10**, which suggests that your feeds feel "
|
| 109 |
-
"quite repetitive and
|
| 110 |
)
|
| 111 |
elif avg_variety > 7:
|
| 112 |
variety_text = (
|
|
@@ -118,7 +116,7 @@ def analyze_user_data(
|
|
| 118 |
f"Your average variety rating is **{avg_variety:.1f} / 10**, indicating a moderate mix of content types."
|
| 119 |
)
|
| 120 |
|
| 121 |
-
#
|
| 122 |
satisfaction_text = ""
|
| 123 |
if satisfaction is not None:
|
| 124 |
if satisfaction <= 3:
|
|
@@ -128,12 +126,13 @@ def analyze_user_data(
|
|
| 128 |
)
|
| 129 |
elif satisfaction >= 8:
|
| 130 |
satisfaction_text = (
|
| 131 |
-
"You report high satisfaction with your feed, indicating your current
|
| 132 |
-
"with
|
| 133 |
)
|
| 134 |
else:
|
| 135 |
satisfaction_text = (
|
| 136 |
-
"Your satisfaction is in the
|
|
|
|
| 137 |
)
|
| 138 |
|
| 139 |
fomo_text = ""
|
|
@@ -141,7 +140,7 @@ def analyze_user_data(
|
|
| 141 |
if fomo >= 7 and c < 50:
|
| 142 |
fomo_text = (
|
| 143 |
"You feel out of the loop and your relatively low C-Score supports that feeling. "
|
| 144 |
-
"
|
| 145 |
)
|
| 146 |
elif fomo <= 3 and c < 40:
|
| 147 |
fomo_text = (
|
|
@@ -149,6 +148,7 @@ def analyze_user_data(
|
|
| 149 |
"distance from viral culture."
|
| 150 |
)
|
| 151 |
|
|
|
|
| 152 |
summary_lines = [
|
| 153 |
"## π CEAR Analysis Summary",
|
| 154 |
"",
|
|
@@ -157,18 +157,13 @@ def analyze_user_data(
|
|
| 157 |
f"- **Platform Diversity Index (D-Index):** **{d:.2f}**",
|
| 158 |
]
|
| 159 |
if avg_variety is not None:
|
| 160 |
-
summary_lines.append(
|
| 161 |
-
f"- **Average Variety Rating (0β10):** **{avg_variety:.2f}**"
|
| 162 |
-
)
|
| 163 |
if satisfaction is not None:
|
| 164 |
-
summary_lines.append(
|
| 165 |
-
f"- **Feed Satisfaction (0β10):** **{satisfaction:.1f}**"
|
| 166 |
-
)
|
| 167 |
if fomo is not None:
|
| 168 |
-
summary_lines.append(
|
| 169 |
-
f"- **FOMO / Out-of-the-loop feeling (0β10):** **{fomo:.1f}**"
|
| 170 |
-
)
|
| 171 |
|
|
|
|
| 172 |
summary_lines.extend(
|
| 173 |
[
|
| 174 |
"",
|
|
@@ -186,6 +181,18 @@ def analyze_user_data(
|
|
| 186 |
summary_lines.append("")
|
| 187 |
summary_lines.append(fomo_text)
|
| 188 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
summary_lines.append(
|
| 190 |
"\nThe C-Score uses a logarithmic transform of your weekly minutes, encoding diminishing returns as time increases. "
|
| 191 |
"A-Risk reflects your raw time investment and how concentrated it is on a small set of high-weight platforms. "
|
|
@@ -194,13 +201,14 @@ def analyze_user_data(
|
|
| 194 |
|
| 195 |
summary = "\n".join(summary_lines).strip()
|
| 196 |
|
| 197 |
-
#
|
| 198 |
if isinstance(per_eff, list) and per_eff:
|
| 199 |
eff_df = pd.DataFrame(per_eff)
|
| 200 |
if "platform_name" in eff_df.columns:
|
| 201 |
eff_df = eff_df.rename(
|
| 202 |
columns={"platform_name": "platform", "Cultural_Efficiency": "efficiency_score"}
|
| 203 |
)
|
|
|
|
| 204 |
eff_df = eff_df.sort_values("efficiency_score", ascending=False)
|
| 205 |
else:
|
| 206 |
eff_df = pd.DataFrame(columns=["platform", "efficiency_score"])
|
|
@@ -208,7 +216,7 @@ def analyze_user_data(
|
|
| 208 |
return summary, eff_df
|
| 209 |
|
| 210 |
|
| 211 |
-
# ---------------- Gradio UI ----------------
|
| 212 |
|
| 213 |
with gr.Blocks() as demo:
|
| 214 |
gr.Markdown(
|
|
|
|
| 16 |
for name, minutes, variety in values:
|
| 17 |
minutes = 0.0 if minutes is None else float(minutes)
|
| 18 |
variety = None if variety is None else float(variety)
|
|
|
|
| 19 |
if minutes > 0 or (variety is not None and not np.isnan(variety)):
|
| 20 |
rows.append(
|
| 21 |
{
|
|
|
|
| 62 |
if df.empty:
|
| 63 |
return "Please enter at least one platform with some weekly minutes.", pd.DataFrame()
|
| 64 |
|
|
|
|
| 65 |
scores = cear_analyzer.calculate_scores(
|
| 66 |
df, satisfaction=feed_satisfaction, fomo=fomo_level
|
| 67 |
)
|
|
|
|
| 74 |
fomo = scores.get("FOMO", None)
|
| 75 |
per_eff = scores.get("Per_Platform_Efficiency", [])
|
| 76 |
|
| 77 |
+
# --- profile based on C & A --- #
|
| 78 |
if c >= 70 and a >= 70:
|
| 79 |
profile = (
|
| 80 |
"You are highly plugged into online culture, but that comes with high "
|
| 81 |
+
"algorithmic risk and a heavy concentration of attention on a small set of feeds."
|
| 82 |
)
|
| 83 |
elif c >= 70 and a < 70:
|
| 84 |
profile = (
|
|
|
|
| 88 |
elif c < 40 and a >= 70:
|
| 89 |
profile = (
|
| 90 |
"You give a lot of attention to a narrow set of feeds without gaining much cultural exposure. "
|
| 91 |
+
"This is a high-risk, low-benefit pattern."
|
| 92 |
)
|
| 93 |
else:
|
| 94 |
profile = (
|
| 95 |
"You currently have relatively low exposure to viral trends and also keep algorithmic risk low. "
|
| 96 |
+
"You are either deliberately detached from viral culture or simply under-invested in trend-dense platforms."
|
| 97 |
)
|
| 98 |
|
| 99 |
+
# --- variety interpretation --- #
|
| 100 |
if avg_variety is None:
|
| 101 |
variety_text = (
|
| 102 |
"You did not provide variety ratings, so this analysis focuses only on time and platform mix."
|
|
|
|
| 104 |
elif avg_variety < 4:
|
| 105 |
variety_text = (
|
| 106 |
f"Your average variety rating is **{avg_variety:.1f} / 10**, which suggests that your feeds feel "
|
| 107 |
+
"quite repetitive and reinforce a narrow slice of content."
|
| 108 |
)
|
| 109 |
elif avg_variety > 7:
|
| 110 |
variety_text = (
|
|
|
|
| 116 |
f"Your average variety rating is **{avg_variety:.1f} / 10**, indicating a moderate mix of content types."
|
| 117 |
)
|
| 118 |
|
| 119 |
+
# --- satisfaction & FOMO interpretation --- #
|
| 120 |
satisfaction_text = ""
|
| 121 |
if satisfaction is not None:
|
| 122 |
if satisfaction <= 3:
|
|
|
|
| 126 |
)
|
| 127 |
elif satisfaction >= 8:
|
| 128 |
satisfaction_text = (
|
| 129 |
+
"You report high satisfaction with your feed, indicating your current usage largely aligns "
|
| 130 |
+
"with what you want out of these platforms."
|
| 131 |
)
|
| 132 |
else:
|
| 133 |
satisfaction_text = (
|
| 134 |
+
"Your satisfaction is in the mid range, which suggests your feed is 'fine' but not fully optimized "
|
| 135 |
+
"for how you would like to spend your attention."
|
| 136 |
)
|
| 137 |
|
| 138 |
fomo_text = ""
|
|
|
|
| 140 |
if fomo >= 7 and c < 50:
|
| 141 |
fomo_text = (
|
| 142 |
"You feel out of the loop and your relatively low C-Score supports that feeling. "
|
| 143 |
+
"If staying current matters to you, a bit more time on trend-dense platforms could help."
|
| 144 |
)
|
| 145 |
elif fomo <= 3 and c < 40:
|
| 146 |
fomo_text = (
|
|
|
|
| 148 |
"distance from viral culture."
|
| 149 |
)
|
| 150 |
|
| 151 |
+
# --- summary header --- #
|
| 152 |
summary_lines = [
|
| 153 |
"## π CEAR Analysis Summary",
|
| 154 |
"",
|
|
|
|
| 157 |
f"- **Platform Diversity Index (D-Index):** **{d:.2f}**",
|
| 158 |
]
|
| 159 |
if avg_variety is not None:
|
| 160 |
+
summary_lines.append(f"- **Average Variety Rating (0β10):** **{avg_variety:.2f}**")
|
|
|
|
|
|
|
| 161 |
if satisfaction is not None:
|
| 162 |
+
summary_lines.append(f"- **Feed Satisfaction (0β10):** **{satisfaction:.1f}**")
|
|
|
|
|
|
|
| 163 |
if fomo is not None:
|
| 164 |
+
summary_lines.append(f"- **FOMO / Out-of-the-loop (0β10):** **{fomo:.1f}**")
|
|
|
|
|
|
|
| 165 |
|
| 166 |
+
# --- interpretation section --- #
|
| 167 |
summary_lines.extend(
|
| 168 |
[
|
| 169 |
"",
|
|
|
|
| 181 |
summary_lines.append("")
|
| 182 |
summary_lines.append(fomo_text)
|
| 183 |
|
| 184 |
+
# --- explanation of how survey inputs are used --- #
|
| 185 |
+
survey_explainer = """
|
| 186 |
+
### βΉοΈ How your answers are used
|
| 187 |
+
|
| 188 |
+
- **Minutes per week** drive the core scores. More time on high-weight platforms increases both C-Score and A-Risk, with diminishing returns for C-Score.
|
| 189 |
+
- **Per-platform variety (0β10)** is combined into a minutes-weighted average. Low variety means you mainly see one type of content; high variety means you see a wider mix of topics and styles.
|
| 190 |
+
- **Feed satisfaction (0β10)** does not change the scores; it is used to interpret whether your current pattern feels good or frustrating to you.
|
| 191 |
+
- **FOMO (0β10)** is compared with your C-Score: high FOMO with low C-Score means you feel out of the loop, while low FOMO with low C-Score means you are detached by choice.
|
| 192 |
+
"""
|
| 193 |
+
summary_lines.append("")
|
| 194 |
+
summary_lines.append(survey_explainer.strip())
|
| 195 |
+
|
| 196 |
summary_lines.append(
|
| 197 |
"\nThe C-Score uses a logarithmic transform of your weekly minutes, encoding diminishing returns as time increases. "
|
| 198 |
"A-Risk reflects your raw time investment and how concentrated it is on a small set of high-weight platforms. "
|
|
|
|
| 201 |
|
| 202 |
summary = "\n".join(summary_lines).strip()
|
| 203 |
|
| 204 |
+
# --- per-platform efficiency table --- #
|
| 205 |
if isinstance(per_eff, list) and per_eff:
|
| 206 |
eff_df = pd.DataFrame(per_eff)
|
| 207 |
if "platform_name" in eff_df.columns:
|
| 208 |
eff_df = eff_df.rename(
|
| 209 |
columns={"platform_name": "platform", "Cultural_Efficiency": "efficiency_score"}
|
| 210 |
)
|
| 211 |
+
eff_df["efficiency_score"] = eff_df["efficiency_score"].round(1)
|
| 212 |
eff_df = eff_df.sort_values("efficiency_score", ascending=False)
|
| 213 |
else:
|
| 214 |
eff_df = pd.DataFrame(columns=["platform", "efficiency_score"])
|
|
|
|
| 216 |
return summary, eff_df
|
| 217 |
|
| 218 |
|
| 219 |
+
# ---------------- Gradio UI ---------------- #
|
| 220 |
|
| 221 |
with gr.Blocks() as demo:
|
| 222 |
gr.Markdown(
|