From 50518351bc79093d806f52ccb744dc916926ec26 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 27 Dec 2025 01:19:24 +0800 Subject: [PATCH] :sparkles: Improvements, new data in rewind point :bug: Fix most called rewind point unable to get real data --- DysonNetwork.Pass/Rewind/PassRewindService.cs | 62 ++++++++++++-- DysonNetwork.Sphere/Chat/ChatRoomService.cs | 6 +- .../Publisher/PublisherService.cs | 10 ++- .../Rewind/SphereRewindServiceGrpc.cs | 83 +++++++++++++------ 4 files changed, 122 insertions(+), 39 deletions(-) diff --git a/DysonNetwork.Pass/Rewind/PassRewindService.cs b/DysonNetwork.Pass/Rewind/PassRewindService.cs index a79bd7e..e97586d 100644 --- a/DysonNetwork.Pass/Rewind/PassRewindService.cs +++ b/DysonNetwork.Pass/Rewind/PassRewindService.cs @@ -1,6 +1,8 @@ +using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; using Microsoft.EntityFrameworkCore; using NodaTime; +using NodaTime.TimeZones; namespace DysonNetwork.Pass.Rewind; @@ -15,6 +17,32 @@ public class PassRewindService(AppDatabase db) var startDate = new LocalDate(year - 1, 12, 26).AtMidnight().InUtc().ToInstant(); var endDate = new LocalDate(year, 12, 26).AtMidnight().InUtc().ToInstant(); + var timeZone = (await db.AccountProfiles + .Where(p => p.AccountId == accountId) + .FirstOrDefaultAsync())?.TimeZone; + + var zone = TimeZoneInfo.Utc; + if (!string.IsNullOrEmpty(timeZone)) + try + { + zone = TimeZoneInfo.FindSystemTimeZoneById(timeZone); + } + catch (DateTimeZoneNotFoundException) + { + // use UTC + } + + var newFriendsCount = await db.AccountRelationships + .Where(r => r.CreatedAt >= startDate && r.CreatedAt < endDate) + .Where(r => r.AccountId == accountId) + .Where(r => r.Status == RelationshipStatus.Friends) + .CountAsync(); + var newBlockedCount = await db.AccountRelationships + .Where(r => r.CreatedAt >= startDate && r.CreatedAt < endDate) + .Where(r => r.AccountId == accountId) + .Where(r => r.Status == RelationshipStatus.Blocked) + .CountAsync(); + var checkInDates = await db.AccountCheckInResults .Where(a => a.CreatedAt >= startDate && a.CreatedAt < endDate) .Where(a => a.AccountId == accountId) @@ -53,13 +81,28 @@ public class PassRewindService(AppDatabase db) .OrderByDescending(g => g.Count) .FirstOrDefault(); - var actionTimes = await db.ActionLogs - .Where(a => a.CreatedAt >= startDate && a.CreatedAt < endDate) - .Where(a => a.AccountId == accountId) - .Select(a => a.CreatedAt.ToDateTimeUtc()) - .ToListAsync(); + var actionTimes = actionDates + .Select(a => TimeZoneInfo.ConvertTimeFromUtc(a, zone).TimeOfDay) + .ToList(); - TimeSpan? latestActiveTime = actionTimes.Any() ? actionTimes.Max(dt => dt.TimeOfDay) : null; + TimeSpan? latestActiveTime = null; + if (actionTimes.Count != 0) + { + var timesBefore6Am = actionTimes.Where(t => t < TimeSpan.FromHours(6)).ToList(); + latestActiveTime = timesBefore6Am.Count != 0 ? timesBefore6Am.Max() : actionTimes.Max(); + } + + var lotteriesQuery = db.Lotteries + .Where(l => l.CreatedAt >= startDate && l.CreatedAt < endDate) + .Where(l => l.AccountId == accountId) + .AsQueryable(); + var lotteriesWins = await lotteriesQuery + .Where(l => l.MatchedRegionOneNumbers != null && l.MatchedRegionOneNumbers.Count > 0) + .CountAsync(); + var lotteriesLosses = await lotteriesQuery + .Where(l => l.MatchedRegionOneNumbers == null || l.MatchedRegionOneNumbers.Count == 0) + .CountAsync(); + var lotteriesWinRate = lotteriesWins / (double)(lotteriesWins + lotteriesLosses); var data = new Dictionary { @@ -68,8 +111,13 @@ public class PassRewindService(AppDatabase db) ["most_active_day"] = mostActiveDay?.Date.ToString("yyyy-MM-dd"), ["most_active_weekday"] = mostActiveWeekday?.Day.ToString(), ["latest_active_time"] = latestActiveTime?.ToString(@"hh\:mm"), + ["new_friends_count"] = newFriendsCount, + ["new_blocked_count"] = newBlockedCount, + ["lotteries_wins"] = lotteriesWins, + ["lotteries_losses"] = lotteriesLosses, + ["lotteries_win_rate"] = lotteriesWinRate, }; - + return new RewindEvent { ServiceId = "pass", diff --git a/DysonNetwork.Sphere/Chat/ChatRoomService.cs b/DysonNetwork.Sphere/Chat/ChatRoomService.cs index 78e6830..de9e518 100644 --- a/DysonNetwork.Sphere/Chat/ChatRoomService.cs +++ b/DysonNetwork.Sphere/Chat/ChatRoomService.cs @@ -226,13 +226,13 @@ public class ChatRoomService( { var topMembers = await db.ChatMessages .Where(m => m.ChatRoomId == roomId && m.CreatedAt >= startDate && m.CreatedAt < endDate) - .GroupBy(m => m.SenderId) - .Select(g => new { SenderId = g.Key, MessageCount = g.Count() }) + .GroupBy(m => m.Sender.AccountId) + .Select(g => new { AccountId = g.Key, MessageCount = g.Count() }) .OrderByDescending(g => g.MessageCount) .Take(3) .ToListAsync(); - var accountIds = topMembers.Select(t => t.SenderId).ToList(); + var accountIds = topMembers.Select(t => t.AccountId).ToList(); var accounts = await remoteAccounts.GetAccountBatch(accountIds); return accounts.Select(SnAccount.FromProtoValue).ToList(); } diff --git a/DysonNetwork.Sphere/Publisher/PublisherService.cs b/DysonNetwork.Sphere/Publisher/PublisherService.cs index d309445..34da815 100644 --- a/DysonNetwork.Sphere/Publisher/PublisherService.cs +++ b/DysonNetwork.Sphere/Publisher/PublisherService.cs @@ -310,17 +310,19 @@ public class PublisherService( var publisher = await db.Publishers.FirstOrDefaultAsync(e => e.Name == name); if (publisher is null) return null; - var postsCount = await db.Posts.Where(e => e.Publisher.Id == publisher.Id).CountAsync(); + var postsCount = await db.Posts.Where(e => e.PublisherId == publisher.Id).CountAsync(); var postsUpvotes = await db.PostReactions - .Where(r => r.Post.Publisher.Id == publisher.Id && + .Where(r => r.Post.PublisherId == publisher.Id && r.Attitude == Shared.Models.PostReactionAttitude.Positive) .CountAsync(); var postsDownvotes = await db.PostReactions - .Where(r => r.Post.Publisher.Id == publisher.Id && + .Where(r => r.Post.PublisherId == publisher.Id && r.Attitude == Shared.Models.PostReactionAttitude.Negative) .CountAsync(); - var stickerPacksId = await db.StickerPacks.Where(e => e.Publisher.Id == publisher.Id).Select(e => e.Id) + var stickerPacksId = await db.StickerPacks + .Where(e => e.PublisherId == publisher.Id) + .Select(e => e.Id) .ToListAsync(); var stickerPacksCount = stickerPacksId.Count; diff --git a/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs b/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs index 57878cb..15c8206 100644 --- a/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs +++ b/DysonNetwork.Sphere/Rewind/SphereRewindServiceGrpc.cs @@ -6,6 +6,7 @@ using DysonNetwork.Sphere.Chat; using Grpc.Core; using Microsoft.EntityFrameworkCore; using NodaTime; +using PostReactionAttitude = DysonNetwork.Shared.Models.PostReactionAttitude; namespace DysonNetwork.Sphere.Rewind; @@ -28,7 +29,7 @@ public class SphereRewindServiceGrpc( var mostLovedPublisherClue = await db.PostReactions .Where(a => a.CreatedAt >= startDate && a.CreatedAt < endDate) - .Where(p => p.AccountId == accountId && p.Attitude == Shared.Models.PostReactionAttitude.Positive) + .Where(p => p.AccountId == accountId && p.Attitude == PostReactionAttitude.Positive) .GroupBy(p => p.Post.PublisherId) .OrderByDescending(g => g.Count()) .Select(g => new { PublisherId = g.Key, ReactionCount = g.Count() }) @@ -47,7 +48,7 @@ public class SphereRewindServiceGrpc( await db.PostReactions .Where(a => a.CreatedAt >= startDate && a.CreatedAt < endDate) .Where(pr => - pr.Attitude == Shared.Models.PostReactionAttitude.Positive && + pr.Attitude == PostReactionAttitude.Positive && publishers.Contains(pr.Post.PublisherId)) .GroupBy(pr => pr.AccountId) .OrderByDescending(g => g.Count()) @@ -62,6 +63,11 @@ public class SphereRewindServiceGrpc( .Where(p => publishers.Contains(p.PublisherId)) .AsQueryable(); var postTotalCount = await posts.CountAsync(); + var postTotalUpvotes = await db.PostReactions + .Where(a => a.CreatedAt >= startDate && a.CreatedAt < endDate) + .Where(p => publishers.Contains(p.Post.PublisherId)) + .Where(r => r.Attitude == PostReactionAttitude.Positive) + .CountAsync(); var mostPopularPost = await posts .OrderByDescending(p => p.Upvotes - p.Downvotes) .FirstOrDefaultAsync(); @@ -78,20 +84,21 @@ public class SphereRewindServiceGrpc( .Where(m => m.CreatedAt >= startDate && m.CreatedAt < endDate) .Where(m => m.Sender.AccountId == accountId) .AsQueryable(); - var mostMessagedChat = await messagesQuery - .Where(m => m.ChatRoom.Type == Shared.Models.ChatRoomType.Group) + var mostMessagedChatInfo = await messagesQuery + .Where(m => m.ChatRoom.Type == ChatRoomType.Group) .GroupBy(m => m.ChatRoomId) .OrderByDescending(g => g.Count()) - .Select(g => g.First().ChatRoom) + .Select(g => new { ChatRoom = g.First().ChatRoom, MessageCount = g.Count() }) .FirstOrDefaultAsync(); - var mostMessagedDirectChat = await messagesQuery - .Where(m => m.ChatRoom.Type == Shared.Models.ChatRoomType.DirectMessage) + var mostMessagedChat = mostMessagedChatInfo?.ChatRoom; + var mostMessagedDirectChatInfo = await messagesQuery + .Where(m => m.ChatRoom.Type == ChatRoomType.DirectMessage) .GroupBy(m => m.ChatRoomId) .OrderByDescending(g => g.Count()) - .Select(g => g.First().ChatRoom) + .Select(g => new { ChatRoom = g.First().ChatRoom, MessageCount = g.Count() }) .FirstOrDefaultAsync(); - mostMessagedDirectChat = mostMessagedDirectChat is not null - ? await crs.LoadDirectMessageMembers(mostMessagedDirectChat, accountId) + var mostMessagedDirectChat = mostMessagedDirectChatInfo is not null + ? await crs.LoadDirectMessageMembers(mostMessagedDirectChatInfo.ChatRoom, accountId) : null; // Call data @@ -104,25 +111,28 @@ public class SphereRewindServiceGrpc( var now = SystemClock.Instance.GetCurrentInstant(); var callDurations = await callQuery - .Where(c => c.Room.Type == Shared.Models.ChatRoomType.Group) - .Select(c => new { RoomId = c.RoomId, Duration = c.CreatedAt.Minus(c.EndedAt ?? now).Seconds }) + .Where(c => c.Room.Type == ChatRoomType.Group) + .Select(c => new { c.RoomId, Duration = c.CreatedAt.Minus(c.EndedAt ?? now).Seconds }) .ToListAsync(); - var mostCalledRoomId = callDurations + var mostCalledRoomInfo = callDurations .GroupBy(c => c.RoomId) - .OrderByDescending(g => g.Sum(c => c.Duration)) - .Select(g => g.Key) + .Select(g => new { RoomId = g.Key, TotalDuration = g.Sum(c => c.Duration) }) + .OrderByDescending(g => g.TotalDuration) .FirstOrDefault(); - var mostCalledRoom = mostCalledRoomId != Guid.Empty ? await db.ChatRooms.FindAsync(mostCalledRoomId) : null; + var mostCalledRoom = mostCalledRoomInfo != null && mostCalledRoomInfo.RoomId != Guid.Empty + ? await db.ChatRooms.FindAsync(mostCalledRoomInfo.RoomId) + : null; List? mostCalledChatTopMembers = null; if (mostCalledRoom != null) mostCalledChatTopMembers = await crs.GetTopActiveMembers(mostCalledRoom.Id, startDate, endDate); var mostCalledDirectRooms = await callQuery - .Where(c => c.Room.Type == Shared.Models.ChatRoomType.DirectMessage) + .Where(c => c.Room.Type == ChatRoomType.DirectMessage) .GroupBy(c => c.RoomId) - .Select(g => new { ChatRoom = g.First().Room, CallCount = g.Count() }) - .OrderByDescending(g => g.CallCount) + .Select(g => new + { ChatRoom = g.First().Room, TotalDuration = g.Sum(c => c.CreatedAt.Minus(c.EndedAt ?? now).Seconds) }) + .OrderByDescending(g => g.TotalDuration) .Take(3) .ToListAsync(); @@ -134,12 +144,19 @@ public class SphereRewindServiceGrpc( if (otherMember != null) accountIds.Add(otherMember.AccountId); } - var mostCalledAccounts = await remoteAccounts.GetAccountBatch(accountIds); + + var accounts = await remoteAccounts.GetAccountBatch(accountIds); + var mostCalledAccounts = accounts.Zip(mostCalledDirectRooms, + (account, room) => new Dictionary + { ["account"] = account, ["duration"] = room.TotalDuration } + ) + .ToList(); var data = new Dictionary { - ["total_count"] = postTotalCount, + ["total_post_count"] = postTotalCount, + ["total_upvote_count"] = postTotalUpvotes, ["most_popular_post"] = mostPopularPost, ["most_productive_day"] = mostProductiveDay is not null ? new Dictionary @@ -162,9 +179,25 @@ public class SphereRewindServiceGrpc( ["upvote_counts"] = mostLovedAudienceClue.ReactionCount, } : null, - ["most_messaged_chat"] = mostMessagedChat, - ["most_messaged_direct_chat"] = mostMessagedDirectChat, - ["most_called_chat"] = mostCalledRoom, + ["most_messaged_chat"] = mostMessagedChatInfo is not null + ? new Dictionary + { + ["chat"] = mostMessagedChat, + ["message_counts"] = mostMessagedChatInfo.MessageCount, + } + : null, + ["most_messaged_direct_chat"] = mostMessagedDirectChatInfo is not null + ? new Dictionary + { + ["chat"] = mostMessagedDirectChat, + ["message_counts"] = mostMessagedDirectChatInfo.MessageCount + } + : null, + ["most_called_chat"] = new Dictionary + { + ["chat"] = mostCalledRoom, + ["duration"] = mostCalledRoomInfo?.TotalDuration + }, ["most_called_chat_top_members"] = mostCalledChatTopMembers, ["most_called_accounts"] = mostCalledAccounts, }; @@ -176,4 +209,4 @@ public class SphereRewindServiceGrpc( Data = GrpcTypeHelper.ConvertObjectToByteString(data) }; } -} +} \ No newline at end of file