Finish off the links between frontend and backend #10

Merged
dylan merged 24 commits from feat/add-frontend-pages into main 2026-03-18 20:30:19 +00:00
2 changed files with 18 additions and 62 deletions
Showing only changes of commit 2a00384a55 - Show all commits

View File

@@ -52,67 +52,22 @@ class InteractionAnalysis:
return round(sum(depths) / len(depths), 2) return round(sum(depths) / len(depths), 2)
def average_thread_length_by_emotion(self, df: pd.DataFrame): def top_interaction_pairs(self, df: pd.DataFrame, top_n=10):
emotion_exclusions = {"emotion_neutral", "emotion_surprise"} graph = self.interaction_graph(df)
pairs = []
emotion_cols = [ for a, targets in graph.items():
c for b, count in targets.items():
for c in df.columns pairs.append(((a, b), count))
if c.startswith("emotion_") and c not in emotion_exclusions
]
id_to_reply = df.set_index("id")["reply_to"].to_dict() pairs.sort(key=lambda x: x[1], reverse=True)
length_cache = {} return pairs[:top_n]
def thread_length_from(start_id): def initiator_ratio(self, df: pd.DataFrame):
if start_id in length_cache: starters = df["reply_to"].isna().sum()
return length_cache[start_id] total = len(df)
seen = set() if total == 0:
length = 1 return 0
current = start_id
while True: return round(starters / total, 2)
if current in seen:
# infinite loop shouldn't happen, but just in case
break
seen.add(current)
reply_to = id_to_reply.get(current)
if (
reply_to is None
or (isinstance(reply_to, float) and pd.isna(reply_to))
or reply_to == ""
):
break
length += 1
current = reply_to
if current in length_cache:
length += length_cache[current] - 1
break
length_cache[start_id] = length
return length
emotion_to_lengths = {}
# Fill NaNs in emotion cols to avoid max() issues
emo_df = df[["id"] + emotion_cols].copy()
emo_df[emotion_cols] = emo_df[emotion_cols].fillna(0)
for _, row in emo_df.iterrows():
msg_id = row["id"]
length = thread_length_from(msg_id)
emotions = {c: row[c] for c in emotion_cols}
dominant = max(emotions, key=emotions.get)
emotion_to_lengths.setdefault(dominant, []).append(length)
return {
emotion: round(sum(lengths) / len(lengths), 2)
for emotion, lengths in emotion_to_lengths.items()
}

View File

@@ -120,7 +120,8 @@ class StatGen:
return { return {
"average_thread_depth": self.interaction_analysis.average_thread_depth(filtered_df), "average_thread_depth": self.interaction_analysis.average_thread_depth(filtered_df),
"average_thread_length_by_emotion": self.interaction_analysis.average_thread_length_by_emotion(filtered_df), "top_interaction_pairs": self.interaction_analysis.top_interaction_pairs(filtered_df, top_n=100),
"initiator_ratio": self.interaction_analysis.initiator_ratio(filtered_df),
"interaction_graph": self.interaction_analysis.interaction_graph(filtered_df) "interaction_graph": self.interaction_analysis.interaction_graph(filtered_df)
} }