mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-08-02 10:08:39 +00:00
Remove giant ActivityDto ternary and add more documentation in some areas
This commit is contained in:
parent
0445a0b3a6
commit
c2011837d7
23 changed files with 760 additions and 168 deletions
|
@ -3,7 +3,7 @@
|
|||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "7.0.13",
|
||||
"version": "8.0.0",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
|
|
|
@ -56,7 +56,7 @@ public class ActivityController : ControllerBase
|
|||
.ToListAsync();
|
||||
|
||||
List<int>? friendIds = UserFriendStore.GetUserFriendData(token.UserId)?.FriendIds;
|
||||
friendIds ??= new List<int>();
|
||||
friendIds ??= [];
|
||||
|
||||
// This is how lbp3 does its filtering
|
||||
GameStreamFilter? filter = await this.DeserializeBody<GameStreamFilter>();
|
||||
|
@ -89,7 +89,7 @@ public class ActivityController : ControllerBase
|
|||
predicate = predicate.Or(dto => dto.TargetSlotCreatorId == token.UserId);
|
||||
}
|
||||
|
||||
List<int> includedUserIds = new();
|
||||
List<int> includedUserIds = [];
|
||||
|
||||
if (!excludeFriends)
|
||||
{
|
||||
|
@ -168,7 +168,7 @@ public class ActivityController : ControllerBase
|
|||
|
||||
private static DateTime GetOldestTime
|
||||
(IReadOnlyCollection<IGrouping<ActivityGroup, ActivityDto>> groups, DateTime defaultTimestamp) =>
|
||||
groups.Any()
|
||||
groups.Count != 0
|
||||
? groups.Min(g => g.MinBy(a => a.Activity.Timestamp)?.Activity.Timestamp ?? defaultTimestamp)
|
||||
: defaultTimestamp;
|
||||
|
||||
|
@ -247,7 +247,7 @@ public class ActivityController : ControllerBase
|
|||
{
|
||||
GameTokenEntity token = this.GetToken();
|
||||
|
||||
if (token.GameVersion == GameVersion.LittleBigPlanet1) return this.NotFound();
|
||||
if (token.GameVersion is GameVersion.LittleBigPlanet1 or GameVersion.LittleBigPlanetPSP) return this.NotFound();
|
||||
|
||||
IQueryable<ActivityDto> activityEvents = await this.GetFilters(this.database.Activities.ToActivityDto(true),
|
||||
token,
|
||||
|
@ -305,10 +305,11 @@ public class ActivityController : ControllerBase
|
|||
{
|
||||
GameTokenEntity token = this.GetToken();
|
||||
|
||||
if (token.GameVersion == GameVersion.LittleBigPlanet1) return this.NotFound();
|
||||
if (token.GameVersion is GameVersion.LittleBigPlanet1 or GameVersion.LittleBigPlanetPSP) return this.NotFound();
|
||||
|
||||
if ((SlotHelper.IsTypeInvalid(slotType) || slotId == 0) == (username == null)) return this.BadRequest();
|
||||
|
||||
// User and Level activity will never contain news posts or MM pick events.
|
||||
IQueryable<ActivityDto> activityQuery = this.database.Activities.ToActivityDto()
|
||||
.Where(a => a.Activity.Type != EventType.NewsPost && a.Activity.Type != EventType.MMPickLevel);
|
||||
|
||||
|
@ -343,6 +344,8 @@ public class ActivityController : ControllerBase
|
|||
|
||||
List<OuterActivityGroup> outerGroups = groups.ToOuterActivityGroups();
|
||||
|
||||
PrintOuterGroups(outerGroups);
|
||||
|
||||
long oldestTimestamp = GetOldestTime(groups, times.Start).ToUnixTimeMilliseconds();
|
||||
|
||||
await this.CacheEntities(outerGroups);
|
||||
|
|
|
@ -1,31 +1,345 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Extensions;
|
||||
using LBPUnion.ProjectLighthouse.Tests.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Website;
|
||||
using LBPUnion.ProjectLighthouse.Types.Users;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Xunit;
|
||||
|
||||
namespace ProjectLighthouse.Tests.GameApiTests.Unit.Activity;
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
public class ActivityGroupingTests
|
||||
{
|
||||
[Fact]
|
||||
public void ActivityGroupingTest()
|
||||
public void ToOuterActivityGroups_ShouldCreateGroupPerObject_WhenGroupedBy_ObjectThenActor()
|
||||
{
|
||||
List<ActivityDto> activities = new()
|
||||
{
|
||||
new ActivityDto
|
||||
List<ActivityEntity> activities = [
|
||||
new LevelActivityEntity
|
||||
{
|
||||
TargetPlaylistId = 1,
|
||||
Activity = new ActivityEntity(),
|
||||
UserId = 1,
|
||||
SlotId = 1,
|
||||
Slot = new SlotEntity
|
||||
{
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
},
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.PlayLevel,
|
||||
},
|
||||
};
|
||||
List<OuterActivityGroup> groups = activities.AsQueryable().ToActivityGroups().ToList().ToOuterActivityGroups();
|
||||
new LevelActivityEntity
|
||||
{
|
||||
UserId = 1,
|
||||
SlotId = 1,
|
||||
Slot = new SlotEntity
|
||||
{
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
},
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.ReviewLevel,
|
||||
},
|
||||
new LevelActivityEntity
|
||||
{
|
||||
UserId = 2,
|
||||
SlotId = 1,
|
||||
Slot = new SlotEntity
|
||||
{
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
},
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.PlayLevel,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 2,
|
||||
UserId = 1,
|
||||
Type = EventType.HeartUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 2,
|
||||
UserId = 1,
|
||||
Type = EventType.CommentOnUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 1,
|
||||
UserId = 2,
|
||||
Type = EventType.HeartUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 1,
|
||||
UserId = 2,
|
||||
Type = EventType.CommentOnUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
];
|
||||
|
||||
//TODO: fix test
|
||||
List<OuterActivityGroup> groups = activities.ToActivityDto().AsQueryable().ToActivityGroups().ToList().ToOuterActivityGroups();
|
||||
Assert.NotNull(groups);
|
||||
Assert.Single(groups);
|
||||
OuterActivityGroup groupEntry = groups.First();
|
||||
|
||||
Assert.Equal(ActivityGroupType.Playlist, groupEntry.Key.GroupType);
|
||||
Assert.Equal(1, groupEntry.Key.TargetId);
|
||||
OuterActivityGroup outerGroup = groups.First();
|
||||
|
||||
Assert.Equal(ActivityGroupType.Level, outerGroup.Key.GroupType);
|
||||
Assert.Equal(1, outerGroup.Key.TargetSlotId);
|
||||
|
||||
IGrouping<InnerActivityGroup, ActivityDto>? firstGroup = outerGroup.Groups.First();
|
||||
IGrouping<InnerActivityGroup, ActivityDto>? secondGroup = outerGroup.Groups.Last();
|
||||
|
||||
Assert.NotNull(secondGroup);
|
||||
Assert.Equal(ActivityGroupType.User, secondGroup.Key.Type);
|
||||
Assert.Equal(1, secondGroup.Key.TargetId); // user group should have the user id
|
||||
Assert.Equal(1, secondGroup.ToList()[0].TargetSlotId); // events in user group should have t
|
||||
Assert.Equal(1, secondGroup.ToList()[1].TargetSlotId);
|
||||
|
||||
Assert.NotNull(firstGroup);
|
||||
Assert.Equal(ActivityGroupType.User, firstGroup.Key.Type);
|
||||
Assert.Equal(2, firstGroup.Key.TargetId);
|
||||
Assert.Equal(1, firstGroup.ToList()[0].TargetSlotId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToOuterActivityGroups_ShouldCreateGroupPerObject_WhenGroupedBy_ActorThenObject()
|
||||
{
|
||||
List<ActivityEntity> activities = [
|
||||
new LevelActivityEntity
|
||||
{
|
||||
UserId = 1,
|
||||
SlotId = 1,
|
||||
Slot = new SlotEntity
|
||||
{
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
},
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.PlayLevel,
|
||||
},
|
||||
new LevelActivityEntity
|
||||
{
|
||||
UserId = 1,
|
||||
SlotId = 1,
|
||||
Slot = new SlotEntity
|
||||
{
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
},
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.ReviewLevel,
|
||||
},
|
||||
new LevelActivityEntity
|
||||
{
|
||||
UserId = 2,
|
||||
SlotId = 1,
|
||||
Slot = new SlotEntity
|
||||
{
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
},
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.PlayLevel,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 2,
|
||||
UserId = 1,
|
||||
Type = EventType.HeartUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 2,
|
||||
UserId = 1,
|
||||
Type = EventType.CommentOnUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 1,
|
||||
UserId = 2,
|
||||
Type = EventType.HeartUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
new UserActivityEntity
|
||||
{
|
||||
TargetUserId = 1,
|
||||
UserId = 2,
|
||||
Type = EventType.CommentOnUser,
|
||||
Timestamp = DateTime.Now,
|
||||
},
|
||||
];
|
||||
List<OuterActivityGroup> groups = activities.ToActivityDto()
|
||||
.AsQueryable()
|
||||
.ToActivityGroups(true)
|
||||
.ToList()
|
||||
.ToOuterActivityGroups(true);
|
||||
//TODO: fix test
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.NotNull(groups);
|
||||
Assert.Equal(2, groups.Count);
|
||||
OuterActivityGroup firstUserGroup = groups.FirstOrDefault(g => g.Key.UserId == 1);
|
||||
OuterActivityGroup secondUserGroup = groups.FirstOrDefault(g => g.Key.UserId == 2);
|
||||
Assert.NotNull(firstUserGroup.Groups);
|
||||
Assert.NotNull(secondUserGroup.Groups);
|
||||
|
||||
Assert.Equal(ActivityGroupType.User, firstUserGroup.Key.GroupType);
|
||||
Assert.Equal(ActivityGroupType.User, secondUserGroup.Key.GroupType);
|
||||
|
||||
Assert.Single(firstUserGroup.Groups);
|
||||
Assert.Single(secondUserGroup.Groups);
|
||||
|
||||
Assert.Equal(2, firstUserGroup.Groups.ToList()[0].Count());
|
||||
Assert.Single(secondUserGroup.Groups.ToList()[0]);
|
||||
|
||||
// Assert.Equal(ActivityGroupType.Level, outerGroup.Key.GroupType);
|
||||
// Assert.Equal(1, outerGroup.Key.TargetSlotId);
|
||||
//
|
||||
// IGrouping<InnerActivityGroup, ActivityDto>? firstGroup = outerGroup.Groups.First();
|
||||
// IGrouping<InnerActivityGroup, ActivityDto>? secondGroup = outerGroup.Groups.Last();
|
||||
//
|
||||
// Assert.NotNull(secondGroup);
|
||||
// Assert.Equal(ActivityGroupType.User, secondGroup.Key.Type);
|
||||
// Assert.Equal(1, secondGroup.Key.TargetId); // user group should have the user id
|
||||
// Assert.Equal(1, secondGroup.ToList()[0].TargetSlotId); // events in user group should have t
|
||||
// Assert.Equal(1, secondGroup.ToList()[1].TargetSlotId);
|
||||
//
|
||||
// Assert.NotNull(firstGroup);
|
||||
// Assert.Equal(ActivityGroupType.User, firstGroup.Key.Type);
|
||||
// Assert.Equal(2, firstGroup.Key.TargetId);
|
||||
// Assert.Equal(1, firstGroup.ToList()[0].TargetSlotId);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToActivityDtoTest()
|
||||
{
|
||||
DatabaseContext db = await MockHelper.GetTestDatabase();
|
||||
db.Slots.Add(new SlotEntity
|
||||
{
|
||||
SlotId = 1,
|
||||
CreatorId = 1,
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
});
|
||||
db.Slots.Add(new SlotEntity
|
||||
{
|
||||
SlotId = 2,
|
||||
CreatorId = 1,
|
||||
GameVersion = GameVersion.LittleBigPlanet2,
|
||||
TeamPickTime = 1,
|
||||
});
|
||||
db.Reviews.Add(new ReviewEntity
|
||||
{
|
||||
Timestamp = DateTime.Now.ToUnixTimeMilliseconds(),
|
||||
SlotId = 1,
|
||||
ReviewerId = 1,
|
||||
ReviewId = 1,
|
||||
});
|
||||
db.Comments.Add(new CommentEntity
|
||||
{
|
||||
TargetSlotId = 1,
|
||||
PosterUserId = 1,
|
||||
Message = "comment on level test",
|
||||
CommentId = 1,
|
||||
});
|
||||
db.Comments.Add(new CommentEntity
|
||||
{
|
||||
TargetUserId = 1,
|
||||
PosterUserId = 1,
|
||||
Message = "comment on user test",
|
||||
CommentId = 2,
|
||||
});
|
||||
db.WebsiteAnnouncements.Add(new WebsiteAnnouncementEntity
|
||||
{
|
||||
PublisherId = 1,
|
||||
AnnouncementId = 1,
|
||||
});
|
||||
db.Playlists.Add(new PlaylistEntity
|
||||
{
|
||||
PlaylistId = 1,
|
||||
CreatorId = 1,
|
||||
});
|
||||
db.Activities.Add(new LevelActivityEntity
|
||||
{
|
||||
Timestamp = DateTime.Now,
|
||||
SlotId = 1,
|
||||
Type = EventType.PlayLevel,
|
||||
UserId = 1,
|
||||
});
|
||||
db.Activities.Add(new ReviewActivityEntity
|
||||
{
|
||||
Timestamp = DateTime.Now,
|
||||
SlotId = 1,
|
||||
Type = EventType.ReviewLevel,
|
||||
ReviewId = 1,
|
||||
UserId = 1,
|
||||
});
|
||||
db.Activities.Add(new UserCommentActivityEntity
|
||||
{
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.CommentOnUser,
|
||||
UserId = 1,
|
||||
TargetUserId = 1,
|
||||
CommentId = 2,
|
||||
});
|
||||
db.Activities.Add(new LevelCommentActivityEntity
|
||||
{
|
||||
Timestamp = DateTime.Now,
|
||||
Type = EventType.CommentOnLevel,
|
||||
UserId = 1,
|
||||
SlotId = 1,
|
||||
CommentId = 1,
|
||||
});
|
||||
db.Activities.Add(new NewsActivityEntity
|
||||
{
|
||||
Type = EventType.NewsPost,
|
||||
NewsId = 1,
|
||||
UserId = 1,
|
||||
});
|
||||
db.Activities.Add(new PlaylistActivityEntity
|
||||
{
|
||||
Type = EventType.CreatePlaylist,
|
||||
PlaylistId = 1,
|
||||
UserId = 1,
|
||||
});
|
||||
db.Activities.Add(new LevelActivityEntity
|
||||
{
|
||||
Type = EventType.MMPickLevel,
|
||||
SlotId = 2,
|
||||
UserId = 1,
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
var sql = db.Activities.ToActivityDto().ToQueryString();
|
||||
|
||||
List<ActivityDto> resultDto = await db.Activities.ToActivityDto(includeSlotCreator: true, includeTeamPick: true).ToListAsync();
|
||||
|
||||
Assert.Equal(2, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.MMPickLevel)?.TargetTeamPickId);
|
||||
Assert.Equal(2, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.MMPickLevel)?.TargetSlotId);
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.MMPickLevel)?.TargetSlotCreatorId);
|
||||
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.CreatePlaylist)?.TargetPlaylistId);
|
||||
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.NewsPost)?.TargetNewsId);
|
||||
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.CommentOnUser)?.TargetUserId);
|
||||
|
||||
Assert.Null(resultDto.FirstOrDefault(a => a.Activity.Type == EventType.CommentOnLevel)?.TargetTeamPickId);
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.CommentOnLevel)?.TargetSlotId);
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.CommentOnLevel)?.TargetSlotCreatorId);
|
||||
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.ReviewLevel)?.TargetSlotId);
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.ReviewLevel)?.TargetSlotCreatorId);
|
||||
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.PlayLevel)?.TargetSlotId);
|
||||
Assert.Equal(1, resultDto.FirstOrDefault(a => a.Activity.Type == EventType.PlayLevel)?.TargetSlotCreatorId);
|
||||
}
|
||||
}
|
|
@ -93,7 +93,7 @@ public class ActivityInterceptor : SaveChangesInterceptor
|
|||
{
|
||||
if (eventData.Context is not DatabaseContext context) return;
|
||||
|
||||
HashSet<CustomTrackedEntity> entities = new();
|
||||
HashSet<CustomTrackedEntity> entities = [];
|
||||
|
||||
List<EntityEntry> entries = context.ChangeTracker.Entries().ToList();
|
||||
|
||||
|
|
|
@ -109,13 +109,15 @@ public partial class DatabaseContext : DbContext
|
|||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<LevelActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<PhotoActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<UserPhotoActivity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<LevelPhotoActivity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<PlaylistActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<PlaylistWithSlotActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<ScoreActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<UserActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<NewsActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<CommentActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<LevelCommentActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<UserCommentActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<UserActivityEntity>().UseTphMappingStrategy();
|
||||
modelBuilder.Entity<ReviewActivityEntity>().UseTphMappingStrategy();
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using System.Linq;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Extensions;
|
||||
|
||||
|
@ -10,7 +9,7 @@ public static class ActivityQueryExtensions
|
|||
{
|
||||
public static List<int> GetIds(this IReadOnlyCollection<OuterActivityGroup> groups, ActivityGroupType type)
|
||||
{
|
||||
List<int> ids = new();
|
||||
List<int> ids = [];
|
||||
// Add outer group ids
|
||||
ids.AddRange(groups.Where(g => g.Key.GroupType == type)
|
||||
.Where(g => g.Key.TargetId != 0)
|
||||
|
@ -29,6 +28,12 @@ public static class ActivityQueryExtensions
|
|||
return ids.Distinct().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns a list of <see cref="ActivityDto"/> into a group based on its timestamp
|
||||
/// </summary>
|
||||
/// <param name="activityQuery">An <see cref="IQueryable{ActivityDto}"/> to group</param>
|
||||
/// <param name="groupByActor">Whether or not the groups should be created based on the initiator of the event or the target of the event</param>
|
||||
/// <returns>The transformed query containing groups of <see cref="ActivityDto"/></returns>
|
||||
public static IQueryable<IGrouping<ActivityGroup, ActivityDto>> ToActivityGroups
|
||||
(this IQueryable<ActivityDto> activityQuery, bool groupByActor = false) =>
|
||||
groupByActor
|
||||
|
@ -59,74 +64,65 @@ public static class ActivityQueryExtensions
|
|||
Groups = g.OrderByDescending(a => a.Activity.Timestamp)
|
||||
.GroupBy(gr => new InnerActivityGroup
|
||||
{
|
||||
Type = groupByActor ? gr.GroupType : gr.GroupType != ActivityGroupType.News ? ActivityGroupType.User : ActivityGroupType.News,
|
||||
Type = groupByActor
|
||||
? gr.GroupType
|
||||
: gr.GroupType != ActivityGroupType.News
|
||||
? ActivityGroupType.User
|
||||
: ActivityGroupType.News,
|
||||
UserId = gr.Activity.UserId,
|
||||
TargetId = groupByActor ? gr.TargetId : gr.GroupType != ActivityGroupType.News ? gr.Activity.UserId : gr.TargetNewsId ?? 0,
|
||||
TargetId = groupByActor
|
||||
? gr.TargetId
|
||||
: gr.GroupType != ActivityGroupType.News
|
||||
? gr.Activity.UserId
|
||||
: gr.TargetNewsId ?? 0,
|
||||
})
|
||||
.ToList(),
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// WARNING - To the next person who tries to improve this code: As of writing this, it's not possible
|
||||
// to build a pattern matching switch statement with expression trees. so the only other option
|
||||
// is to basically rewrite this nested ternary mess with expression trees which isn't much better
|
||||
// The resulting SQL generated by EntityFramework uses a CASE statement which is probably fine
|
||||
// TOTAL HOURS WASTED: 3
|
||||
/// <summary>
|
||||
/// Converts an <see cref="IQueryable"/><<see cref="ActivityEntity"/>> into an <see cref="IQueryable"/><<see cref="ActivityDto"/>> for grouping.
|
||||
/// </summary>
|
||||
/// <param name="activityQuery">The activity query to be converted.</param>
|
||||
/// <param name="includeSlotCreator">Whether or not the <see cref="ActivityDto.TargetSlotCreatorId"/> field should be included.</param>
|
||||
/// <param name="includeTeamPick">Whether or not the <see cref="ActivityDto.TargetTeamPickId"/> field should be included.</param>
|
||||
/// <returns>The converted <see cref="IQueryable"/><<see cref="ActivityDto"/>></returns>
|
||||
public static IQueryable<ActivityDto> ToActivityDto
|
||||
(this IQueryable<ActivityEntity> activityQuery, bool includeSlotCreator = false, bool includeTeamPick = false)
|
||||
{
|
||||
return activityQuery.Select(a => new ActivityDto
|
||||
{
|
||||
Activity = a,
|
||||
TargetSlotId = a is LevelActivityEntity
|
||||
? ((LevelActivityEntity)a).SlotId
|
||||
: a is PhotoActivityEntity && ((PhotoActivityEntity)a).Photo.SlotId != 0
|
||||
? ((PhotoActivityEntity)a).Photo.SlotId
|
||||
: a is CommentActivityEntity && ((CommentActivityEntity)a).Comment.Type == CommentType.Level
|
||||
? ((CommentActivityEntity)a).Comment.TargetSlotId
|
||||
: a is ScoreActivityEntity
|
||||
? ((ScoreActivityEntity)a).Score.SlotId
|
||||
: a is ReviewActivityEntity
|
||||
? ((ReviewActivityEntity)a).Review.SlotId
|
||||
: 0,
|
||||
TargetSlotGameVersion = a is LevelActivityEntity
|
||||
? ((LevelActivityEntity)a).Slot.GameVersion
|
||||
: a is PhotoActivityEntity && ((PhotoActivityEntity)a).Photo.SlotId != 0
|
||||
? ((PhotoActivityEntity)a).Photo.Slot.GameVersion
|
||||
: a is CommentActivityEntity && ((CommentActivityEntity)a).Comment.Type == CommentType.Level
|
||||
? ((CommentActivityEntity)a).Comment.TargetSlot.GameVersion
|
||||
: a is ScoreActivityEntity
|
||||
? ((ScoreActivityEntity)a).Score.Slot.GameVersion
|
||||
: a is ReviewActivityEntity
|
||||
? ((ReviewActivityEntity)a).Review.Slot.GameVersion
|
||||
: 0,
|
||||
TargetSlotCreatorId = includeSlotCreator
|
||||
? a is LevelActivityEntity
|
||||
? ((LevelActivityEntity)a).Slot.CreatorId
|
||||
: a is PhotoActivityEntity && ((PhotoActivityEntity)a).Photo.SlotId != 0
|
||||
? ((PhotoActivityEntity)a).Photo.Slot!.CreatorId
|
||||
: a is CommentActivityEntity && ((CommentActivityEntity)a).Comment.Type == CommentType.Level
|
||||
? ((CommentActivityEntity)a).Comment.TargetSlot.CreatorId
|
||||
: a is ScoreActivityEntity
|
||||
? ((ScoreActivityEntity)a).Score.Slot.CreatorId
|
||||
: a is ReviewActivityEntity
|
||||
? ((ReviewActivityEntity)a).Review.Slot!.CreatorId
|
||||
: 0
|
||||
: 0,
|
||||
TargetSlotId = (a as LevelActivityEntity).SlotId,
|
||||
TargetSlotGameVersion = (a as LevelActivityEntity).Slot.GameVersion,
|
||||
TargetSlotCreatorId = includeSlotCreator ? (a as LevelActivityEntity).Slot.CreatorId : null,
|
||||
TargetUserId = (a as UserActivityEntity).TargetUserId,
|
||||
TargetNewsId = (a as NewsActivityEntity).NewsId,
|
||||
TargetPlaylistId = (a as PlaylistActivityEntity).PlaylistId,
|
||||
TargetTeamPickId =
|
||||
includeTeamPick && a.Type == EventType.MMPickLevel ? (a as LevelActivityEntity).SlotId : null, });
|
||||
}
|
||||
|
||||
TargetUserId = a is UserActivityEntity
|
||||
? ((UserActivityEntity)a).TargetUserId
|
||||
: a is CommentActivityEntity && ((CommentActivityEntity)a).Comment.Type == CommentType.Profile
|
||||
? ((CommentActivityEntity)a).Comment.TargetUserId
|
||||
: a is PhotoActivityEntity && ((PhotoActivityEntity)a).Photo.SlotId == 0
|
||||
? ((PhotoActivityEntity)a).Photo.CreatorId
|
||||
: 0,
|
||||
TargetPlaylistId = a is PlaylistActivityEntity || a is PlaylistWithSlotActivityEntity
|
||||
? ((PlaylistActivityEntity)a).PlaylistId
|
||||
: 0,
|
||||
TargetNewsId = a is NewsActivityEntity ? ((NewsActivityEntity)a).NewsId : 0,
|
||||
TargetTeamPickId = includeTeamPick
|
||||
? a.Type == EventType.MMPickLevel && a is LevelActivityEntity ? ((LevelActivityEntity)a).SlotId : 0
|
||||
: 0, });
|
||||
/// <summary>
|
||||
/// Converts an IEnumerable<<see cref="ActivityEntity"/>> into an IEnumerable<<see cref="ActivityDto"/>> for grouping.
|
||||
/// </summary>
|
||||
/// <param name="activityEnumerable">The activity query to be converted.</param>
|
||||
/// <param name="includeSlotCreator">Whether or not the <see cref="ActivityDto.TargetSlotCreatorId"/> field should be included.</param>
|
||||
/// <param name="includeTeamPick">Whether or not the <see cref="ActivityDto.TargetTeamPickId"/> field should be included.</param>
|
||||
/// <returns>The converted IEnumerable<<see cref="ActivityDto"/>></returns>
|
||||
public static IEnumerable<ActivityDto> ToActivityDto
|
||||
(this IEnumerable<ActivityEntity> activityEnumerable, bool includeSlotCreator = false, bool includeTeamPick = false)
|
||||
{
|
||||
return activityEnumerable.Select(a => new ActivityDto
|
||||
{
|
||||
Activity = a,
|
||||
TargetSlotId = (a as LevelActivityEntity)?.SlotId,
|
||||
TargetSlotGameVersion = (a as LevelActivityEntity)?.Slot.GameVersion,
|
||||
TargetSlotCreatorId = includeSlotCreator ? (a as LevelActivityEntity)?.Slot.CreatorId : null,
|
||||
TargetUserId = (a as UserActivityEntity)?.TargetUserId,
|
||||
TargetNewsId = (a as NewsActivityEntity)?.NewsId,
|
||||
TargetPlaylistId = (a as PlaylistActivityEntity)?.PlaylistId,
|
||||
TargetTeamPickId =
|
||||
includeTeamPick && a.Type == EventType.MMPickLevel ? (a as LevelActivityEntity)?.SlotId : null, });
|
||||
}
|
||||
}
|
|
@ -6,10 +6,10 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
|||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
namespace LBPUnion.ProjectLighthouse.Migrations
|
||||
{
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240120214525_InitialActivity")]
|
||||
[Migration("20240325034658_InitialActivity")]
|
||||
public partial class InitialActivity : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
@ -24,12 +24,12 @@ namespace ProjectLighthouse.Migrations
|
|||
Timestamp = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
UserId = table.Column<int>(type: "int", nullable: false),
|
||||
Type = table.Column<int>(type: "int", nullable: false),
|
||||
Discriminator = table.Column<string>(type: "longtext", nullable: false)
|
||||
Discriminator = table.Column<string>(type: "varchar(34)", maxLength: 34, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
CommentId = table.Column<int>(type: "int", nullable: true),
|
||||
SlotId = table.Column<int>(type: "int", nullable: true),
|
||||
NewsId = table.Column<int>(type: "int", nullable: true),
|
||||
CommentId = table.Column<int>(type: "int", nullable: true),
|
||||
PhotoId = table.Column<int>(type: "int", nullable: true),
|
||||
NewsId = table.Column<int>(type: "int", nullable: true),
|
||||
PlaylistId = table.Column<int>(type: "int", nullable: true),
|
||||
ReviewId = table.Column<int>(type: "int", nullable: true),
|
||||
ScoreId = table.Column<int>(type: "int", nullable: true),
|
|
@ -27,7 +27,8 @@ namespace ProjectLighthouse.Migrations
|
|||
|
||||
b.Property<string>("Discriminator")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
.HasMaxLength(34)
|
||||
.HasColumnType("varchar(34)");
|
||||
|
||||
b.Property<DateTime>("Timestamp")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
@ -1123,18 +1124,6 @@ namespace ProjectLighthouse.Migrations
|
|||
b.ToTable("WebsiteAnnouncements");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.CommentActivityEntity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
||||
b.Property<int>("CommentId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasIndex("CommentId");
|
||||
|
||||
b.HasDiscriminator().HasValue("CommentActivityEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.LevelActivityEntity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
@ -1149,6 +1138,46 @@ namespace ProjectLighthouse.Migrations
|
|||
b.HasDiscriminator().HasValue("LevelActivityEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.LevelCommentActivityEntity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
||||
b.Property<int>("CommentId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SlotId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("SlotId");
|
||||
|
||||
b.HasIndex("CommentId");
|
||||
|
||||
b.HasIndex("SlotId");
|
||||
|
||||
b.HasDiscriminator().HasValue("LevelCommentActivityEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.LevelPhotoActivity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
||||
b.Property<int>("PhotoId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SlotId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("SlotId");
|
||||
|
||||
b.HasIndex("PhotoId");
|
||||
|
||||
b.HasIndex("SlotId");
|
||||
|
||||
b.HasDiscriminator().HasValue("LevelPhotoActivity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.NewsActivityEntity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
@ -1161,18 +1190,6 @@ namespace ProjectLighthouse.Migrations
|
|||
b.HasDiscriminator().HasValue("NewsActivityEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.PhotoActivityEntity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
||||
b.Property<int>("PhotoId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasIndex("PhotoId");
|
||||
|
||||
b.HasDiscriminator().HasValue("PhotoActivityEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.PlaylistActivityEntity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
@ -1213,8 +1230,15 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Property<int>("ReviewId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SlotId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("SlotId");
|
||||
|
||||
b.HasIndex("ReviewId");
|
||||
|
||||
b.HasIndex("SlotId");
|
||||
|
||||
b.HasDiscriminator().HasValue("ReviewActivityEntity");
|
||||
});
|
||||
|
||||
|
@ -1225,8 +1249,15 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Property<int>("ScoreId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("SlotId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("SlotId");
|
||||
|
||||
b.HasIndex("ScoreId");
|
||||
|
||||
b.HasIndex("SlotId");
|
||||
|
||||
b.HasDiscriminator().HasValue("ScoreActivityEntity");
|
||||
});
|
||||
|
||||
|
@ -1235,13 +1266,55 @@ namespace ProjectLighthouse.Migrations
|
|||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
||||
b.Property<int>("TargetUserId")
|
||||
.HasColumnType("int");
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("TargetUserId");
|
||||
|
||||
b.HasIndex("TargetUserId");
|
||||
|
||||
b.HasDiscriminator().HasValue("UserActivityEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.UserCommentActivityEntity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
||||
b.Property<int>("CommentId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TargetUserId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("TargetUserId");
|
||||
|
||||
b.HasIndex("CommentId");
|
||||
|
||||
b.HasIndex("TargetUserId");
|
||||
|
||||
b.HasDiscriminator().HasValue("UserCommentActivityEntity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.UserPhotoActivity", b =>
|
||||
{
|
||||
b.HasBaseType("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity");
|
||||
|
||||
b.Property<int>("PhotoId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TargetUserId")
|
||||
.ValueGeneratedOnUpdateSometimes()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("TargetUserId");
|
||||
|
||||
b.HasIndex("PhotoId");
|
||||
|
||||
b.HasIndex("TargetUserId");
|
||||
|
||||
b.HasDiscriminator().HasValue("UserPhotoActivity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity", "User")
|
||||
|
@ -1646,17 +1719,6 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Navigation("Publisher");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.CommentActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.CommentEntity", "Comment")
|
||||
.WithMany()
|
||||
.HasForeignKey("CommentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Comment");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.LevelActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity", "Slot")
|
||||
|
@ -1668,6 +1730,44 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Navigation("Slot");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.LevelCommentActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.CommentEntity", "Comment")
|
||||
.WithMany()
|
||||
.HasForeignKey("CommentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity", "Slot")
|
||||
.WithMany()
|
||||
.HasForeignKey("SlotId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Comment");
|
||||
|
||||
b.Navigation("Slot");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.LevelPhotoActivity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoEntity", "Photo")
|
||||
.WithMany()
|
||||
.HasForeignKey("PhotoId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity", "Slot")
|
||||
.WithMany()
|
||||
.HasForeignKey("SlotId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Photo");
|
||||
|
||||
b.Navigation("Slot");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.NewsActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Website.WebsiteAnnouncementEntity", "News")
|
||||
|
@ -1679,17 +1779,6 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Navigation("News");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.PhotoActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoEntity", "Photo")
|
||||
.WithMany()
|
||||
.HasForeignKey("PhotoId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Photo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.PlaylistActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.PlaylistEntity", "Playlist")
|
||||
|
@ -1720,7 +1809,15 @@ namespace ProjectLighthouse.Migrations
|
|||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity", "Slot")
|
||||
.WithMany()
|
||||
.HasForeignKey("SlotId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Review");
|
||||
|
||||
b.Navigation("Slot");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.ScoreActivityEntity", b =>
|
||||
|
@ -1731,7 +1828,15 @@ namespace ProjectLighthouse.Migrations
|
|||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Level.SlotEntity", "Slot")
|
||||
.WithMany()
|
||||
.HasForeignKey("SlotId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Score");
|
||||
|
||||
b.Navigation("Slot");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.UserActivityEntity", b =>
|
||||
|
@ -1745,6 +1850,44 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Navigation("TargetUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.UserCommentActivityEntity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.CommentEntity", "Comment")
|
||||
.WithMany()
|
||||
.HasForeignKey("CommentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity", "TargetUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("TargetUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Comment");
|
||||
|
||||
b.Navigation("TargetUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Activity.UserPhotoActivity", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoEntity", "Photo")
|
||||
.WithMany()
|
||||
.HasForeignKey("PhotoId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.Entities.Profile.UserEntity", "TargetUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("TargetUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Photo");
|
||||
|
||||
b.Navigation("TargetUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Profile.PhotoEntity", b =>
|
||||
{
|
||||
b.Navigation("PhotoSubjects");
|
||||
|
|
|
@ -25,11 +25,11 @@ public class ActivityDto
|
|||
};
|
||||
|
||||
public ActivityGroupType GroupType =>
|
||||
this.TargetSlotId != 0
|
||||
this.TargetSlotId != null
|
||||
? ActivityGroupType.Level
|
||||
: this.TargetUserId != 0
|
||||
: this.TargetUserId != null
|
||||
? ActivityGroupType.User
|
||||
: this.TargetPlaylistId != 0
|
||||
: this.TargetPlaylistId != null
|
||||
? ActivityGroupType.Playlist
|
||||
: ActivityGroupType.News;
|
||||
}
|
|
@ -41,40 +41,44 @@ public class ActivityEntityEventHandler : IEntityEventHandler
|
|||
{
|
||||
CommentType.Level => comment.TargetSlot?.Type switch
|
||||
{
|
||||
SlotType.User => new CommentActivityEntity
|
||||
SlotType.User => new LevelCommentActivityEntity
|
||||
{
|
||||
Type = EventType.CommentOnLevel,
|
||||
CommentId = comment.CommentId,
|
||||
UserId = comment.PosterUserId,
|
||||
SlotId = comment.TargetSlotId ?? throw new NullReferenceException("SlotId in Level comment is null, this shouldn't happen."),
|
||||
},
|
||||
_ => null,
|
||||
},
|
||||
CommentType.Profile => new CommentActivityEntity
|
||||
CommentType.Profile => new UserCommentActivityEntity()
|
||||
{
|
||||
Type = EventType.CommentOnUser,
|
||||
CommentId = comment.CommentId,
|
||||
UserId = comment.PosterUserId,
|
||||
TargetUserId = comment.TargetUserId ?? throw new NullReferenceException("TargetUserId in User comment is null, this shouldn't happen."),
|
||||
},
|
||||
_ => null,
|
||||
},
|
||||
PhotoEntity photo => photo.SlotId switch
|
||||
{
|
||||
// Photos without levels
|
||||
null => new PhotoActivityEntity
|
||||
null => new UserPhotoActivity
|
||||
{
|
||||
Type = EventType.UploadPhoto,
|
||||
PhotoId = photo.PhotoId,
|
||||
UserId = photo.CreatorId,
|
||||
TargetUserId = photo.CreatorId,
|
||||
},
|
||||
_ => photo.Slot?.Type switch
|
||||
{
|
||||
SlotType.Developer => null,
|
||||
// Non-story levels (moon, pod, etc)
|
||||
_ => new PhotoActivityEntity
|
||||
_ => new LevelPhotoActivity
|
||||
{
|
||||
Type = EventType.UploadPhoto,
|
||||
PhotoId = photo.PhotoId,
|
||||
UserId = photo.CreatorId,
|
||||
SlotId = photo.SlotId ?? throw new NullReferenceException("SlotId in Photo is null"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -86,6 +90,7 @@ public class ActivityEntityEventHandler : IEntityEventHandler
|
|||
Type = EventType.Score,
|
||||
ScoreId = score.ScoreId,
|
||||
UserId = score.UserId,
|
||||
SlotId = score.SlotId,
|
||||
},
|
||||
_ => null,
|
||||
},
|
||||
|
@ -122,6 +127,7 @@ public class ActivityEntityEventHandler : IEntityEventHandler
|
|||
Type = EventType.ReviewLevel,
|
||||
ReviewId = review.ReviewId,
|
||||
UserId = review.ReviewerId,
|
||||
SlotId = review.SlotId,
|
||||
},
|
||||
RatedLevelEntity ratedLevel => new LevelActivityEntity
|
||||
{
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
namespace LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// UnheartLevel, UnheartUser, DeleteLevelComment, and UnpublishLevel don't actually do anything
|
||||
/// An enum of all possible event types that LBP recognizes in Recent Activity
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <see cref="UnheartLevel"/>, <see cref="UnheartUser"/>, <see cref="DeleteLevelComment"/>, <see cref="UnpublishLevel"/> are ignored by the game
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
public enum EventType
|
||||
{
|
||||
|
@ -61,12 +66,21 @@ public enum EventType
|
|||
[XmlEnum("comment_on_user")]
|
||||
CommentOnUser = 17,
|
||||
|
||||
/// <remarks>
|
||||
/// This event is only used in LBP3
|
||||
/// </remarks>>
|
||||
[XmlEnum("create_playlist")]
|
||||
CreatePlaylist = 18,
|
||||
|
||||
/// <remarks>
|
||||
/// This event is only used in LBP3
|
||||
/// </remarks>>
|
||||
[XmlEnum("heart_playlist")]
|
||||
HeartPlaylist = 19,
|
||||
|
||||
/// <remarks>
|
||||
/// This event is only used in LBP3
|
||||
/// </remarks>>
|
||||
[XmlEnum("add_level_to_playlist")]
|
||||
AddLevelToPlaylist = 20,
|
||||
}
|
|
@ -11,12 +11,21 @@ public class ActivityEntity
|
|||
[Key]
|
||||
public int ActivityId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time that this event took place.
|
||||
/// </summary>
|
||||
public DateTime Timestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="UserEntity.UserId"/> of the <see cref="UserEntity"/> that triggered this event.
|
||||
/// </summary>
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public UserEntity User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of this event.
|
||||
/// </summary>
|
||||
public EventType Type { get; set; }
|
||||
}
|
|
@ -1,15 +1,38 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: CommentOnUser, CommentOnLevel, DeleteLevelComment
|
||||
/// Supported event types: <see cref="EventType.CommentOnUser"/>, <see cref="EventType.CommentOnLevel"/>, and <see cref="EventType.DeleteLevelComment"/>.
|
||||
/// </summary>
|
||||
public class CommentActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="CommentEntity.CommentId"/> of the <see cref="CommentEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
public int CommentId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(CommentId))]
|
||||
public CommentEntity Comment { get; set; }
|
||||
}
|
||||
|
||||
public class LevelCommentActivityEntity : CommentActivityEntity
|
||||
{
|
||||
[Column("SlotId")]
|
||||
public int SlotId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(SlotId))]
|
||||
public SlotEntity Slot { get; set; }
|
||||
}
|
||||
|
||||
public class UserCommentActivityEntity : CommentActivityEntity
|
||||
{
|
||||
[Column("TargetUserId")]
|
||||
public int TargetUserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(TargetUserId))]
|
||||
public UserEntity TargetUser { get; set; }
|
||||
}
|
|
@ -1,13 +1,18 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: play_level, heart_level, publish_level, unheart_level, dpad_rate_level, rate_level, tag_level, mm_pick_level
|
||||
/// Supported event types: <see cref="EventType.PlayLevel"/>, <see cref="EventType.HeartLevel"/>, <see cref="EventType.PublishLevel"/>,
|
||||
/// <see cref="EventType.UnheartLevel"/>, and <see cref="EventType.MMPickLevel"/>.
|
||||
/// </summary>
|
||||
public class LevelActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="SlotEntity.SlotId"/> of the <see cref="SlotEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
[Column("SlotId")]
|
||||
public int SlotId { get; set; }
|
||||
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Website;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: NewsPost
|
||||
/// Supported event types: <see cref="EventType.NewsPost"/>.
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This event type can only be grouped with other <see cref="NewsActivityEntity"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
public class NewsActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="WebsiteAnnouncementEntity.AnnouncementId"/> of the <see cref="WebsiteAnnouncementEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
public int NewsId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(NewsId))]
|
||||
|
|
|
@ -1,16 +1,38 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: UploadPhoto
|
||||
/// Supported event types: <see cref="EventType.UploadPhoto"/>.
|
||||
/// </summary>
|
||||
public class PhotoActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="PhotoEntity.PhotoId"/> of the <see cref="PhotoEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
public int PhotoId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(PhotoId))]
|
||||
public PhotoEntity Photo { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class LevelPhotoActivity : PhotoActivityEntity
|
||||
{
|
||||
[Column("SlotId")]
|
||||
public int SlotId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(SlotId))]
|
||||
public SlotEntity Slot { get; set; }
|
||||
}
|
||||
|
||||
public class UserPhotoActivity : PhotoActivityEntity
|
||||
{
|
||||
[Column("TargetUserId")]
|
||||
public int TargetUserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(TargetUserId))]
|
||||
public UserEntity TargetUser { get; set; }
|
||||
}
|
|
@ -1,13 +1,17 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: CreatePlaylist, HeartPlaylist
|
||||
/// Supported event types: <see cref="EventType.CreatePlaylist"/> and <see cref="EventType.HeartPlaylist"/>.
|
||||
/// </summary>
|
||||
public class PlaylistActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="PlaylistEntity.PlaylistId"/> of the <see cref="PlaylistEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
[Column("PlaylistId")]
|
||||
public int PlaylistId { get; set; }
|
||||
|
||||
|
@ -16,15 +20,19 @@ public class PlaylistActivityEntity : ActivityEntity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: AddLevelToPlaylist
|
||||
/// Supported event types: <see cref="EventType.AddLevelToPlaylist"/>.
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The relationship between <see cref="PlaylistActivityEntity"/> and <see cref="PlaylistWithSlotActivityEntity"/>
|
||||
/// is slightly hacky but it allows conditional reuse of columns from other ActivityEntity's
|
||||
///
|
||||
/// </para>
|
||||
/// is slightly hacky but it allows us to reuse columns that would normally only be user with other <see cref="ActivityEntity"/> types.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
public class PlaylistWithSlotActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="PlaylistEntity.PlaylistId"/> of the <see cref="PlaylistEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
[Column("PlaylistId")]
|
||||
public int PlaylistId { get; set; }
|
||||
|
||||
|
@ -33,7 +41,11 @@ public class PlaylistWithSlotActivityEntity : ActivityEntity
|
|||
|
||||
/// <summary>
|
||||
/// This reuses the SlotId column of <see cref="LevelActivityEntity"/> but has no ForeignKey definition so that it can be null
|
||||
/// <para>It effectively serves as extra storage for PlaylistActivityEntity to use for the AddLevelToPlaylistEvent</para>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// It effectively serves as extra storage for PlaylistActivityEntity to use for the AddLevelToPlaylistEvent
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
[Column("SlotId")]
|
||||
public int SlotId { get; set; }
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: DpadRateLevel, ReviewLevel, RateLevel, TagLevel
|
||||
/// Supported event types: <see cref="EventType.DpadRateLevel"/>, <see cref="EventType.ReviewLevel"/>, <see cref="EventType.RateLevel"/>, and <see cref="EventType.TagLevel"/>.
|
||||
/// </summary>
|
||||
public class ReviewActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ReviewEntity.ReviewId"/> of the <see cref="ReviewEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
public int ReviewId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(ReviewId))]
|
||||
public ReviewEntity Review { get; set; }
|
||||
|
||||
[Column("SlotId")]
|
||||
public int SlotId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(SlotId))]
|
||||
public SlotEntity Slot { get; set; }
|
||||
}
|
|
@ -1,15 +1,25 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: Score
|
||||
/// Supported event types: <see cref="EventType.Score"/>.
|
||||
/// </summary>
|
||||
public class ScoreActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ScoreEntity.ScoreId"/> of the <see cref="ScoreEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
public int ScoreId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(ScoreId))]
|
||||
public ScoreEntity Score { get; set; }
|
||||
|
||||
[Column("SlotId")]
|
||||
public int SlotId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(SlotId))]
|
||||
public SlotEntity Slot { get; set; }
|
||||
}
|
|
@ -1,13 +1,18 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using LBPUnion.ProjectLighthouse.Types.Activity;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types.Entities.Activity;
|
||||
|
||||
/// <summary>
|
||||
/// Supported event types: HeartUser, UnheartUser
|
||||
/// Supported event types: <see cref="EventType.HeartUser"/> and <see cref="EventType.UnheartUser"/>.
|
||||
/// </summary>
|
||||
public class UserActivityEntity : ActivityEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="UserEntity.UserId"/> of the <see cref="UserEntity"/> that this event refers to.
|
||||
/// </summary>
|
||||
[Column("TargetUserId")]
|
||||
public int TargetUserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(TargetUserId))]
|
||||
|
|
|
@ -58,7 +58,7 @@ public class GameEvent : ILbpSerializable, INeedsPreparationForSerialization
|
|||
|
||||
public static IEnumerable<GameEvent> CreateFromActivities(IEnumerable<ActivityDto> activities)
|
||||
{
|
||||
List<GameEvent> events = new();
|
||||
List<GameEvent> events = [];
|
||||
List<IGrouping<EventType, ActivityDto>> typeGroups = activities.GroupBy(g => g.Activity.Type).ToList();
|
||||
foreach (IGrouping<EventType, ActivityDto> typeGroup in typeGroups)
|
||||
{
|
||||
|
|
|
@ -26,21 +26,34 @@ namespace LBPUnion.ProjectLighthouse.Types.Serialization.Activity;
|
|||
[XmlRoot("stream")]
|
||||
public class GameStream : ILbpSerializable, INeedsPreparationForSerialization
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of <see cref="SlotEntity.SlotId"/> that should be included in the root
|
||||
/// of the stream object. These will be loaded into <see cref="Slots"/>
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public List<int> SlotIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of <see cref="UserEntity.UserId"/> that should be included in the root
|
||||
/// of the stream object. These will be loaded into <see cref="Users"/>
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public List<int> UserIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of <see cref="PlaylistEntity.PlaylistId"/> that should be included in the root
|
||||
/// of the stream object. These will be loaded into <see cref="Playlists"/>
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public List<int> PlaylistIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of <see cref="WebsiteAnnouncementEntity.AnnouncementId"/> that should be included in the root
|
||||
/// of the stream object. These will be loaded into <see cref="News"/>
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public List<int> NewsIds { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
private int TargetUserId { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
private GameVersion TargetGame { get; set; }
|
||||
|
||||
|
@ -77,7 +90,7 @@ public class GameStream : ILbpSerializable, INeedsPreparationForSerialization
|
|||
|
||||
public async Task PrepareSerialization(DatabaseContext database)
|
||||
{
|
||||
this.Slots = await LoadEntities<SlotEntity, SlotBase>(this.SlotIds, slot => SlotBase.CreateFromEntity(slot, this.TargetGame, this.TargetUserId), s => s.Type == SlotType.User);
|
||||
this.Slots = await LoadEntities<SlotEntity, SlotBase>(this.SlotIds, slot => SlotBase.CreateFromEntity(slot, this.TargetGame, 0), s => s.Type == SlotType.User);
|
||||
this.Users = await LoadEntities<UserEntity, GameUser>(this.UserIds, user => GameUser.CreateFromEntity(user, this.TargetGame));
|
||||
this.Playlists = await LoadEntities<PlaylistEntity, GamePlaylist>(this.PlaylistIds, GamePlaylist.CreateFromEntity);
|
||||
this.News = await LoadEntities<WebsiteAnnouncementEntity, GameNewsObject>(this.NewsIds, a => GameNewsObject.CreateFromEntity(a, this.TargetGame));
|
||||
|
@ -86,16 +99,16 @@ public class GameStream : ILbpSerializable, INeedsPreparationForSerialization
|
|||
async Task<List<TResult>> LoadEntities<TFrom, TResult>(List<int> ids, Func<TFrom, TResult> transformation, Func<TFrom, bool> predicate = null)
|
||||
where TFrom : class
|
||||
{
|
||||
List<TResult> results = new();
|
||||
List<TResult> results = [];
|
||||
if (ids.Count <= 0) return null;
|
||||
foreach (int id in ids)
|
||||
{
|
||||
TFrom entity = await database.Set<TFrom>().FindAsync(id);
|
||||
|
||||
if (predicate != null && !predicate(entity)) continue;
|
||||
|
||||
if (entity == null) continue;
|
||||
|
||||
if (predicate != null && !predicate(entity)) continue;
|
||||
|
||||
results.Add(transformation(entity));
|
||||
}
|
||||
|
||||
|
@ -108,7 +121,6 @@ public class GameStream : ILbpSerializable, INeedsPreparationForSerialization
|
|||
{
|
||||
GameStream gameStream = new()
|
||||
{
|
||||
TargetUserId = token.UserId,
|
||||
TargetGame = token.GameVersion,
|
||||
StartTimestamp = startTimestamp,
|
||||
EndTimestamp = endTimestamp,
|
||||
|
|
|
@ -37,8 +37,6 @@ public class GameStreamGroup : ILbpSerializable
|
|||
[XmlArray("events")]
|
||||
[XmlArrayItem("event")]
|
||||
[DefaultValue(null)]
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
// (the serializer can't see this if it's private)
|
||||
public List<GameEvent> Events { get; set; }
|
||||
|
||||
public static GameStreamGroup CreateFromGroup(OuterActivityGroup group)
|
||||
|
@ -56,8 +54,7 @@ public class GameStreamGroup : ILbpSerializable
|
|||
g.Key.TargetId,
|
||||
streamGroup =>
|
||||
{
|
||||
streamGroup.Timestamp =
|
||||
g.MaxBy(a => a.Activity.Timestamp).Activity.Timestamp.ToUnixTimeMilliseconds();
|
||||
streamGroup.Timestamp = g.Max(a => a.Activity.Timestamp).ToUnixTimeMilliseconds();
|
||||
streamGroup.Events = GameEvent.CreateFromActivities(g).ToList();
|
||||
}))
|
||||
.ToList());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue