diff --git a/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj b/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj
index 6cc27ef..67b7121 100644
--- a/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj
+++ b/DysonNetwork.Sphere/DysonNetwork.Sphere.csproj
@@ -15,6 +15,7 @@
+
diff --git a/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs b/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs
index 15c8206..9d1b9ab 100644
--- a/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs
+++ b/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs
@@ -4,6 +4,7 @@ using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using DysonNetwork.Sphere.Chat;
using Grpc.Core;
+using JiebaNet.Segmenter;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using PostReactionAttitude = DysonNetwork.Shared.Models.PostReactionAttitude;
@@ -76,6 +77,22 @@ public class SphereRewindServiceGrpc(
.OrderByDescending(g => g.Count())
.Select(g => new { Date = g.Key, PostCount = g.Count() })
.FirstOrDefault();
+ // Contents to create word cloud
+ var postContents = await posts
+ .Where(p => p.Content != null)
+ .Select(p => p.Content)
+ .OrderByDescending(p => p!.Length)
+ .Take(1000)
+ .ToListAsync();
+ var segmenter = new JiebaSegmenter();
+ var words = segmenter.CutForSearchInParallel(postContents);
+ var allWords = words.SelectMany(w => w);
+ var topWords = allWords
+ .GroupBy(w => w)
+ .Select(g => new { Word = g.Key, Count = g.Count() })
+ .OrderByDescending(wc => wc.Count)
+ .Take(100)
+ .ToList();
// Chat data
var messagesQuery = db.ChatMessages
@@ -157,6 +174,8 @@ public class SphereRewindServiceGrpc(
{
["total_post_count"] = postTotalCount,
["total_upvote_count"] = postTotalUpvotes,
+ ["top_words"] = topWords.Select(wc => new Dictionary
+ { ["word"] = wc.Word, ["count"] = wc.Count }).ToList(),
["most_popular_post"] = mostPopularPost,
["most_productive_day"] = mostProductiveDay is not null
? new Dictionary