leancloud-storage
Version:
LeanCloud JavaScript SDK.
546 lines (499 loc) • 17.4 kB
JavaScript
'use strict';
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _ = require('underscore');
var _require = require('./request'),
request = _require.request;
var _require2 = require('./utils'),
ensureArray = _require2.ensureArray,
parseDate = _require2.parseDate;
var AV = require('./av');
/**
* The version change interval for Leaderboard
* @enum
*/
AV.LeaderboardVersionChangeInterval = {
NEVER: 'never',
DAY: 'day',
WEEK: 'week',
MONTH: 'month'
};
/**
* The order of the leaderboard results
* @enum
*/
AV.LeaderboardOrder = {
ASCENDING: 'ascending',
DESCENDING: 'descending'
};
/**
* The update strategy for Leaderboard
* @enum
*/
AV.LeaderboardUpdateStrategy = {
/** Only keep the best statistic. If the leaderboard is in descending order, the best statistic is the highest one. */
BETTER: 'better',
/** Keep the last updated statistic */
LAST: 'last',
/** Keep the sum of all updated statistics */
SUM: 'sum'
};
/**
* @typedef {Object} Ranking
* @property {number} rank Starts at 0
* @property {number} value the statistic value of this ranking
* @property {AV.User} user The user of this ranking
* @property {Statistic[]} [includedStatistics] Other statistics of the user, specified by the `includeStatistic` option of `AV.Leaderboard.getResults()`
*/
/**
* @typedef {Object} LeaderboardArchive
* @property {string} statisticName
* @property {number} version version of the leaderboard
* @property {string} status
* @property {string} url URL for the downloadable archive
* @property {Date} activatedAt time when this version became active
* @property {Date} deactivatedAt time when this version was deactivated by a version incrementing
*/
/**
* @class
*/
function Statistic(_ref) {
var name = _ref.name,
value = _ref.value,
version = _ref.version;
/**
* @type {string}
*/
this.name = name;
/**
* @type {number}
*/
this.value = value;
/**
* @type {number?}
*/
this.version = version;
}
var parseStatisticData = function parseStatisticData(statisticData) {
var _AV$_decode = AV._decode(statisticData),
name = _AV$_decode.statisticName,
value = _AV$_decode.statisticValue,
version = _AV$_decode.version;
return new Statistic({ name: name, value: value, version: version });
};
/**
* @class
*/
AV.Leaderboard = function Leaderboard(statisticName) {
/**
* @type {string}
*/
this.statisticName = statisticName;
/**
* @type {AV.LeaderboardOrder}
*/
this.order = undefined;
/**
* @type {AV.LeaderboardUpdateStrategy}
*/
this.updateStrategy = undefined;
/**
* @type {AV.LeaderboardVersionChangeInterval}
*/
this.versionChangeInterval = undefined;
/**
* @type {number}
*/
this.version = undefined;
/**
* @type {Date?}
*/
this.nextResetAt = undefined;
/**
* @type {Date?}
*/
this.createdAt = undefined;
};
var Leaderboard = AV.Leaderboard;
/**
* Create an instance of Leaderboard for the give statistic name.
* @param {string} statisticName
* @return {AV.Leaderboard}
*/
AV.Leaderboard.createWithoutData = function (statisticName) {
return new Leaderboard(statisticName);
};
/**
* (masterKey required) Create a new Leaderboard.
* @param {Object} options
* @param {string} options.statisticName
* @param {AV.LeaderboardOrder} options.order
* @param {AV.LeaderboardVersionChangeInterval} [options.versionChangeInterval] default to WEEK
* @param {AV.LeaderboardUpdateStrategy} [options.updateStrategy] default to BETTER
* @param {AuthOptions} [authOptions]
* @return {Promise<AV.Leaderboard>}
*/
AV.Leaderboard.createLeaderboard = function (_ref2, authOptions) {
var statisticName = _ref2.statisticName,
order = _ref2.order,
versionChangeInterval = _ref2.versionChangeInterval,
updateStrategy = _ref2.updateStrategy;
return request({
method: 'POST',
path: '/leaderboard/leaderboards',
data: {
statisticName: statisticName,
order: order,
versionChangeInterval: versionChangeInterval,
updateStrategy: updateStrategy
},
authOptions: authOptions
}).then(function (data) {
var leaderboard = new Leaderboard(statisticName);
return leaderboard._finishFetch(data);
});
};
/**
* Get the Leaderboard with the specified statistic name.
* @param {string} statisticName
* @param {AuthOptions} [authOptions]
* @return {Promise<AV.Leaderboard>}
*/
AV.Leaderboard.getLeaderboard = function (statisticName, authOptions) {
return Leaderboard.createWithoutData(statisticName).fetch(authOptions);
};
/**
* Get Statistics for the specified user.
* @param {AV.User} user The specified AV.User pointer.
* @param {Object} [options]
* @param {string[]} [options.statisticNames] Specify the statisticNames. If not set, all statistics of the user will be fetched.
* @param {AuthOptions} [authOptions]
* @return {Promise<Statistic[]>}
*/
AV.Leaderboard.getStatistics = function (user) {
var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
statisticNames = _ref3.statisticNames;
var authOptions = arguments[2];
return _promise2.default.resolve().then(function () {
if (!(user && user.id)) throw new Error('user must be an AV.User');
return request({
method: 'GET',
path: '/leaderboard/users/' + user.id + '/statistics',
query: {
statistics: statisticNames ? ensureArray(statisticNames).join(',') : undefined
},
authOptions: authOptions
}).then(function (_ref4) {
var results = _ref4.results;
return results.map(parseStatisticData);
});
});
};
/**
* Update Statistics for the specified user.
* @param {AV.User} user The specified AV.User pointer.
* @param {Object} statistics A name-value pair representing the statistics to update.
* @param {AuthOptions} [options] AuthOptions plus:
* @param {boolean} [options.overwrite] Wethere to overwrite these statistics disregarding the updateStrategy of there leaderboards
* @return {Promise<Statistic[]>}
*/
AV.Leaderboard.updateStatistics = function (user, statistics) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return _promise2.default.resolve().then(function () {
if (!(user && user.id)) throw new Error('user must be an AV.User');
var data = _.map(statistics, function (value, key) {
return {
statisticName: key,
statisticValue: value
};
});
var overwrite = options.overwrite;
return request({
method: 'POST',
path: '/leaderboard/users/' + user.id + '/statistics',
query: {
overwrite: overwrite ? 1 : undefined
},
data: data,
authOptions: options
}).then(function (_ref5) {
var results = _ref5.results;
return results.map(parseStatisticData);
});
});
};
/**
* Delete Statistics for the specified user.
* @param {AV.User} user The specified AV.User pointer.
* @param {Object} statistics A name-value pair representing the statistics to delete.
* @param {AuthOptions} [options]
* @return {Promise<void>}
*/
AV.Leaderboard.deleteStatistics = function (user, statisticNames, authOptions) {
return _promise2.default.resolve().then(function () {
if (!(user && user.id)) throw new Error('user must be an AV.User');
return request({
method: 'DELETE',
path: '/leaderboard/users/' + user.id + '/statistics',
query: {
statistics: ensureArray(statisticNames).join(',')
},
authOptions: authOptions
}).then(function () {
return undefined;
});
});
};
_.extend(Leaderboard.prototype,
/** @lends AV.Leaderboard.prototype */{
_finishFetch: function _finishFetch(data) {
var _this = this;
_.forEach(data, function (value, key) {
if (key === 'updatedAt' || key === 'objectId') return;
if (key === 'expiredAt') {
key = 'nextResetAt';
}
if (key === 'createdAt') {
value = parseDate(value);
}
if (value && value.__type === 'Date') {
value = parseDate(value.iso);
}
_this[key] = value;
});
return this;
},
/**
* Fetch data from the srever.
* @param {AuthOptions} [authOptions]
* @return {Promise<AV.Leaderboard>}
*/
fetch: function fetch(authOptions) {
var _this2 = this;
return request({
method: 'GET',
path: '/leaderboard/leaderboards/' + this.statisticName,
authOptions: authOptions
}).then(function (data) {
return _this2._finishFetch(data);
});
},
/**
* Counts the number of users participated in this leaderboard
* @param {Object} [options]
* @param {number} [options.version] Specify the version of the leaderboard
* @param {AuthOptions} [authOptions]
* @return {Promise<number>}
*/
count: function count() {
var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
version = _ref6.version;
var authOptions = arguments[1];
return request({
method: 'GET',
path: '/leaderboard/leaderboards/' + this.statisticName + '/ranks',
query: {
count: 1,
limit: 0,
version: version
},
authOptions: authOptions
}).then(function (_ref7) {
var count = _ref7.count;
return count;
});
},
_getResults: function _getResults(_ref8, authOptions, userId) {
var skip = _ref8.skip,
limit = _ref8.limit,
selectUserKeys = _ref8.selectUserKeys,
includeUserKeys = _ref8.includeUserKeys,
includeStatistics = _ref8.includeStatistics,
version = _ref8.version;
return request({
method: 'GET',
path: '/leaderboard/leaderboards/' + this.statisticName + '/ranks' + (userId ? '/' + userId : ''),
query: {
skip: skip,
limit: limit,
selectUserKeys: _.union(ensureArray(selectUserKeys), ensureArray(includeUserKeys)).join(',') || undefined,
includeUser: includeUserKeys ? ensureArray(includeUserKeys).join(',') : undefined,
includeStatistics: includeStatistics ? ensureArray(includeStatistics).join(',') : undefined,
version: version
},
authOptions: authOptions
}).then(function (_ref9) {
var rankings = _ref9.results;
return rankings.map(function (rankingData) {
var _AV$_decode2 = AV._decode(rankingData),
user = _AV$_decode2.user,
value = _AV$_decode2.statisticValue,
rank = _AV$_decode2.rank,
_AV$_decode2$statisti = _AV$_decode2.statistics,
statistics = _AV$_decode2$statisti === undefined ? [] : _AV$_decode2$statisti;
return {
user: user,
value: value,
rank: rank,
includedStatistics: statistics.map(parseStatisticData)
};
});
});
},
/**
* Retrieve a list of ranked users for this Leaderboard.
* @param {Object} [options]
* @param {number} [options.skip] The number of results to skip. This is useful for pagination.
* @param {number} [options.limit] The limit of the number of results.
* @param {string[]} [options.selectUserKeys] Specify keys of the users to include in the Rankings
* @param {string[]} [options.includeUserKeys] If the value of a selected user keys is a Pointer, use this options to include its value.
* @param {string[]} [options.includeStatistics] Specify other statistics to include in the Rankings
* @param {number} [options.version] Specify the version of the leaderboard
* @param {AuthOptions} [authOptions]
* @return {Promise<Ranking[]>}
*/
getResults: function getResults() {
var _ref10 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
skip = _ref10.skip,
limit = _ref10.limit,
selectUserKeys = _ref10.selectUserKeys,
includeUserKeys = _ref10.includeUserKeys,
includeStatistics = _ref10.includeStatistics,
version = _ref10.version;
var authOptions = arguments[1];
return this._getResults({
skip: skip,
limit: limit,
selectUserKeys: selectUserKeys,
includeUserKeys: includeUserKeys,
includeStatistics: includeStatistics,
version: version
}, authOptions);
},
/**
* Retrieve a list of ranked users for this Leaderboard, centered on the specified user.
* @param {AV.User} user The specified AV.User pointer.
* @param {Object} [options]
* @param {number} [options.limit] The limit of the number of results.
* @param {string[]} [options.selectUserKeys] Specify keys of the users to include in the Rankings
* @param {string[]} [options.includeUserKeys] If the value of a selected user keys is a Pointer, use this options to include its value.
* @param {string[]} [options.includeStatistics] Specify other statistics to include in the Rankings
* @param {number} [options.version] Specify the version of the leaderboard
* @param {AuthOptions} [authOptions]
* @return {Promise<Ranking[]>}
*/
getResultsAroundUser: function getResultsAroundUser(user) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var authOptions = arguments[2];
// getResultsAroundUser(options, authOptions)
if (user && typeof user.id !== 'string') {
return this.getResultsAroundUser(undefined, user, options);
}
var limit = options.limit,
selectUserKeys = options.selectUserKeys,
includeUserKeys = options.includeUserKeys,
includeStatistics = options.includeStatistics,
version = options.version;
return this._getResults({ limit: limit, selectUserKeys: selectUserKeys, includeUserKeys: includeUserKeys, includeStatistics: includeStatistics, version: version }, authOptions, user ? user.id : 'self');
},
_update: function _update(data, authOptions) {
var _this3 = this;
return request({
method: 'PUT',
path: '/leaderboard/leaderboards/' + this.statisticName,
data: data,
authOptions: authOptions
}).then(function (result) {
return _this3._finishFetch(result);
});
},
/**
* (masterKey required) Update the version change interval of the Leaderboard.
* @param {AV.LeaderboardVersionChangeInterval} versionChangeInterval
* @param {AuthOptions} [authOptions]
* @return {Promise<AV.Leaderboard>}
*/
updateVersionChangeInterval: function updateVersionChangeInterval(versionChangeInterval, authOptions) {
return this._update({ versionChangeInterval: versionChangeInterval }, authOptions);
},
/**
* (masterKey required) Update the version change interval of the Leaderboard.
* @param {AV.LeaderboardUpdateStrategy} updateStrategy
* @param {AuthOptions} [authOptions]
* @return {Promise<AV.Leaderboard>}
*/
updateUpdateStrategy: function updateUpdateStrategy(updateStrategy, authOptions) {
return this._update({ updateStrategy: updateStrategy }, authOptions);
},
/**
* (masterKey required) Reset the Leaderboard. The version of the Leaderboard will be incremented by 1.
* @param {AuthOptions} [authOptions]
* @return {Promise<AV.Leaderboard>}
*/
reset: function reset(authOptions) {
var _this4 = this;
return request({
method: 'PUT',
path: '/leaderboard/leaderboards/' + this.statisticName + '/incrementVersion',
authOptions: authOptions
}).then(function (data) {
return _this4._finishFetch(data);
});
},
/**
* (masterKey required) Delete the Leaderboard and its all archived versions.
* @param {AuthOptions} [authOptions]
* @return {void}
*/
destroy: function destroy(authOptions) {
return AV.request({
method: 'DELETE',
path: '/leaderboard/leaderboards/' + this.statisticName,
authOptions: authOptions
}).then(function () {
return undefined;
});
},
/**
* (masterKey required) Get archived versions.
* @param {Object} [options]
* @param {number} [options.skip] The number of results to skip. This is useful for pagination.
* @param {number} [options.limit] The limit of the number of results.
* @param {AuthOptions} [authOptions]
* @return {Promise<LeaderboardArchive[]>}
*/
getArchives: function getArchives() {
var _this5 = this;
var _ref11 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
skip = _ref11.skip,
limit = _ref11.limit;
var authOptions = arguments[1];
return request({
method: 'GET',
path: '/leaderboard/leaderboards/' + this.statisticName + '/archives',
query: {
skip: skip,
limit: limit
},
authOptions: authOptions
}).then(function (_ref12) {
var results = _ref12.results;
return results.map(function (_ref13) {
var version = _ref13.version,
status = _ref13.status,
url = _ref13.url,
activatedAt = _ref13.activatedAt,
deactivatedAt = _ref13.deactivatedAt;
return {
statisticName: _this5.statisticName,
version: version,
status: status,
url: url,
activatedAt: parseDate(activatedAt.iso),
deactivatedAt: parseDate(deactivatedAt.iso)
};
});
});
}
});