Skip to content

Commit bb08362

Browse files
committed
fix(leaderboard): revise #getResults
- returns Ranking[] instead of Statistic[] - add includeStatistics option
1 parent 4e36a33 commit bb08362

File tree

6 files changed

+181
-117
lines changed

6 files changed

+181
-117
lines changed

demo/leaderboard/index.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@
3131
</transition>
3232
</div>
3333
</div>
34-
<transition-group name="statistic-list" class="statistic-list" tag="ul">
35-
<li v-for="statistic in statistics" class="statistic" :key="statistic.user.username" :class="{ completed: statistic.done }">
36-
<span>{{statistic.position + 1}}.&nbsp;</span>
37-
<span class="username">{{statistic.user.username}}
38-
<span v-if="statistic.user.username == user.username">(你)</span>
34+
<transition-group name="ranking-list" class="ranking-list" tag="ul">
35+
<li v-for="ranking in rankings" class="ranking" :key="ranking.user.username" :class="{ completed: ranking.done }">
36+
<span>{{ranking.rank + 1}}.&nbsp;</span>
37+
<span class="username">{{ranking.user.username}}
38+
<span v-if="ranking.user.username == user.username">(你)</span>
3939
</span>
4040
<span class="score">
41-
<animated-integer :value="statistic.value"></animated-integer>
41+
<animated-integer :value="ranking.value"></animated-integer>
4242
</span>
4343
</li>
4444
</transition-group>

demo/leaderboard/leaderboard.css

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ a:visited {
6262
left: 0;
6363
}
6464

65-
.statistic-list {
65+
.ranking-list {
6666
height: 100%;
6767
flex: 1;
6868
margin: 0;
@@ -74,7 +74,7 @@ a:visited {
7474
overflow: auto;
7575
}
7676

77-
.statistic {
77+
.ranking {
7878
background: linear-gradient(320deg, #581b98, #9c1de7);
7979
height: 100%;
8080
max-height: 8.333%;
@@ -87,34 +87,34 @@ a:visited {
8787
position: relative;
8888
}
8989

90-
.statistic-list-move {
90+
.ranking-list-move {
9191
transition: transform 1s;
9292
}
9393

94-
.statistic-list-enter,
95-
.statistic-list-leave-to {
94+
.ranking-list-enter,
95+
.ranking-list-leave-to {
9696
opacity: 0;
9797
transform: translateY(-30px);
9898
}
99-
.statistic-list-leave-active {
99+
.ranking-list-leave-active {
100100
position: absolute;
101101
}
102102

103-
.statistic:nth-child(1) {
103+
.ranking:nth-child(1) {
104104
color: gold;
105105
}
106-
.statistic:nth-child(2) {
106+
.ranking:nth-child(2) {
107107
color: lightgray;
108108
}
109-
.statistic:nth-child(3) {
109+
.ranking:nth-child(3) {
110110
color: sandybrown;
111111
}
112112

113113
.username {
114114
width: 100%;
115115
flex: 1;
116116
}
117-
.statistic .score {
117+
.ranking .score {
118118
max-width: 44px;
119119
overflow: hidden;
120120
}

demo/leaderboard/leaderboard.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Vue.component('animated-integer', {
4848

4949
var app = new Vue({
5050
data: {
51-
statistics: [],
51+
rankings: [],
5252
score: null,
5353
highScore: 0,
5454
newHighScore: false,
@@ -115,32 +115,32 @@ var app = new Vue({
115115
Promise.all([
116116
leaderboard.getResults({
117117
limit: MAX_RESULTS_COUNT,
118-
includeUserKeys: ['username'],
118+
selectUserKeys: ['username'],
119119
}),
120120
Promise.resolve(
121121
AV.User.current()
122122
? leaderboard.getResultsAroundUser({
123123
limit: 3,
124-
includeUserKeys: ['username'],
124+
selectUserKeys: ['username'],
125125
})
126126
: []
127127
),
128128
])
129-
.then(([topStatistics, [beforeUserStatistic, userStatistic]]) => {
130-
console.log(topStatistics, [beforeUserStatistic, userStatistic]);
131-
let statistics;
132-
if (userStatistic && userStatistic.position >= MAX_RESULTS_COUNT) {
133-
statistics = [
134-
...topStatistics.slice(0, -2),
135-
beforeUserStatistic,
136-
userStatistic,
129+
.then(([topRankings, [beforeUserRankings, userRanking]]) => {
130+
console.log(topRankings, [beforeUserRankings, userRanking]);
131+
let rankings;
132+
if (userRanking && userRanking.rank >= MAX_RESULTS_COUNT) {
133+
rankings = [
134+
...topRankings.slice(0, -2),
135+
beforeUserRankings,
136+
userRanking,
137137
];
138138
} else {
139-
statistics = topStatistics;
139+
rankings = topRankings;
140140
}
141-
this.statistics = JSON.parse(JSON.stringify(statistics));
142-
if (userStatistic) {
143-
this.highScore = userStatistic.value;
141+
this.rankings = JSON.parse(JSON.stringify(rankings));
142+
if (userRanking) {
143+
this.highScore = userRanking.value;
144144
}
145145
})
146146
.catch(console.error);

src/leaderboard.js

Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,18 @@ AV.LeaderboardUpdateStrategy = {
3636
LAST: 'last',
3737
};
3838

39+
/**
40+
* @typedef {Object} Ranking
41+
* @property {number} rank Starts at 0
42+
* @property {number} value the statistic value of this ranking
43+
* @property {AV.User} user The user of this ranking
44+
* @property {Statistic[]} [includedStatistics] Other statistics of the user, specified by the `includeStatistic` option of `AV.Leaderboard.getResults()`
45+
*/
46+
3947
/**
4048
* @class
4149
*/
42-
function Statistic({ user, name, value, position, version }) {
50+
function Statistic({ name, value, version }) {
4351
/**
4452
* @type {string}
4553
*/
@@ -48,21 +56,19 @@ function Statistic({ user, name, value, position, version }) {
4856
* @type {number}
4957
*/
5058
this.value = value;
51-
/**
52-
* @type {AV.User}
53-
*/
54-
this.user = user;
55-
/**
56-
* The position of the leandboard. Only occurs in leaderboard results.
57-
* @type {number?}
58-
*/
59-
this.position = position;
6059
/**
6160
* @type {number?}
6261
*/
6362
this.version = version;
6463
}
6564

65+
const parseStatisticData = statisticData => {
66+
const { statisticName: name, statisticValue: value, version } = AV._decode(
67+
statisticData
68+
);
69+
return new Statistic({ name, value, version });
70+
};
71+
6672
/**
6773
* @class
6874
*/
@@ -156,19 +162,12 @@ AV.Leaderboard.getStatistics = (user, { statisticNames } = {}, authOptions) =>
156162
method: 'GET',
157163
path: `/leaderboard/users/${user.id}/statistics`,
158164
query: {
159-
statistics: statisticNames ? ensureArray(statisticNames) : undefined,
165+
statistics: statisticNames
166+
? ensureArray(statisticNames).join(',')
167+
: undefined,
160168
},
161169
authOptions,
162-
}).then(({ results }) =>
163-
results.map(statisticData => {
164-
const {
165-
statisticName: name,
166-
statisticValue: value,
167-
version,
168-
} = AV._decode(statisticData);
169-
return new Statistic({ user, name, value, version });
170-
})
171-
);
170+
}).then(({ results }) => results.map(parseStatisticData));
172171
});
173172
/**
174173
* Update Statistics for the specified user.
@@ -189,16 +188,7 @@ AV.Leaderboard.updateStatistics = (user, statistics, authOptions) =>
189188
path: `/leaderboard/users/${user.id}/statistics`,
190189
data,
191190
authOptions,
192-
}).then(({ results }) =>
193-
results.map(statisticData => {
194-
const {
195-
statisticName: name,
196-
statisticValue: value,
197-
version,
198-
} = AV._decode(statisticData);
199-
return new Statistic({ user, name, value, version });
200-
})
201-
);
191+
}).then(({ results }) => results.map(parseStatisticData));
202192
});
203193

204194
_.extend(
@@ -213,7 +203,7 @@ _.extend(
213203
if (key === 'createdAt') {
214204
value = parseDate(value);
215205
}
216-
if (value.__type === 'Date') {
206+
if (value && value.__type === 'Date') {
217207
value = parseDate(value.iso);
218208
}
219209
this[key] = value;
@@ -232,29 +222,41 @@ _.extend(
232222
authOptions,
233223
}).then(data => this._finishFetch(data));
234224
},
235-
_getResults({ skip, limit, includeUserKeys }, authOptions, self) {
225+
_getResults(
226+
{ skip, limit, selectUserKeys, includeStatistics },
227+
authOptions,
228+
self
229+
) {
236230
return request({
237231
method: 'GET',
238-
path: `/leaderboard/leaderboards/${this.statisticName}/positions${
232+
path: `/leaderboard/leaderboards/${this.statisticName}/ranks${
239233
self ? '/self' : ''
240234
}`,
241235
query: {
242236
skip,
243237
limit,
244-
includeUser: includeUserKeys
245-
? ensureArray(includeUserKeys).join(',')
238+
includeUser: selectUserKeys
239+
? ensureArray(selectUserKeys).join(',')
240+
: undefined,
241+
includeStatistics: includeStatistics
242+
? ensureArray(includeStatistics).join(',')
246243
: undefined,
247244
},
248245
authOptions,
249-
}).then(({ results }) =>
250-
results.map(statisticData => {
246+
}).then(({ results: rankings }) =>
247+
rankings.map(rankingData => {
251248
const {
252249
user,
253-
statisticName: name,
254250
statisticValue: value,
255-
position,
256-
} = AV._decode(statisticData);
257-
return new Statistic({ user, name, value, position });
251+
rank,
252+
statistics = [],
253+
} = AV._decode(rankingData);
254+
return {
255+
user,
256+
value,
257+
rank,
258+
includedStatistics: statistics.map(parseStatisticData),
259+
};
258260
})
259261
);
260262
},
@@ -263,23 +265,38 @@ _.extend(
263265
* @param {Object} [options]
264266
* @param {number} [options.skip] The number of results to skip. This is useful for pagination.
265267
* @param {number} [options.limit] The limit of the number of results.
266-
* @param {string[]} [options.includeUserKeys] Specify keys of the users to include
268+
* @param {string[]} [options.selectUserKeys] Specify keys of the users to include
269+
* @param {string[]} [options.includeStatistics] Specify other statistics to include in the Rankings
267270
* @param {AuthOptions} [authOptions]
268-
* @return {Promise<Statistic[]>}
271+
* @return {Promise<Ranking[]>}
269272
*/
270-
getResults({ skip, limit, includeUserKeys } = {}, authOptions) {
271-
return this._getResults({ skip, limit, includeUserKeys }, authOptions);
273+
getResults(
274+
{ skip, limit, selectUserKeys, includeStatistics } = {},
275+
authOptions
276+
) {
277+
return this._getResults(
278+
{ skip, limit, selectUserKeys, includeStatistics },
279+
authOptions
280+
);
272281
},
273282
/**
274283
* Retrieve a list of ranked users for this Leaderboard, centered on the specified user.
275284
* @param {Object} [options]
276285
* @param {number} [options.limit] The limit of the number of results.
277-
* @param {string[]} [options.includeUserKeys] Specify keys of the users to include
286+
* @param {string[]} [options.selectUserKeys] Specify keys of the users to include
287+
* @param {string[]} [options.includeStatistics] Specify other statistics to include in the Rankings
278288
* @param {AuthOptions} [authOptions]
279-
* @return {Promise<Statistic[]>}
289+
* @return {Promise<Ranking[]>}
280290
*/
281-
getResultsAroundUser({ limit, includeUserKeys } = {}, authOptions) {
282-
return this._getResults({ limit, includeUserKeys }, authOptions, true);
291+
getResultsAroundUser(
292+
{ limit, selectUserKeys, includeStatistics } = {},
293+
authOptions
294+
) {
295+
return this._getResults(
296+
{ limit, selectUserKeys, includeStatistics },
297+
authOptions,
298+
true
299+
);
283300
},
284301
_update(data, authOptions) {
285302
return request({

storage.d.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,11 +791,16 @@ export class Conversation extends Object {
791791
declare class Statistic {
792792
name: string;
793793
value: number;
794-
user: AV.User;
795-
position?: number;
796794
version?: number;
797795
}
798796

797+
declare interface Ranking {
798+
value: number;
799+
user: AV.User;
800+
rank: number;
801+
includedStatistics?: Statistic[];
802+
}
803+
799804
export class Leaderboard {
800805
statisticName: string;
801806
order?: LeaderboardOrder;
@@ -831,13 +836,22 @@ export class Leaderboard {
831836

832837
fetch(authOptions?: AuthOptions): Promise<Leaderboard>;
833838
getResults(
834-
options?: { skip?: number; limit?: number; includeUserKeys?: string[] },
839+
options?: {
840+
skip?: number;
841+
limit?: number;
842+
selectUserKeys?: string | string[];
843+
includeStatistics?: string | string[];
844+
},
835845
authOptions?: AuthOptions
836-
): Promise<Statistic[]>;
846+
): Promise<Ranking[]>;
837847
getResultsAroundUser(
838-
options?: { limit?: number; includeUserKeys?: string[] },
848+
options?: {
849+
limit?: number;
850+
selectUserKeys?: string | string[];
851+
includeStatistics?: string | string[];
852+
},
839853
authOptions?: AuthOptions
840-
): Promise<Statistic[]>;
854+
): Promise<Ranking[]>;
841855
updateVersionChangeInterval(
842856
versionChangeInterval: LeaderboardVersionChangeInterval,
843857
authOptions?: AuthOptions

0 commit comments

Comments
 (0)