diff --git a/Refresh.Database/GameDatabaseContext.Pins.cs b/Refresh.Database/GameDatabaseContext.Pins.cs index 193eff71..822bd078 100644 --- a/Refresh.Database/GameDatabaseContext.Pins.cs +++ b/Refresh.Database/GameDatabaseContext.Pins.cs @@ -7,11 +7,10 @@ namespace Refresh.Database; public partial class GameDatabaseContext // Pins { - public void UpdateUserPinProgress(Dictionary pinProgressUpdates, GameUser user, TokenGame game) + public void UpdateUserPinProgress(Dictionary pinProgressUpdates, GameUser user, bool isBeta, TokenPlatform platform) { DateTimeOffset now = this._time.Now; - bool isBeta = game == TokenGame.BetaBuild; - IEnumerable existingProgresses = this.GetPinProgressesByUser(user, isBeta); + IEnumerable existingProgresses = this.GetPinProgressesByUser(user, isBeta, platform); List descendingProgressPins = [ (long)ServerPins.TopXOfAnyStoryLevelWithOver50Scores, @@ -34,6 +33,7 @@ public void UpdateUserPinProgress(Dictionary pinProgressUpdates, Game FirstPublished = now, LastUpdated = now, IsBeta = isBeta, + Platform = platform, }; this.PinProgressRelations.Add(newRelation); continue; @@ -53,10 +53,12 @@ public void UpdateUserPinProgress(Dictionary pinProgressUpdates, Game this.SaveChanges(); } - public void UpdateUserProfilePins(List pinUpdates, GameUser user, TokenGame game) + public void UpdateUserProfilePins(List pinUpdates, GameUser user, TokenGame game, TokenPlatform platform) { - IEnumerable existingProgressIds = this.GetPinProgressesByUser(user, game == TokenGame.BetaBuild).Select(p => p.PinId); - IEnumerable existingProfilePins = this.GetProfilePinsByUser(user, game); + IEnumerable existingProgressIds = this + .GetPinProgressesByUser(user, game == TokenGame.BetaBuild, platform) + .Select(p => p.PinId); + IEnumerable existingProfilePins = this.GetProfilePinsByUser(user, game, platform); DateTimeOffset now = this._time.Now; for (int i = 0; i < pinUpdates.Count; i++) @@ -80,6 +82,7 @@ public void UpdateUserProfilePins(List pinUpdates, GameUser user, TokenGam PublisherId = user.UserId, Index = i, Game = game, + Platform = platform, Timestamp = now, }); } @@ -93,10 +96,10 @@ public void UpdateUserProfilePins(List pinUpdates, GameUser user, TokenGam this.SaveChanges(); } - public PinProgressRelation UpdateUserPinProgressToLowest(long pinId, int newProgressValue, GameUser user, bool isBeta) + public PinProgressRelation UpdateUserPinProgressToLowest(long pinId, int newProgressValue, GameUser user, bool isBeta, TokenPlatform platform) { // Get pin progress if it exists already - PinProgressRelation? progressToUpdate = this.GetUserPinProgress(pinId, user, isBeta); + PinProgressRelation? progressToUpdate = this.GetUserPinProgress(pinId, user, isBeta, platform); DateTimeOffset now = this._time.Now; if (progressToUpdate == null) @@ -126,31 +129,15 @@ public PinProgressRelation UpdateUserPinProgressToLowest(long pinId, int newProg return progressToUpdate!; } - public void IncrementUserPinProgress(long pinId, int progressToAdd, GameUser user) - { - this.IncrementUserPinProgressInternal(pinId, progressToAdd, user, true); - this.IncrementUserPinProgressInternal(pinId, progressToAdd, user, false); - - this.SaveChanges(); - } - - public PinProgressRelation IncrementUserPinProgress(long pinId, int progressToAdd, GameUser user, bool isBeta) - { - PinProgressRelation relation = this.IncrementUserPinProgressInternal(pinId, progressToAdd, user, isBeta); - this.SaveChanges(); - - return relation; - } - - private PinProgressRelation IncrementUserPinProgressInternal(long pinId, int progressToAdd, GameUser user, bool isBeta) + public PinProgressRelation IncrementUserPinProgress(long pinId, int progressToAdd, GameUser user, bool isBeta, TokenPlatform platform) { // Get pin progress if it exists already - PinProgressRelation? progressToUpdate = this.GetUserPinProgress(pinId, user, isBeta); + PinProgressRelation? progressToUpdate = this.GetUserPinProgress(pinId, user, isBeta, platform); DateTimeOffset now = this._time.Now; if (progressToUpdate == null) { - PinProgressRelation newRelation = new() + progressToUpdate = new() { PinId = pinId, Progress = progressToAdd, @@ -159,10 +146,9 @@ private PinProgressRelation IncrementUserPinProgressInternal(long pinId, int pro FirstPublished = now, LastUpdated = now, IsBeta = isBeta, + Platform = platform, }; - - this.PinProgressRelations.Add(newRelation); - return newRelation; + this.PinProgressRelations.Add(progressToUpdate); } else { @@ -170,25 +156,39 @@ private PinProgressRelation IncrementUserPinProgressInternal(long pinId, int pro progressToUpdate.LastUpdated = now; } + this.SaveChanges(); return progressToUpdate; } - private IEnumerable GetPinProgressesByUser(GameUser user, bool isBeta) + private IEnumerable GetPinProgressesByUser(GameUser user, bool isBeta, TokenPlatform platform) => this.PinProgressRelations - .Where(p => p.PublisherId == user.UserId && p.IsBeta == isBeta) + .Where(p => p.PublisherId == user.UserId && (p.IsBeta == isBeta && p.Platform == platform || p.Platform == TokenPlatform.Website)) .OrderByDescending(p => p.LastUpdated); - public DatabaseList GetPinProgressesByUser(GameUser user, TokenGame game, int skip, int count) - => new(this.GetPinProgressesByUser(user, game == TokenGame.BetaBuild), skip, count); + public DatabaseList GetPinProgressesByUser(GameUser user, bool isBeta, TokenPlatform platform, int skip, int count) + => new(this.GetPinProgressesByUser(user, isBeta, platform), skip, count); - public PinProgressRelation? GetUserPinProgress(long pinId, GameUser user, bool isBeta) - => this.PinProgressRelations.FirstOrDefault(p => p.PinId == pinId && p.PublisherId == user.UserId && p.IsBeta == isBeta); + public PinProgressRelation? GetUserPinProgress(long pinId, GameUser user, bool isBeta, TokenPlatform platform) + => this.PinProgressRelations.FirstOrDefault(p => p.PinId == pinId && p.PublisherId == user.UserId + && (p.IsBeta == isBeta && p.Platform == platform || p.Platform == TokenPlatform.Website)); - private IEnumerable GetProfilePinsByUser(GameUser user, TokenGame game) + private IEnumerable GetProfilePinsByUser(GameUser user, TokenGame game, TokenPlatform platform) => this.ProfilePinRelations - .Where(p => p.PublisherId == user.UserId && p.Game == game) + .Where(p => p.PublisherId == user.UserId && p.Game == game && p.Platform == platform) .OrderBy(p => p.Index); - public DatabaseList GetProfilePinsByUser(GameUser user, TokenGame game, int skip, int count) - => new(this.GetProfilePinsByUser(user, game), skip, count); + public DatabaseList GetProfilePinsByUser(GameUser user, TokenGame game, TokenPlatform platform, int skip, int count) + => new(this.GetProfilePinsByUser(user, game, platform), skip, count); + + public void AddPinProgress(PinProgressRelation relation, bool save) + { + this.PinProgressRelations.Add(relation); + if (save) this.SaveChanges(); + } + + public void RemovePinProgresses(IEnumerable relations, bool save) + { + this.PinProgressRelations.RemoveRange(relations); + if (save) this.SaveChanges(); + } } \ No newline at end of file diff --git a/Refresh.Database/Migrations/20251029184346_SeperatePinProgressByPlatform.cs b/Refresh.Database/Migrations/20251029184346_SeperatePinProgressByPlatform.cs new file mode 100644 index 00000000..4598b2d6 --- /dev/null +++ b/Refresh.Database/Migrations/20251029184346_SeperatePinProgressByPlatform.cs @@ -0,0 +1,83 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Refresh.Database.Models.Authentication; +using Refresh.Database.Models.Pins; + +#nullable disable + +namespace Refresh.Database.Migrations +{ + /// + [DbContext(typeof(GameDatabaseContext))] + [Migration("20251029184346_SeperatePinProgressByPlatform")] + public partial class SeperatePinProgressByPlatform : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + // RPCS3 is the safest default value here, as game achievements on RPCS3 are considered the least valuable. + // Also, the game will sync progress and profile pins after login anyway, so practically no information is lost here. + migrationBuilder.AddColumn( + name: "Platform", + table: "ProfilePinRelations", + type: "integer", + nullable: false, + defaultValue: TokenPlatform.RPCS3); + + migrationBuilder.AddColumn( + name: "Platform", + table: "PinProgressRelations", + type: "integer", + nullable: false, + defaultValue: TokenPlatform.RPCS3); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProfilePinRelations", + table: "ProfilePinRelations"); + + migrationBuilder.DropPrimaryKey( + name: "PK_PinProgressRelations", + table: "PinProgressRelations"); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProfilePinRelations", + table: "ProfilePinRelations", + columns: ["Index", "PublisherId", "Game", "Platform"]); + + migrationBuilder.AddPrimaryKey( + name: "PK_PinProgressRelations", + table: "PinProgressRelations", + columns: ["PinId", "PublisherId", "IsBeta", "Platform"]); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Platform", + table: "ProfilePinRelations"); + + migrationBuilder.DropColumn( + name: "Platform", + table: "PinProgressRelations"); + + migrationBuilder.DropPrimaryKey( + name: "PK_ProfilePinRelations", + table: "ProfilePinRelations"); + + migrationBuilder.DropPrimaryKey( + name: "PK_PinProgressRelations", + table: "PinProgressRelations"); + + migrationBuilder.AddPrimaryKey( + name: "PK_ProfilePinRelations", + table: "ProfilePinRelations", + columns: ["Index", "PublisherId", "Game"]); + + migrationBuilder.AddPrimaryKey( + name: "PK_PinProgressRelations", + table: "PinProgressRelations", + columns: ["PinId", "PublisherId", "IsBeta"]); + } + } +} diff --git a/Refresh.Database/Migrations/GameDatabaseContextModelSnapshot.cs b/Refresh.Database/Migrations/GameDatabaseContextModelSnapshot.cs index 88a67cdb..4cd9366b 100644 --- a/Refresh.Database/Migrations/GameDatabaseContextModelSnapshot.cs +++ b/Refresh.Database/Migrations/GameDatabaseContextModelSnapshot.cs @@ -943,6 +943,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("IsBeta") .HasColumnType("boolean"); + b.Property("Platform") + .HasColumnType("integer"); + b.Property("FirstPublished") .HasColumnType("timestamp with time zone"); @@ -952,7 +955,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Progress") .HasColumnType("integer"); - b.HasKey("PinId", "PublisherId", "IsBeta"); + b.HasKey("PinId", "PublisherId", "IsBeta", "Platform"); b.HasIndex("PublisherId"); @@ -1024,13 +1027,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Game") .HasColumnType("integer"); + b.Property("Platform") + .HasColumnType("integer"); + b.Property("PinId") .HasColumnType("bigint"); b.Property("Timestamp") .HasColumnType("timestamp with time zone"); - b.HasKey("Index", "PublisherId", "Game"); + b.HasKey("Index", "PublisherId", "Game", "Platform"); b.HasIndex("PublisherId"); diff --git a/Refresh.Database/Models/Relations/PinProgressRelation.cs b/Refresh.Database/Models/Relations/PinProgressRelation.cs index 20d59ec0..a7074a72 100644 --- a/Refresh.Database/Models/Relations/PinProgressRelation.cs +++ b/Refresh.Database/Models/Relations/PinProgressRelation.cs @@ -1,11 +1,12 @@ using MongoDB.Bson; +using Refresh.Database.Models.Authentication; using Refresh.Database.Models.Users; namespace Refresh.Database.Models.Relations; #nullable disable -[PrimaryKey(nameof(PinId), nameof(PublisherId), nameof(IsBeta))] +[PrimaryKey(nameof(PinId), nameof(PublisherId), nameof(IsBeta), nameof(Platform))] public partial class PinProgressRelation { /// @@ -26,4 +27,13 @@ public partial class PinProgressRelation /// for these game groups seperately. /// public bool IsBeta { get; set; } + + /// + /// Seperates pin progresses per platform, to not let progress transfer inbetween PS3, RPCS3 and especially Vita, + /// as that's commonly unwanted behaviour. Maybe figure out how to make this be opt-out in the future? + /// + /// Website = this pin is "universal" across platforms and games (e.g. LBP.me pin). + /// In that case ignore both IsBeta and Platform, and show this progress on all games. + /// + public TokenPlatform Platform { get; set; } } \ No newline at end of file diff --git a/Refresh.Database/Models/Relations/ProfilePinRelation.cs b/Refresh.Database/Models/Relations/ProfilePinRelation.cs index de54015b..9608b190 100644 --- a/Refresh.Database/Models/Relations/ProfilePinRelation.cs +++ b/Refresh.Database/Models/Relations/ProfilePinRelation.cs @@ -6,7 +6,7 @@ namespace Refresh.Database.Models.Relations; #nullable disable -[PrimaryKey(nameof(Index), nameof(PublisherId), nameof(Game))] +[PrimaryKey(nameof(Index), nameof(PublisherId), nameof(Game), nameof(Platform))] public partial class ProfilePinRelation { public long PinId { get; set; } @@ -26,5 +26,10 @@ public partial class ProfilePinRelation /// public TokenGame Game { get; set; } + /// + /// Since pin progresses are split per platforms now, we also have to split profile pins aswell + /// + public TokenPlatform Platform { get; set; } + public DateTimeOffset Timestamp { get; set; } } \ No newline at end of file diff --git a/Refresh.Interfaces.APIv3/Endpoints/AuthenticationApiEndpoints.cs b/Refresh.Interfaces.APIv3/Endpoints/AuthenticationApiEndpoints.cs index 85f67e25..e90122c0 100644 --- a/Refresh.Interfaces.APIv3/Endpoints/AuthenticationApiEndpoints.cs +++ b/Refresh.Interfaces.APIv3/Endpoints/AuthenticationApiEndpoints.cs @@ -109,7 +109,7 @@ public ApiResponse Authenticate(RequestContext conte context.Logger.LogInfo(BunkumCategory.Authentication, $"{user} successfully logged in through the API"); // Update pin progress for signing into the API - database.IncrementUserPinProgress((long)ServerPins.SignIntoWebsite, 1, user); + database.IncrementUserPinProgress((long)ServerPins.SignIntoWebsite, 1, user, false, TokenPlatform.Website); return new ApiAuthenticationResponse { diff --git a/Refresh.Interfaces.APIv3/Endpoints/LevelApiEndpoints.cs b/Refresh.Interfaces.APIv3/Endpoints/LevelApiEndpoints.cs index fa82ded7..ec56a68a 100644 --- a/Refresh.Interfaces.APIv3/Endpoints/LevelApiEndpoints.cs +++ b/Refresh.Interfaces.APIv3/Endpoints/LevelApiEndpoints.cs @@ -9,6 +9,7 @@ using Refresh.Core.Services; using Refresh.Core.Types.Data; using Refresh.Database; +using Refresh.Database.Models.Authentication; using Refresh.Database.Models.Levels; using Refresh.Database.Models.Pins; using Refresh.Database.Models.Users; @@ -183,7 +184,7 @@ public ApiOkResponse QueueLevel(RequestContext context, GameDatabaseContext data database.QueueLevel(level, user); // Update pin progress for queueing a level through the API - database.IncrementUserPinProgress((long)ServerPins.QueueLevelOnWebsite, 1, user); + database.IncrementUserPinProgress((long)ServerPins.QueueLevelOnWebsite, 1, user, false, TokenPlatform.Website); return new ApiOkResponse(); } diff --git a/Refresh.Interfaces.Game/Endpoints/DataTypes/Response/GameUserResponse.cs b/Refresh.Interfaces.Game/Endpoints/DataTypes/Response/GameUserResponse.cs index 66542903..ec8dd2d2 100644 --- a/Refresh.Interfaces.Game/Endpoints/DataTypes/Response/GameUserResponse.cs +++ b/Refresh.Interfaces.Game/Endpoints/DataTypes/Response/GameUserResponse.cs @@ -121,7 +121,7 @@ public class GameUserResponse : IDataConvertableFrom } if (game is not TokenGame.LittleBigPlanet1 or TokenGame.LittleBigPlanetPSP) { - response.ProfilePins = dataContext.Database.GetProfilePinsByUser(old, dataContext.Game, 0, 3) + response.ProfilePins = dataContext.Database.GetProfilePinsByUser(old, dataContext.Game, dataContext.Platform, 0, 3) .Items.Select(p => p.PinId).ToList(); } diff --git a/Refresh.Interfaces.Game/Endpoints/Levels/LeaderboardEndpoints.cs b/Refresh.Interfaces.Game/Endpoints/Levels/LeaderboardEndpoints.cs index ad6c8cce..1cc43ade 100644 --- a/Refresh.Interfaces.Game/Endpoints/Levels/LeaderboardEndpoints.cs +++ b/Refresh.Interfaces.Game/Endpoints/Levels/LeaderboardEndpoints.cs @@ -211,12 +211,12 @@ private void AwardScoreboardPins(DatabaseList scores, DataContext if (isStoryLevel) { dataContext.Database.UpdateUserPinProgressToLowest((long)ServerPins.TopXOfAnyStoryLevelWithOver50Scores, - rankingInPercent, user, isGameBetaBuild); + rankingInPercent, user, isGameBetaBuild, dataContext.Platform); } else { dataContext.Database.UpdateUserPinProgressToLowest((long)ServerPins.TopXOfAnyCommunityLevelWithOver50Scores, - rankingInPercent, user, isGameBetaBuild); + rankingInPercent, user, isGameBetaBuild, dataContext.Platform); } // Update on how many story/user levels the user's ranking is in the top 25% (top 1/4th) of the leaderboard or below @@ -225,12 +225,12 @@ private void AwardScoreboardPins(DatabaseList scores, DataContext if (isStoryLevel) { dataContext.Database.IncrementUserPinProgress((long)ServerPins.TopFourthOfXStoryLevelsWithOver50Scores, - 1, user, isGameBetaBuild); + 1, user, isGameBetaBuild, dataContext.Platform); } else { dataContext.Database.IncrementUserPinProgress((long)ServerPins.TopFourthOfXCommunityLevelsWithOver50Scores, - 1, user, isGameBetaBuild); + 1, user, isGameBetaBuild, dataContext.Platform); } } diff --git a/Refresh.Interfaces.Game/Endpoints/UserEndpoints.cs b/Refresh.Interfaces.Game/Endpoints/UserEndpoints.cs index a679dd19..1e9f98c3 100644 --- a/Refresh.Interfaces.Game/Endpoints/UserEndpoints.cs +++ b/Refresh.Interfaces.Game/Endpoints/UserEndpoints.cs @@ -10,6 +10,7 @@ using Refresh.Core.Types.Data; using Refresh.Database; using Refresh.Database.Models.Authentication; +using Refresh.Database.Models.Pins; using Refresh.Database.Models.Users; using Refresh.Interfaces.Game.Endpoints.DataTypes.Response; using Refresh.Interfaces.Game.Types.Lists; @@ -176,7 +177,7 @@ public SerializedFriendsList GetFriends(RequestContext context, GameDatabaseCont if (pinProgresses.Count > 0) { - dataContext.Database.UpdateUserPinProgress(pinProgresses, user, dataContext.Game); + dataContext.Database.UpdateUserPinProgress(pinProgresses, user, dataContext.Game == TokenGame.BetaBuild, dataContext.Platform); } // Users can only have 3 pins set on their profile @@ -185,7 +186,7 @@ public SerializedFriendsList GetFriends(RequestContext context, GameDatabaseCont if (body.ProfilePins.Count > 0) { - dataContext.Database.UpdateUserProfilePins(body.ProfilePins, user, dataContext.Game); + dataContext.Database.UpdateUserProfilePins(body.ProfilePins, user, dataContext.Game, dataContext.Platform); } // Return newly updated pins (LBP2 and 3 update their pin progresses if there are higher progress values @@ -198,6 +199,6 @@ public SerializedFriendsList GetFriends(RequestContext context, GameDatabaseCont public SerializedPins GetPins(RequestContext context, DataContext dataContext, GameUser user) => SerializedPins.FromOld ( - dataContext.Database.GetPinProgressesByUser(user, dataContext.Game, 0, 999).Items + dataContext.Database.GetPinProgressesByUser(user, dataContext.Game == TokenGame.BetaBuild, dataContext.Platform, 0, 999).Items ); } \ No newline at end of file diff --git a/Refresh.Interfaces.Workers/Migrations/CorrectWebsitePinProgressPlatform.cs b/Refresh.Interfaces.Workers/Migrations/CorrectWebsitePinProgressPlatform.cs new file mode 100644 index 00000000..1b5e41f6 --- /dev/null +++ b/Refresh.Interfaces.Workers/Migrations/CorrectWebsitePinProgressPlatform.cs @@ -0,0 +1,58 @@ +using MongoDB.Bson; +using Refresh.Common.Time; +using Refresh.Database.Models.Authentication; +using Refresh.Database.Models.Pins; +using Refresh.Database.Models.Relations; +using Refresh.Workers; + +namespace Refresh.Interfaces.Workers.Migrations; + +public class CorrectWebsitePinProgressPlatform : MigrationJob +{ + private List websitePinIds = + [ + (long)ServerPins.HeartPlayerOnWebsite, + (long)ServerPins.QueueLevelOnWebsite, + (long)ServerPins.SignIntoWebsite, + ]; + + protected override IQueryable SortAndFilter(IQueryable query) + { + return query + .Where(p => this.websitePinIds.Contains(p.PinId)) + .OrderBy(p => p.PinId); + } + + protected override void Migrate(WorkContext context, PinProgressRelation[] batch) + { + foreach (long pinId in this.websitePinIds) + { + IEnumerable> pinsByUser = batch + .Where(r => r.PinId == pinId) + .GroupBy(r => r.PublisherId); + + foreach (IEnumerable group in pinsByUser) + { + if (!group.Any()) continue; + + // Find and migrate one progress + PinProgressRelation relationToMigrate = group.MaxBy(r => r.Progress)!; + context.Database.AddPinProgress(new() + { + PinId = relationToMigrate.PinId, + Progress = relationToMigrate.Progress, + PublisherId = relationToMigrate.PublisherId, + FirstPublished = relationToMigrate.FirstPublished, + LastUpdated = relationToMigrate.LastUpdated, + IsBeta = false, // doesn't matter here + Platform = TokenPlatform.Website, + }, false); + + // Remove all others + context.Database.RemovePinProgresses(group, false); + } + } + + context.Database.SaveChanges(); + } +} \ No newline at end of file diff --git a/Refresh.Interfaces.Workers/RefreshWorkerManager.cs b/Refresh.Interfaces.Workers/RefreshWorkerManager.cs index cf181524..7d0d4cb2 100644 --- a/Refresh.Interfaces.Workers/RefreshWorkerManager.cs +++ b/Refresh.Interfaces.Workers/RefreshWorkerManager.cs @@ -25,7 +25,8 @@ public static WorkerManager Create(Logger logger, IDataStore dataStore, GameData manager.AddJob(); manager.AddJob(); manager.AddJob(); - + manager.AddJob(); + return manager; } } \ No newline at end of file diff --git a/RefreshTests.GameServer/Tests/Pins/PinProgressPlatformTests.cs b/RefreshTests.GameServer/Tests/Pins/PinProgressPlatformTests.cs new file mode 100644 index 00000000..e2bb3420 --- /dev/null +++ b/RefreshTests.GameServer/Tests/Pins/PinProgressPlatformTests.cs @@ -0,0 +1,97 @@ +using Refresh.Database; +using Refresh.Database.Models.Authentication; +using Refresh.Database.Models.Pins; +using Refresh.Database.Models.Relations; +using Refresh.Database.Models.Users; + +namespace RefreshTests.GameServer.Tests.Pins; + +public class PinProgressPlatformTests : GameServerTest +{ + [Test] + public void PlatformedPinsSeperatedByPlatformTest() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + + // ROUND 1 - Create a pin which has a non-website platform (not universal) + context.Database.IncrementUserPinProgress((long)ServerPins.TopXOfAnyStoryLevelWithOver50Scores, 420, user, false, TokenPlatform.PS3); + + // Pin should appear when searching for this specific game type and platform + DatabaseList relations = context.Database.GetPinProgressesByUser(user, false, TokenPlatform.PS3, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.TopXOfAnyStoryLevelWithOver50Scores)); + + // Pin should not appear if searched game type is wrong + relations = context.Database.GetPinProgressesByUser(user, true, TokenPlatform.PS3, 0, 300); + Assert.That(relations.Items.Count(), Is.Zero); + + // Pin should not appear if searched platform is wrong + relations = context.Database.GetPinProgressesByUser(user, false, TokenPlatform.Vita, 0, 300); + Assert.That(relations.Items.Count(), Is.Zero); + + // ROUND 2 - Update the pin to lowest + context.Database.UpdateUserPinProgressToLowest((long)ServerPins.TopXOfAnyStoryLevelWithOver50Scores, 210, user, false, TokenPlatform.PS3); + + // Pin should appear when searching for this specific game type and platform + relations = context.Database.GetPinProgressesByUser(user, false, TokenPlatform.PS3, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.TopXOfAnyStoryLevelWithOver50Scores)); + + // Pin should not appear if searched game type is wrong + relations = context.Database.GetPinProgressesByUser(user, true, TokenPlatform.PS3, 0, 300); + Assert.That(relations.Items.Count(), Is.Zero); + + // Pin should not appear if searched platform is wrong + relations = context.Database.GetPinProgressesByUser(user, false, TokenPlatform.Vita, 0, 300); + Assert.That(relations.Items.Count(), Is.Zero); + } + + [Test] + public void UniversalPinsAppearOnAllPlatformsTest() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + + // ROUND 1 - Create a pin which is "universal" (platform is Website) + context.Database.IncrementUserPinProgress((long)ServerPins.SignIntoWebsite, 420, user, false, TokenPlatform.Website); + + // Pin should appear when searching for any specific game type and platform + DatabaseList relations = context.Database.GetPinProgressesByUser(user, false, TokenPlatform.PS3, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.SignIntoWebsite)); + + // Pin should appear if searched game type is wrong + relations = context.Database.GetPinProgressesByUser(user, true, TokenPlatform.PS3, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.SignIntoWebsite)); + + // Pin should appear if searched platform is wrong + relations = context.Database.GetPinProgressesByUser(user, false, TokenPlatform.Vita, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.SignIntoWebsite)); + + // Pin should appear if both are wrong + relations = context.Database.GetPinProgressesByUser(user, true, TokenPlatform.RPCS3, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.SignIntoWebsite)); + + // ROUND 2 - Update the pin to lowest (through the game) + context.Database.UpdateUserPinProgressToLowest((long)ServerPins.SignIntoWebsite, 210, user, false, TokenPlatform.PS3); + + // Pin should appear if searched game type is wrong + relations = context.Database.GetPinProgressesByUser(user, true, TokenPlatform.PS3, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.SignIntoWebsite)); + + // Pin should appear if searched platform is wrong + relations = context.Database.GetPinProgressesByUser(user, false, TokenPlatform.Vita, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.SignIntoWebsite)); + + // Pin should appear if both are wrong + relations = context.Database.GetPinProgressesByUser(user, true, TokenPlatform.RPCS3, 0, 300); + Assert.That(relations.Items.Count(), Is.EqualTo(1)); + Assert.That(relations.Items.First().PinId, Is.EqualTo((long)ServerPins.SignIntoWebsite)); + } +} \ No newline at end of file diff --git a/RefreshTests.GameServer/Tests/Pins/ScorePinTests.cs b/RefreshTests.GameServer/Tests/Pins/ScorePinTests.cs index cc6ffd3c..9903c889 100644 --- a/RefreshTests.GameServer/Tests/Pins/ScorePinTests.cs +++ b/RefreshTests.GameServer/Tests/Pins/ScorePinTests.cs @@ -44,7 +44,7 @@ public void AchieveTopXOfLeaderboardsPin(byte scoreType, bool isStoryLevel) Assert.That(message.StatusCode, Is.EqualTo(OK)); // Ensure we now have the pin - PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false); + PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false, TokenPlatform.PS3); Assert.That(relation, Is.Not.Null); int progress = relation!.Progress; @@ -63,7 +63,7 @@ public void AchieveTopXOfLeaderboardsPin(byte scoreType, bool isStoryLevel) Assert.That(message.StatusCode, Is.EqualTo(OK)); // Ensure the pin now has a better progress value (is smaller) - relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false); + relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false, TokenPlatform.PS3); Assert.That(relation, Is.Not.Null); Assert.That(relation!.Progress, Is.LessThan(progress)); @@ -106,7 +106,7 @@ public void AchieveTopFourthOfXLeaderboardsPin(byte scoreType, bool isStoryLevel Assert.That(message.StatusCode, Is.EqualTo(OK)); // Ensure we now have the pin - PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false); + PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false, TokenPlatform.PS3); Assert.That(relation, Is.Not.Null); Assert.That(relation!.Progress, Is.EqualTo(1)); @@ -133,7 +133,7 @@ public void AchieveTopFourthOfXLeaderboardsPin(byte scoreType, bool isStoryLevel context.Database.Refresh(); // Ensure the pin progress has been incremented - PinProgressRelation? relation2 = context.Database.GetUserPinProgress(pinIdToCheck, user, false); + PinProgressRelation? relation2 = context.Database.GetUserPinProgress(pinIdToCheck, user, false, TokenPlatform.PS3); Assert.That(relation2, Is.Not.Null); Assert.That(relation2!.Progress, Is.EqualTo(2)); } @@ -172,7 +172,7 @@ public void RejectTopXOfLeaderboardsPinIfTooFewScores(byte scoreType, bool isSto Assert.That(message.StatusCode, Is.EqualTo(OK)); // Ensure we don't have the pin - PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false); + PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false, TokenPlatform.PS3); Assert.That(relation, Is.Null); } @@ -210,7 +210,7 @@ public void RejectTopFourthOfXLeaderboardsPinIfSkillIssue(byte scoreType, bool i Assert.That(message.StatusCode, Is.EqualTo(OK)); // Ensure we don't have the pin - PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false); + PinProgressRelation? relation = context.Database.GetUserPinProgress(pinIdToCheck, user, false, TokenPlatform.PS3); Assert.That(relation, Is.Null); } } \ No newline at end of file