diff --git a/Storage/Storage-Unity/Storage-Unity.csproj b/Storage/Storage-Unity/Storage-Unity.csproj
index 1151018..7f8ff6f 100644
--- a/Storage/Storage-Unity/Storage-Unity.csproj
+++ b/Storage/Storage-Unity/Storage-Unity.csproj
@@ -123,6 +123,18 @@
LCSMSClient.cs
+
+ Leaderboard\LCLeaderboardArchive.cs
+
+
+ Leaderboard\LCStatistic.cs
+
+
+ Leaderboard\LCLeaderboard.cs
+
+
+ Leaderboard\LCRanking.cs
+
diff --git a/Storage/Storage.Test/LeaderboardTest.cs b/Storage/Storage.Test/LeaderboardTest.cs
new file mode 100644
index 0000000..97cf386
--- /dev/null
+++ b/Storage/Storage.Test/LeaderboardTest.cs
@@ -0,0 +1,116 @@
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using LeanCloud;
+using LeanCloud.Storage;
+
+using static NUnit.Framework.TestContext;
+
+namespace Storage.Test {
+ public class LeaderboardTest {
+ private string leaderboardName;
+
+ [SetUp]
+ public void SetUp() {
+ LCLogger.LogDelegate += Utils.Print;
+ LCApplication.Initialize(Utils.AppId, Utils.AppKey, Utils.AppServer, Utils.MasterKey);
+ LCApplication.UseMasterKey = true;
+ leaderboardName = $"Leaderboard_{DateTimeOffset.Now.DayOfYear}";
+ }
+
+ [TearDown]
+ public void TearDown() {
+ LCApplication.UseMasterKey = false;
+ LCLogger.LogDelegate -= Utils.Print;
+ }
+
+ [Test]
+ [Order(0)]
+ public async Task Create() {
+ try {
+ LCLeaderboard oldLeaderboard = LCLeaderboard.CreateWithoutData(leaderboardName);
+ await oldLeaderboard.Destroy();
+ } catch (Exception e) {
+ WriteLine(e.Message);
+ }
+ LCLeaderboard leaderboard = await LCLeaderboard.CreateLeaderboard(leaderboardName);
+ Assert.AreEqual(leaderboard.StatisticName, leaderboardName);
+ }
+
+ [Test]
+ [Order(1)]
+ public async Task Update() {
+ for (int i = 0; i < 10; i++) {
+ int today = DateTimeOffset.Now.DayOfYear;
+ string username = $"{today}_{i}";
+ string password = "leancloud";
+ LCUser user;
+ try {
+ user = await LCUser.Login(username, password);
+ } catch (Exception) {
+ user = new LCUser {
+ Username = username,
+ Password = password
+ };
+ await user.SignUp();
+ }
+ await LCLeaderboard.UpdateStatistics(user, new Dictionary {
+ { leaderboardName, i * 10 }
+ });
+ }
+ }
+
+ [Test]
+ [Order(2)]
+ public async Task GetStatistics() {
+ int today = DateTimeOffset.Now.DayOfYear;
+ string username = $"{today}_0";
+ string password = "leancloud";
+ LCUser user = await LCUser.Login(username, password);
+ ReadOnlyCollection statistics = await LCLeaderboard.GetStatistics(user);
+ foreach (LCStatistic statistic in statistics) {
+ WriteLine($"{statistic.Name} : {statistic.Value}");
+ }
+ }
+
+ [Test]
+ [Order(3)]
+ public async Task GetResults() {
+ LCLeaderboard leaderboard = LCLeaderboard.CreateWithoutData(leaderboardName);
+ ReadOnlyCollection rankings = await leaderboard.GetResults();
+ foreach (LCRanking ranking in rankings) {
+ WriteLine($"{ranking.Rank} : {ranking.User.ObjectId}, {ranking.Value}");
+ }
+ }
+
+ [Test]
+ [Order(4)]
+ public async Task GetResultsOfMe() {
+ int today = DateTimeOffset.Now.DayOfYear;
+ string username = $"{today}_0";
+ string password = "leancloud";
+ await LCUser.Login(username, password);
+ LCLeaderboard leaderboard = LCLeaderboard.CreateWithoutData(leaderboardName);
+ ReadOnlyCollection rankings = await leaderboard.GetResultsAroundUser(limit: 5);
+ foreach (LCRanking ranking in rankings) {
+ WriteLine($"{ranking.Rank} : {ranking.User.ObjectId}, {ranking.Value}");
+ }
+ }
+
+ [Test]
+ [Order(5)]
+ public async Task GetOtherStatistics() {
+ int today = DateTimeOffset.Now.DayOfYear;
+ string username = $"{today}_0";
+ string password = "leancloud";
+ LCUser user = await LCUser.Login(username, password);
+ await LCUser.Login($"{today}_1", password);
+ ReadOnlyCollection statistics = await LCLeaderboard.GetStatistics(user);
+ foreach (LCStatistic statistic in statistics) {
+ WriteLine($"{statistic.Name}, {statistic.Value}");
+ }
+ }
+ }
+}
diff --git a/Storage/Storage.Test/QueryTest.cs b/Storage/Storage.Test/QueryTest.cs
index 27d3a89..5c7a9b1 100644
--- a/Storage/Storage.Test/QueryTest.cs
+++ b/Storage/Storage.Test/QueryTest.cs
@@ -334,7 +334,9 @@ namespace Storage.Test {
Assert.Greater(hellos.Count, 0);
foreach (LCObject item in hellos) {
LCObject world = item["objectValue"] as LCObject;
- Assert.IsTrue(world == null || world["content"] != "7788");
+ Assert.IsTrue(world == null ||
+ world["content"] == null ||
+ world["content"] as string != "7788");
}
}
}
diff --git a/Storage/Storage.Test/Utils.cs b/Storage/Storage.Test/Utils.cs
index 3876751..7a58982 100644
--- a/Storage/Storage.Test/Utils.cs
+++ b/Storage/Storage.Test/Utils.cs
@@ -5,6 +5,7 @@ namespace Storage.Test {
public static class Utils {
internal const string AppId = "ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz";
internal const string AppKey = "NUKmuRbdAhg1vrb2wexYo1jo";
+ internal const string MasterKey = "pyvbNSh5jXsuFQ3C8EgnIdhw";
internal const string AppServer = "https://ikggdre2.lc-cn-n1-shared.com";
internal static void Print(LCLogLevel level, string info) {
diff --git a/Storage/Storage/Internal/Codec/LCDecoder.cs b/Storage/Storage/Internal/Codec/LCDecoder.cs
index b5acfa2..f9dd00a 100644
--- a/Storage/Storage/Internal/Codec/LCDecoder.cs
+++ b/Storage/Storage/Internal/Codec/LCDecoder.cs
@@ -41,19 +41,19 @@ namespace LeanCloud.Storage.Internal.Codec {
return obj;
}
- static DateTime DecodeDate(IDictionary dict) {
+ public static DateTime DecodeDate(IDictionary dict) {
string str = dict["iso"].ToString();
DateTime dateTime = DateTime.Parse(str);
return dateTime.ToLocalTime();
}
- static byte[] DecodeBytes(IDictionary dict) {
+ public static byte[] DecodeBytes(IDictionary dict) {
string str = dict["base64"].ToString();
byte[] bytes = Convert.FromBase64String(str);
return bytes;
}
- static LCObject DecodeObject(IDictionary dict) {
+ public static LCObject DecodeObject(IDictionary dict) {
string className = dict["className"].ToString();
LCObject obj = LCObject.Create(className);
LCObjectData objectData = LCObjectData.Decode(dict as Dictionary);
@@ -61,13 +61,13 @@ namespace LeanCloud.Storage.Internal.Codec {
return obj;
}
- static LCRelation DecodeRelation(IDictionary dict) {
+ public static LCRelation DecodeRelation(IDictionary dict) {
LCRelation relation = new LCRelation();
relation.TargetClass = dict["className"].ToString();
return relation;
}
- static LCGeoPoint DecodeGeoPoint(IDictionary data) {
+ public static LCGeoPoint DecodeGeoPoint(IDictionary data) {
double latitude = double.Parse(data["latitude"].ToString());
double longitude = double.Parse(data["longitude"].ToString());
LCGeoPoint geoPoint = new LCGeoPoint(latitude, longitude);
diff --git a/Storage/Storage/Internal/Codec/LCEncoder.cs b/Storage/Storage/Internal/Codec/LCEncoder.cs
index 5af75bf..383247b 100644
--- a/Storage/Storage/Internal/Codec/LCEncoder.cs
+++ b/Storage/Storage/Internal/Codec/LCEncoder.cs
@@ -31,7 +31,7 @@ namespace LeanCloud.Storage.Internal.Codec {
return obj;
}
- static object EncodeDateTime(DateTime dateTime) {
+ public static object EncodeDateTime(DateTime dateTime) {
DateTime utc = dateTime.ToUniversalTime();
string str = utc.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
return new Dictionary {
@@ -40,7 +40,7 @@ namespace LeanCloud.Storage.Internal.Codec {
};
}
- static object EncodeBytes(byte[] bytes) {
+ public static object EncodeBytes(byte[] bytes) {
string str = Convert.ToBase64String(bytes);
return new Dictionary {
{ "__type", "Bytes" },
@@ -48,7 +48,7 @@ namespace LeanCloud.Storage.Internal.Codec {
};
}
- static object EncodeList(IList list) {
+ public static object EncodeList(IList list) {
List