Simplify filters and make cross control slots not show by default (#782)

* Simplify filters and make cross control slots not show by default
Also sort author levels by oldest levels first rather than newest levels first.

* Fix unit test expecting slots to sorted by timestamp descending

* Remove errant whitespace
This commit is contained in:
Josh 2023-06-05 17:53:41 -05:00 committed by GitHub
parent 2a85b6a136
commit a69d94054b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 114 additions and 58 deletions

View file

@ -49,7 +49,9 @@ public class SlotsController : ControllerBase
SlotQueryBuilder queryBuilder = this.FilterFromRequest(token).AddFilter(new CreatorFilter(targetUserId)); SlotQueryBuilder queryBuilder = this.FilterFromRequest(token).AddFilter(new CreatorFilter(targetUserId));
SlotSortBuilder<SlotEntity> sortBuilder = new SlotSortBuilder<SlotEntity>().AddSort(new FirstUploadedSort()); SlotSortBuilder<SlotEntity> sortBuilder = new SlotSortBuilder<SlotEntity>()
.AddSort(new FirstUploadedSort())
.SortDescending(false);
List<SlotBase> slots = await this.database.GetSlots(token, queryBuilder, pageData, sortBuilder); List<SlotBase> slots = await this.database.GetSlots(token, queryBuilder, pageData, sortBuilder);

View file

@ -92,8 +92,8 @@ public static class ControllerExtensions
} }
} }
if (bool.TryParse(controller.Request.Query["crosscontrol"], out bool crossControl) && crossControl) bool _ = bool.TryParse(controller.Request.Query["crosscontrol"], out bool showCrossControl);
queryBuilder.AddFilter(new CrossControlFilter()); if (showCrossControl) queryBuilder.AddFilter(new CrossControlFilter());
GameVersion targetVersion = token.GameVersion; GameVersion targetVersion = token.GameVersion;
@ -171,6 +171,9 @@ public static class ControllerExtensions
if (token.GameVersion != GameVersion.LittleBigPlanet1) if (token.GameVersion != GameVersion.LittleBigPlanet1)
queryBuilder.AddFilter(new ExcludeLBP1OnlyFilter(token.UserId, token.GameVersion)); queryBuilder.AddFilter(new ExcludeLBP1OnlyFilter(token.UserId, token.GameVersion));
if (!queryBuilder.GetFilters(typeof(CrossControlFilter)).Any())
queryBuilder.AddFilter(new ExcludeCrossControlFilter());
queryBuilder.AddFilter(new SubLevelFilter(token.UserId)); queryBuilder.AddFilter(new SubLevelFilter(token.UserId));
queryBuilder.AddFilter(new HiddenSlotFilter()); queryBuilder.AddFilter(new HiddenSlotFilter());
queryBuilder.AddFilter(new SlotTypeFilter(SlotType.User)); queryBuilder.AddFilter(new SlotTypeFilter(SlotType.User));

View file

@ -271,6 +271,52 @@ public class ControllerExtensionTests
Assert.NotEmpty(queryBuilder.GetFilters(typeof(CrossControlFilter))); Assert.NotEmpty(queryBuilder.GetFilters(typeof(CrossControlFilter)));
} }
[Fact]
public void FilterFromRequest_ShouldAddExcludeCrossControlFilter_WhenCrossControlNotTrue()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString("?crosscontrol=false"),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeCrossControlFilter)));
}
[Fact]
public void FilterFromRequest_ShouldAddExcludeCrossControlFilter_WhenCrossControlMissing()
{
GameTokenEntity token = MockHelper.GetUnitTestToken();
token.GameVersion = GameVersion.LittleBigPlanet2;
SlotsController controller = new(null!)
{
ControllerContext =
{
HttpContext = new DefaultHttpContext
{
Request =
{
QueryString = new QueryString(),
},
},
},
};
SlotQueryBuilder queryBuilder = controller.FilterFromRequest(token);
Assert.NotEmpty(queryBuilder.GetFilters(typeof(ExcludeCrossControlFilter)));
}
[Fact] [Fact]
public void FilterFromRequest_ShouldAddAdventureFilter_WhenAdventureEqualsAllMust() public void FilterFromRequest_ShouldAddAdventureFilter_WhenAdventureEqualsAllMust()
{ {

View file

@ -77,7 +77,7 @@ public class SlotControllerTests
} }
[Fact] [Fact]
public async Task SlotsBy_ResultsAreOrderedByFirstUploadedTimestampDescending() public async Task SlotsBy_ResultsAreOrderedByFirstUploadedTimestampAscending()
{ {
List<SlotEntity> slots = new() List<SlotEntity> slots = new()
{ {
@ -119,9 +119,9 @@ public class SlotControllerTests
IActionResult result = await slotsController.SlotsBy("bytest"); IActionResult result = await slotsController.SlotsBy("bytest");
const int expectedElements = 3; const int expectedElements = 3;
const int expectedFirstSlotId = 1; const int expectedFirstSlotId = 2;
const int expectedSecondSlotId = 3; const int expectedSecondSlotId = 3;
const int expectedThirdSlotId = 2; const int expectedThirdSlotId = 1;
GenericSlotResponse slotResponse = result.CastTo<OkObjectResult, GenericSlotResponse>(); GenericSlotResponse slotResponse = result.CastTo<OkObjectResult, GenericSlotResponse>();
Assert.Equal(expectedElements, slotResponse.Slots.Count); Assert.Equal(expectedElements, slotResponse.Slots.Count);

View file

@ -208,6 +208,34 @@ public class FilterTests
Assert.True(adventureFunc(slot)); Assert.True(adventureFunc(slot));
} }
[Fact]
public void ExcludeCrossControlFilter_ShouldAccept_WhenNotCrossControl()
{
ExcludeCrossControlFilter crossControlFilter = new();
Func<SlotEntity, bool> crossControlFunc = crossControlFilter.GetPredicate().Compile();
SlotEntity slot = new()
{
CrossControllerRequired = false,
};
Assert.True(crossControlFunc(slot));
}
[Fact]
public void ExcludeCrossControlFilter_ShouldReject_WhenCrossControl()
{
ExcludeCrossControlFilter crossControlFilter = new();
Func<SlotEntity, bool> crossControlFunc = crossControlFilter.GetPredicate().Compile();
SlotEntity slot = new()
{
CrossControllerRequired = true,
};
Assert.False(crossControlFunc(slot));
}
[Fact] [Fact]
public void ExcludeLBP1OnlyFilter_ShouldReject_WhenLbp1Only_AndTokenNotLbp1_AndNotCreator() public void ExcludeLBP1OnlyFilter_ShouldReject_WhenLbp1Only_AndTokenNotLbp1_AndNotCreator()
{ {

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -8,6 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class AdventureFilter : ISlotFilter public class AdventureFilter : ISlotFilter
{ {
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => s.IsAdventurePlanet;
PredicateExtensions.True<SlotEntity>().And(s => s.IsAdventurePlanet);
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -15,6 +14,5 @@ public class CreatorFilter : ISlotFilter
this.creatorId = creatorId; this.creatorId = creatorId;
} }
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => s.CreatorId == this.creatorId;
PredicateExtensions.True<SlotEntity>().And(s => s.CreatorId == this.creatorId);
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -8,6 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class CrossControlFilter : ISlotFilter public class CrossControlFilter : ISlotFilter
{ {
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => s.CrossControllerRequired;
PredicateExtensions.True<SlotEntity>().And(s => s.CrossControllerRequired);
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -8,6 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class ExcludeAdventureFilter : ISlotFilter public class ExcludeAdventureFilter : ISlotFilter
{ {
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => !s.IsAdventurePlanet;
PredicateExtensions.True<SlotEntity>().And(s => !s.IsAdventurePlanet);
} }

View file

@ -0,0 +1,11 @@
using System;
using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter;
namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class ExcludeCrossControlFilter : ISlotFilter
{
public Expression<Func<SlotEntity, bool>> GetPredicate() => s => !s.CrossControllerRequired;
}

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
using LBPUnion.ProjectLighthouse.Types.Users; using LBPUnion.ProjectLighthouse.Types.Users;
@ -18,10 +17,6 @@ public class ExcludeLBP1OnlyFilter : ISlotFilter
this.targetGameVersion = targetGameVersion; this.targetGameVersion = targetGameVersion;
} }
public Expression<Func<SlotEntity, bool>> GetPredicate() public Expression<Func<SlotEntity, bool>> GetPredicate() =>
{ s => !s.Lbp1Only || s.CreatorId == this.userId || this.targetGameVersion == GameVersion.LittleBigPlanet1;
Expression<Func<SlotEntity, bool>> predicate = PredicateExtensions.True<SlotEntity>();
predicate = predicate.And(s => !s.Lbp1Only || s.CreatorId == this.userId || this.targetGameVersion == GameVersion.LittleBigPlanet1);
return predicate;
}
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -8,6 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class ExcludeMovePackFilter : ISlotFilter public class ExcludeMovePackFilter : ISlotFilter
{ {
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => !s.MoveRequired;
PredicateExtensions.True<SlotEntity>().And(s => !s.MoveRequired);
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
using LBPUnion.ProjectLighthouse.Types.Users; using LBPUnion.ProjectLighthouse.Types.Users;
@ -18,12 +17,9 @@ public class GameVersionFilter : ISlotFilter
this.matchExactly = matchExactly; this.matchExactly = matchExactly;
} }
public Expression<Func<SlotEntity, bool>> GetPredicate() public Expression<Func<SlotEntity, bool>> GetPredicate() =>
{ this.matchExactly ||
Expression<Func<SlotEntity, bool>> predicate = PredicateExtensions.True<SlotEntity>(); this.targetVersion is GameVersion.LittleBigPlanetVita or GameVersion.LittleBigPlanetPSP or GameVersion.Unknown
predicate = this.matchExactly || this.targetVersion is GameVersion.LittleBigPlanetVita or GameVersion.LittleBigPlanetPSP or GameVersion.Unknown ? s => s.GameVersion == this.targetVersion
? predicate.And(s => s.GameVersion == this.targetVersion) : s => s.GameVersion <= this.targetVersion;
: predicate.And(s => s.GameVersion <= this.targetVersion);
return predicate;
}
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -8,6 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class HiddenSlotFilter : ISlotFilter public class HiddenSlotFilter : ISlotFilter
{ {
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => !s.Hidden;
PredicateExtensions.True<SlotEntity>().And(s => !s.Hidden);
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -8,6 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class MovePackFilter : ISlotFilter public class MovePackFilter : ISlotFilter
{ {
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => s.MoveRequired;
PredicateExtensions.True<SlotEntity>().And(s => s.MoveRequired);
} }

View file

@ -1,7 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -16,8 +15,5 @@ public class ResultTypeFilter : ISlotFilter
this.results = results; this.results = results;
} }
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => this.results.Contains("slot") ? s => true : s => false;
this.results.Contains("slot")
? PredicateExtensions.True<SlotEntity>()
: PredicateExtensions.False<SlotEntity>();
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
using LBPUnion.ProjectLighthouse.Types.Levels; using LBPUnion.ProjectLighthouse.Types.Levels;
@ -16,6 +15,5 @@ public class SlotTypeFilter : ISlotFilter
this.slotType = slotType; this.slotType = slotType;
} }
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => s.Type == this.slotType;
PredicateExtensions.True<SlotEntity>().And(s => s.Type == this.slotType);
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -15,6 +14,5 @@ public class SubLevelFilter : ISlotFilter
this.userId = userId; this.userId = userId;
} }
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => !s.SubLevel || s.CreatorId == this.userId;
PredicateExtensions.True<SlotEntity>().And(s => !s.SubLevel || s.CreatorId == this.userId);
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Linq.Expressions; using System.Linq.Expressions;
using LBPUnion.ProjectLighthouse.Extensions;
using LBPUnion.ProjectLighthouse.Types.Entities.Level; using LBPUnion.ProjectLighthouse.Types.Entities.Level;
using LBPUnion.ProjectLighthouse.Types.Filter; using LBPUnion.ProjectLighthouse.Types.Filter;
@ -8,6 +7,5 @@ namespace LBPUnion.ProjectLighthouse.Filter.Filters;
public class TeamPickFilter : ISlotFilter public class TeamPickFilter : ISlotFilter
{ {
public Expression<Func<SlotEntity, bool>> GetPredicate() => public Expression<Func<SlotEntity, bool>> GetPredicate() => s => s.TeamPick;
PredicateExtensions.True<SlotEntity>().And(s => s.TeamPick);
} }

View file

@ -10,7 +10,6 @@ namespace LBPUnion.ProjectLighthouse.Helpers;
public static class LastContactHelper public static class LastContactHelper
{ {
public static async Task SetLastContact(DatabaseContext database, UserEntity user, GameVersion gameVersion, Platform platform) public static async Task SetLastContact(DatabaseContext database, UserEntity user, GameVersion gameVersion, Platform platform)
{ {
LastContactEntity? lastContact = await database.LastContacts.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync(); LastContactEntity? lastContact = await database.LastContacts.Where(l => l.UserId == user.UserId).FirstOrDefaultAsync();