diff --git a/Assets/Talo Game Services/Talo/Runtime/APIs/LeaderboardsAPI.cs b/Assets/Talo Game Services/Talo/Runtime/APIs/LeaderboardsAPI.cs index 0dfbca1..bafd90d 100644 --- a/Assets/Talo Game Services/Talo/Runtime/APIs/LeaderboardsAPI.cs +++ b/Assets/Talo Game Services/Talo/Runtime/APIs/LeaderboardsAPI.cs @@ -110,7 +110,7 @@ public async Task GetEntriesForCurrentPlayer(string var json = await Call(uri, "POST", Prop.SanitiseJson(content)); var res = JsonUtility.FromJson(json); - _entriesManager.UpsertEntry(internalName, res.entry); + _entriesManager.UpsertEntry(internalName, res.entry, true); return (res.entry, res.updated); } diff --git a/Assets/Talo Game Services/Talo/Runtime/Utils/LeaderboardEntriesManager.cs b/Assets/Talo Game Services/Talo/Runtime/Utils/LeaderboardEntriesManager.cs index 572c68e..a086cfa 100644 --- a/Assets/Talo Game Services/Talo/Runtime/Utils/LeaderboardEntriesManager.cs +++ b/Assets/Talo Game Services/Talo/Runtime/Utils/LeaderboardEntriesManager.cs @@ -16,7 +16,7 @@ public List GetEntries(string internalName) return _currentEntries[internalName]; } - public void UpsertEntry(string internalName, LeaderboardEntry entry) + public void UpsertEntry(string internalName, LeaderboardEntry entry, bool bumpPositions = false) { if (!_currentEntries.ContainsKey(internalName)) { @@ -31,9 +31,15 @@ public void UpsertEntry(string internalName, LeaderboardEntry entry) int insertPosition = FindInsertPosition(entries, entry); entries.Insert(insertPosition, entry); - for (int idx = 0; idx < entries.Count; idx++) + if (bumpPositions) { - entries[idx].position = idx; + foreach (var e in entries) + { + if (e.id != entry.id && e.position >= entry.position) + { + e.position += 1; + } + } } } diff --git a/Assets/Talo Game Services/Talo/Tests/LeaderboardsAPI/LeaderboardEntriesManagerTests.cs b/Assets/Talo Game Services/Talo/Tests/LeaderboardsAPI/LeaderboardEntriesManagerTests.cs index 67e7e6c..4fff1e0 100644 --- a/Assets/Talo Game Services/Talo/Tests/LeaderboardsAPI/LeaderboardEntriesManagerTests.cs +++ b/Assets/Talo Game Services/Talo/Tests/LeaderboardsAPI/LeaderboardEntriesManagerTests.cs @@ -15,21 +15,21 @@ public void SetUp() [Test] public void UpsertEntry_DescendingSort_InsertsInCorrectPosition() { - var entry1 = new LeaderboardEntry { id = 1, score = 100f, leaderboardSortMode = "desc" }; - var entry2 = new LeaderboardEntry { id = 2, score = 80f, leaderboardSortMode = "desc" }; - var entry3 = new LeaderboardEntry { id = 3, score = 90f, leaderboardSortMode = "desc" }; + var entry1 = new LeaderboardEntry { id = 1, score = 100f, position = 0, leaderboardSortMode = "desc" }; + var entry2 = new LeaderboardEntry { id = 2, score = 80f, position = 2, leaderboardSortMode = "desc" }; + var entry3 = new LeaderboardEntry { id = 3, score = 90f, position = 1, leaderboardSortMode = "desc" }; manager.UpsertEntry("test", entry1); manager.UpsertEntry("test", entry2); manager.UpsertEntry("test", entry3); var entries = manager.GetEntries("test"); - + Assert.AreEqual(3, entries.Count); Assert.AreEqual(100f, entries[0].score); Assert.AreEqual(90f, entries[1].score); Assert.AreEqual(80f, entries[2].score); - + Assert.AreEqual(0, entries[0].position); Assert.AreEqual(1, entries[1].position); Assert.AreEqual(2, entries[2].position); @@ -38,21 +38,21 @@ public void UpsertEntry_DescendingSort_InsertsInCorrectPosition() [Test] public void UpsertEntry_AscendingSort_InsertsInCorrectPosition() { - var entry1 = new LeaderboardEntry { id = 1, score = 100f, leaderboardSortMode = "asc" }; - var entry2 = new LeaderboardEntry { id = 2, score = 80f, leaderboardSortMode = "asc" }; - var entry3 = new LeaderboardEntry { id = 3, score = 90f, leaderboardSortMode = "asc" }; + var entry1 = new LeaderboardEntry { id = 1, score = 100f, position = 2, leaderboardSortMode = "asc" }; + var entry2 = new LeaderboardEntry { id = 2, score = 80f, position = 0, leaderboardSortMode = "asc" }; + var entry3 = new LeaderboardEntry { id = 3, score = 90f, position = 1, leaderboardSortMode = "asc" }; manager.UpsertEntry("test", entry1); manager.UpsertEntry("test", entry2); manager.UpsertEntry("test", entry3); var entries = manager.GetEntries("test"); - + Assert.AreEqual(3, entries.Count); Assert.AreEqual(80f, entries[0].score); Assert.AreEqual(90f, entries[1].score); Assert.AreEqual(100f, entries[2].score); - + Assert.AreEqual(0, entries[0].position); Assert.AreEqual(1, entries[1].position); Assert.AreEqual(2, entries[2].position); @@ -62,39 +62,40 @@ public void UpsertEntry_AscendingSort_InsertsInCorrectPosition() public void UpsertEntry_UpdateExistingEntry_MaintainsCorrectOrder() { // highest score - var entry1 = new LeaderboardEntry { id = 1, score = 100f, leaderboardSortMode = "desc" }; + var entry1 = new LeaderboardEntry { id = 1, score = 100f, position = 0, leaderboardSortMode = "desc" }; manager.UpsertEntry("test", entry1); - + // should go after entry1 - var entry2 = new LeaderboardEntry { id = 2, score = 80f, leaderboardSortMode = "desc" }; + var entry2 = new LeaderboardEntry { id = 2, score = 80f, position = 1, leaderboardSortMode = "desc" }; manager.UpsertEntry("test", entry2); - + // update entry1 to have the lowest score - should move to end - var updatedEntry1 = new LeaderboardEntry { id = 1, score = 70f, leaderboardSortMode = "desc" }; + var updatedEntry1 = new LeaderboardEntry { id = 1, score = 70f, position = 1, leaderboardSortMode = "desc" }; manager.UpsertEntry("test", updatedEntry1); - var entries = manager.GetEntries("test"); + var entries = manager.GetEntries("test"); Assert.AreEqual(2, entries.Count); Assert.AreEqual(2, entries[0].id); // entry2 should be first Assert.AreEqual(80f, entries[0].score); - Assert.AreEqual(1, entries[1].id); // updated entry1 should be second + Assert.AreEqual(1, entries[1].id); // updated entry1 should be second Assert.AreEqual(70f, entries[1].score); - - Assert.AreEqual(0, entries[0].position); + + // Positions preserved as-is when not bumping (intentional) + Assert.AreEqual(1, entries[0].position); Assert.AreEqual(1, entries[1].position); } [Test] public void UpsertEntry_EmptyList_InsertsFirstEntry() { - var entry = new LeaderboardEntry { id = 1, score = 100f, leaderboardSortMode = "desc" }; + var entry = new LeaderboardEntry { id = 1, score = 100f, position = 0, leaderboardSortMode = "desc" }; manager.UpsertEntry("test", entry); var entries = manager.GetEntries("test"); - + Assert.AreEqual(1, entries.Count); Assert.AreEqual(100f, entries[0].score); Assert.AreEqual(0, entries[0].position); @@ -103,17 +104,19 @@ public void UpsertEntry_EmptyList_InsertsFirstEntry() [Test] public void UpsertEntry_EqualScores_OrdersByCreatedAt() { - var earlierEntry = new LeaderboardEntry - { - id = 1, - score = 100f, + var earlierEntry = new LeaderboardEntry + { + id = 1, + score = 100f, + position = 0, leaderboardSortMode = "desc", createdAt = "2025-09-13T10:00:00Z" }; - var laterEntry = new LeaderboardEntry - { - id = 2, - score = 100f, + var laterEntry = new LeaderboardEntry + { + id = 2, + score = 100f, + position = 1, leaderboardSortMode = "desc", createdAt = "2025-09-13T11:00:00Z" }; @@ -122,12 +125,96 @@ public void UpsertEntry_EqualScores_OrdersByCreatedAt() manager.UpsertEntry("test", earlierEntry); var entries = manager.GetEntries("test"); - + Assert.AreEqual(2, entries.Count); Assert.AreEqual(1, entries[0].id); // earlier entry should be first Assert.AreEqual(2, entries[1].id); // later entry should be second Assert.AreEqual(0, entries[0].position); Assert.AreEqual(1, entries[1].position); } + + [Test] + public void UpsertEntry_BumpPositions_BumpsExistingEntries() + { + var entry1 = new LeaderboardEntry { id = 1, score = 100f, position = 0, leaderboardSortMode = "desc" }; + var entry2 = new LeaderboardEntry { id = 2, score = 80f, position = 1, leaderboardSortMode = "desc" }; + + manager.UpsertEntry("test", entry1); + manager.UpsertEntry("test", entry2); + + // Insert a new entry with position 0 - should bump the others + var entry3 = new LeaderboardEntry { id = 3, score = 110f, position = 0, leaderboardSortMode = "desc" }; + manager.UpsertEntry("test", entry3, bumpPositions: true); + + var entries = manager.GetEntries("test"); + + Assert.AreEqual(3, entries.Count); + Assert.AreEqual(3, entries[0].id); + Assert.AreEqual(0, entries[0].position); // new entry at position 0 + + Assert.AreEqual(1, entries[1].id); + Assert.AreEqual(1, entries[1].position); // bumped from 0 to 1 + + Assert.AreEqual(2, entries[2].id); + Assert.AreEqual(2, entries[2].position); // bumped from 1 to 2 + } + + [Test] + public void UpsertEntry_BumpPositions_OnlyBumpsAffectedEntries() + { + var entry1 = new LeaderboardEntry { id = 1, score = 100f, position = 0, leaderboardSortMode = "desc" }; + var entry2 = new LeaderboardEntry { id = 2, score = 80f, position = 1, leaderboardSortMode = "desc" }; + var entry3 = new LeaderboardEntry { id = 3, score = 60f, position = 2, leaderboardSortMode = "desc" }; + + manager.UpsertEntry("test", entry1); + manager.UpsertEntry("test", entry2); + manager.UpsertEntry("test", entry3); + + // Insert a new entry at position 1 - should only bump entries at position >= 1 + var entry4 = new LeaderboardEntry { id = 4, score = 90f, position = 1, leaderboardSortMode = "desc" }; + manager.UpsertEntry("test", entry4, bumpPositions: true); + + var entries = manager.GetEntries("test"); + + Assert.AreEqual(4, entries.Count); + + Assert.AreEqual(1, entries[0].id); + Assert.AreEqual(0, entries[0].position); // unchanged + + Assert.AreEqual(4, entries[1].id); + Assert.AreEqual(1, entries[1].position); // new entry at position 1 + + Assert.AreEqual(2, entries[2].id); + Assert.AreEqual(2, entries[2].position); // bumped from 1 to 2 + + Assert.AreEqual(3, entries[3].id); + Assert.AreEqual(3, entries[3].position); // bumped from 2 to 3 + } + + [Test] + public void UpsertEntry_NoBumpPositions_PreservesExistingPositions() + { + var entry1 = new LeaderboardEntry { id = 1, score = 100f, position = 0, leaderboardSortMode = "desc" }; + var entry2 = new LeaderboardEntry { id = 2, score = 80f, position = 1, leaderboardSortMode = "desc" }; + + manager.UpsertEntry("test", entry1); + manager.UpsertEntry("test", entry2); + + // Insert a new entry with position 0 without bumping + var entry3 = new LeaderboardEntry { id = 3, score = 110f, position = 0, leaderboardSortMode = "desc" }; + manager.UpsertEntry("test", entry3, bumpPositions: false); + + var entries = manager.GetEntries("test"); + + Assert.AreEqual(3, entries.Count); + Assert.AreEqual(3, entries[0].id); + Assert.AreEqual(0, entries[0].position); // new entry at position 0 + + Assert.AreEqual(1, entries[1].id); + Assert.AreEqual(0, entries[1].position); // unchanged - still position 0 + + Assert.AreEqual(2, entries[2].id); + Assert.AreEqual(1, entries[2].position); // unchanged - still position 1 + } } } \ No newline at end of file