feat(users): calculate the user hourly scores income

This commit is contained in:
OldHawk
2018-06-03 23:51:31 +08:00
parent 717acfc98b
commit b9900a9b7c
23 changed files with 385 additions and 47 deletions

View File

@@ -506,6 +506,7 @@ module.exports = {
downloadValue: 0.5,
downloadEnable: true,
vipRatio: 1.5,
uploaderRatio: 2,
enable: true
},
@@ -525,11 +526,11 @@ module.exports = {
name: 'seedSeederAndLife',
content: 'SEED_SEEDER_AND_LIFE',
seederBasicRatio: 1,
seederCoefficient: 0.2,
seederCoefficient: 0.1,
seederCount: 10,
lifeBasicRatio: 1,
lifeCoefficientOfDay: 0.002,
lifeMaxRatio: 3,
lifeCoefficientOfDay: 0.001,
lifeMaxRatio: 2,
enable: true
}

View File

@@ -21,7 +21,7 @@
#### :white_small_square: Data calculation and scores count
1. Seed uploaders calculate the upload volume of `* %(salesGlobalConfig.uploader.value.Ur).2f`
1. Seed uploaders calculate the upload volume of `* %(salesGlobalConfig.uploader.value.Ur).2f`, and calculate the upload scores of `* %(scoreConfig.action.seedUpDownload.uploaderRatio).2f`.
1. Other users calculate the normal upload and download amount.
1. All users of all the seed upload and download volume enjoy promotion bonus, in case of global promotion, they enjoy the overall promotion bonus.
1. VIP users can enjoy additional bonuses for uploading and downloading as well as seeding scores. For details, please refer to [VIP Rights Rules Detail](/about/manual/vipRules)。

View File

@@ -21,7 +21,7 @@
#### :white_small_square: 流量計算與積分統計
1. 種子釋出者按 `%(salesGlobalConfig.uploader.value.Ur).2f` 倍的上傳量計算。
1. 種子釋出者按 `%(salesGlobalConfig.uploader.value.Ur).2f` 倍的上傳量計算,並獲得 `%(scoreConfig.action.seedUpDownload.uploaderRatio).2f` 倍的上傳量積分
1. 分流者按正常上傳下載量計算。
1. 所有用戶所有種子上傳下載量享有促銷加成,如遇全局促銷則享有全局促銷加成。
1. VIP 用戶的上傳下載量以及做種積分享有額外的加成,詳情請參考 [VIP 用戶者權益細則](/about/manual/vipRules)。

View File

@@ -21,7 +21,7 @@
#### :white_small_square: 流量计算与积分统计
1. 种子发布者按 `%(salesGlobalConfig.uploader.value.Ur).2f` 倍的上传量计算。
1. 种子发布者按 `%(salesGlobalConfig.uploader.value.Ur).2f` 倍的上传量计算,并获得 `%(scoreConfig.action.seedUpDownload.uploaderRatio).2f` 倍的上传量积分
1. 分流者按正常上传下载量计算。
1. 所有用户所有种子上传下载量享有促销加成,如遇全局促销则享有全局促销加成。
1. VIP 用户的上传下载量以及做种积分享有额外的加成,详情请参考 [VIP 用户权益细则](/about/manual/vipRules)。

View File

@@ -25,6 +25,7 @@
none vip user get uploaded scores: 2 * 1 * 10 = 20, downloaded scores: 2 * 0.5 * 15 = 15.
vip user get uploaded scores: 20 * 1.5 = 30, downloaded scores: 15 * 1.5 = 22.5.
```
* Seed uploaders calculate the upload scores of `* %(scoreConfig.action.seedUpDownload.uploaderRatio).2f`.
* In the seeding state, the seeding scores will be get from the seeding time. For every seed, `%(scoreConfig.action.seedTimed.timedValue).2f` scores per `%(scoreConfig.action.seedTimed.additionTime_str)s`, vip user extra addition ratio is `%(scoreConfig.action.seedTimed.vipRatio).2f`.
* Scores got for the above two items, will get extra addition based on the seed life and seeding users, <mark>And two kinds of addition are available at the same time</mark>.
```javascript
@@ -33,7 +34,7 @@
Coefficient is: %(scoreConfig.action.seedSeederAndLife.seederCoefficient).2f
Seecer count less than: %(scoreConfig.action.seedSeederAndLife.seederCount)d
For 1 seeding user, the extra addition ratio is: 3, [for 2 is 2.8], [for 3 is 2.6], [for 4 is 2.4], [for 5 is 2.2], [for 6 is 2.0], [for 7 is 1.8], [for 8 is 1.6], [for 9 is 1.4], [for 10 is 1.2], [more than 10 is 1, same as no extra addition].
For 1 seeding user, the extra addition ratio is: 2, [for 2 is 1.9], [for 3 is 1.8], [for 4 is 1.7], [for 5 is 1.6], [for 6 is 1.5], [for 7 is 1.4], [for 8 is 1.3], [for 9 is 1.2], [for 10 is 1.1], [more than 10 is 1, same as no extra addition].
```
```javascript
With seed life:
@@ -42,7 +43,7 @@
Max ratio is: %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f
The basic ratio is %(scoreConfig.action.seedSeederAndLife.lifeBasicRatio).2f, increase %(scoreConfig.action.seedSeederAndLife.lifeCoefficientOfDay).3f every day.
For 10 days life ratio is 1.02, [100 days is 1.2], [200 days is 1.4] etc, the max ratio is %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f.
For 10 days life ratio is 1.01, [100 days is 1.1], [200 days is 1.2] etc, the max ratio is %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f.
```
* At the end of each month, the system will award scores to users who have successfully sent invitations. the score number limit is the percentage `%(scoreConfig.transferToInviter.transRatio)f` of the monthly got of the invited users, the current award function enable status is
```javascript

View File

@@ -25,6 +25,7 @@
Vip 使用者獲得上傳積分: 2 * 1 * 10 = 20, 下載積分: 2 * 0.5 * 15 = 15
Vip 使用者獲得上傳積分: 20 * 1.5 = 30, 下載積分: 15 * 1.5 = 22.5
```
* 種子發布者按 `%(scoreConfig.action.seedUpDownload.uploaderRatio).2f` 倍計算上傳量積分。
* 在做種狀態下,將會獲得由保種時間帶來的保種積分, 每個種子每 `%(scoreConfig.action.seedTimed.additionTime_str)s` 獲得 `%(scoreConfig.action.seedTimed.timedValue).2f` 積分Vip 使用者額外加成係數為 `%(scoreConfig.action.seedTimed.vipRatio).2f`
* 對於上述兩項獲得的積分, 還會根據種子的生命期和保種人數獲得額外的再次加成,<mark>而且兩種加成疊加生效</mark>。
```javascript
@@ -33,7 +34,7 @@
加成係數: %(scoreConfig.action.seedSeederAndLife.seederCoefficient).2f
最多保種人數: %(scoreConfig.action.seedSeederAndLife.seederCount)d
如果只有 1 個保種使用者: 加成係數為 2, [2 使用者為 2.8], [3 使用者為 2.6], [4 使用者為 2.4], [5 使用者為 2.2], [6 使用者為 2.0], [7 使用者為 1.8], [8 使用者為 1.6], [9 使用者為 1.4], [10 使用者為 1.2], [超過 10 使用者為 1, 相當於沒有加成]
如果只有 1 個保種使用者: 加成係數為 2, [2 使用者為 1.9], [3 使用者為 1.8], [4 使用者為 1.7], [5 使用者為 1.6], [6 使用者為 1.5], [7 使用者為 1.4], [8 使用者為 1.3], [9 使用者為 1.2], [10 使用者為 1.1], [超過 10 使用者為 1, 相當於沒有加成]
```
```javascript
種子生命加成:
@@ -42,7 +43,7 @@
最大加成係數: %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f
加成基礎係數為 %(scoreConfig.action.seedSeederAndLife.lifeBasicRatio).2f, 根據種子生命每天增加 %(scoreConfig.action.seedSeederAndLife.lifeCoefficientOfDay).3f
如果種子生命(釋出時間) 10 則加成係數為 1.02, [100 天是 1.2], [200 天是 1.4], 以此類推最大加成係數為 %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f
如果種子生命(釋出時間) 10 則加成係數為 1.01, [100 天是 1.1], [200 天是 1.2], 以此類推最大加成係數為 %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f
```
* 系統在每個月底會對成功發送過邀請函的用戶進行積分獎勵,獎勵額度為受邀請用戶當月的進帳積分的 `%(scoreConfig.transferToInviter.transRatio)f` 倍,目前該獎勵功能開關狀態為:
```javascript

View File

@@ -25,6 +25,7 @@
Vip 用户获得上传积分: 2 * 1 * 10 = 20, 下载积分: 2 * 0.5 * 15 = 15
Vip 用户获得上传积分: 20 * 1.5 = 30, 下载积分: 15 * 1.5 = 22.5
```
* 种子发布者按 `%(scoreConfig.action.seedUpDownload.uploaderRatio).2f` 倍计算上传量积分。
* 在做种状态下,将会获得由保种时间带来的保种积分, 每个种子每 `%(scoreConfig.action.seedTimed.additionTime_str)s` 获得 `%(scoreConfig.action.seedTimed.timedValue).2f` 积分Vip 用户额外加成系数为 `%(scoreConfig.action.seedTimed.vipRatio).2f`
* 对于上述两项获得的积分, 还会根据种子的生命期和保种人数获得额外的再次加成,<mark>而且两种加成叠加生效</mark>。
```javascript
@@ -33,7 +34,7 @@
加成系数: %(scoreConfig.action.seedSeederAndLife.seederCoefficient).2f
最多保种人数: %(scoreConfig.action.seedSeederAndLife.seederCount)d
如果只有 1 个保种用户: 加成系数为 3, [2 用户为 2.8], [3 用户为 2.6], [4 用户为 2.4], [5 用户为 2.2], [6 用户为 2.0], [7 用户为 1.8], [8 用户为 1.6], [9 用户为 1.4], [10 用户为 1.2], [超过 10 用户为 1, 相当于没有加成]
如果只有 1 个保种用户: 加成系数为 3, [2 用户为 1.9], [3 用户为 1.8], [4 用户为 1.7], [5 用户为 1.6], [6 用户为 1.5], [7 用户为 1.4], [8 用户为 1.3], [9 用户为 1.2], [10 用户为 1.1], [超过 10 用户为 1, 相当于没有加成]
```
```javascript
种子生命加成:
@@ -42,7 +43,7 @@
最大加成系数: %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f
加成基础系数为 %(scoreConfig.action.seedSeederAndLife.lifeBasicRatio).2f, 根据种子生命每天增加 %(scoreConfig.action.seedSeederAndLife.lifeCoefficientOfDay).3f
如果种子生命(发布时间) 10 则加成系数为 1.02, [100 天是 1.2], [200 天是 1.4], 以此类推最大加成系数为 %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f
如果种子生命(发布时间) 10 则加成系数为 1.01, [100 天是 1.1], [200 天是 1.2], 以此类推最大加成系数为 %(scoreConfig.action.seedSeederAndLife.lifeMaxRatio).2f
```
* 系统在每个月底会对成功发送过邀请函的用户进行积分奖励,奖励额度为受邀请用户当月的进帐积分的 `%(scoreConfig.transferToInviter.transRatio)f` 倍,目前该奖励功能开关状态为:
```javascript

View File

@@ -586,9 +586,15 @@ exports.announce = function (req, res) {
var sp = {};
if (curru > 0) {
sp.peer_uspeed = Math.round(curru / (Date.now() - req.currentPeer.last_announce_at) * 1000);
sp.peer_cuspeed = Math.round(curru / (Date.now() - req.currentPeer.last_announce_at) * 1000);
} else {
sp.peer_cuspeed = 0;
}
if (currd > 0) {
sp.peer_dspeed = Math.round(currd / (Date.now() - req.currentPeer.last_announce_at) * 1000);
sp.peer_cdspeed = Math.round(currd / (Date.now() - req.currentPeer.last_announce_at) * 1000);
} else {
sp.peer_cdspeed = 0;
}
req.currentPeer.update({
$set: sp
@@ -615,6 +621,10 @@ exports.announce = function (req, res) {
}
var upScore = curru / action.perlSize;
uploadScore = upUnitScore * action.uploadValue * upScore;
//uploader addition
if (req.passkeyuser._id.equals(req.torrent.user._id)) {
uploadScore = uploadScore * action.uploaderRatio;
}
}
if (currd > 0 && action.downloadEnable) {
@@ -692,6 +702,13 @@ exports.announce = function (req, res) {
}
};
dataLog.announceLog(req.passkeyuser, req.torrent, logData);
} else {
req.currentPeer.update({
$set: {
peer_cuspeed: 0,
peer_cdspeed: 0
}
}).exec();
}
}

View File

@@ -24,6 +24,10 @@
VALUE_SELECT_ALL: 'Select All',
BTN_REMOVE: 'Remove',
BTN_CONTINUE: 'Continue',
VALUE_TRUE: 'true',
VALUE_FALSE: 'false',
VALUE_ON: 'on',
VALUE_OFF: 'off',
//Support
SUPPORT_GROUP_NAME_DESC: 'Management group',
@@ -1072,9 +1076,16 @@
//user score
SCORE: {
CURRENT_SCORE: 'Current score:',
INCOME_ESTIMATE: 'My scores income estimate',
HOW_TO_GET_LEVEL: 'How to count user level?',
HOW_TO_GET_SCORE: 'How to get score number?'
},
CURR_LEECHING_TORRENTS: 'Current downloading torrents: `{{count_leech}}`.',
CURR_SEEDING_TORRENTS: 'Current seeding torrents: `{{count_seed}}`.',
CURR_VIP_STATE: 'Current VIP status: `{{vip_status | translate}}`.',
CURR_UP_TOTAL_SPEED: 'Current total upload speed is: `{{up_speed | byteFmt: 2}}`.',
CURR_DOWN_TOTAL_SPEED: 'Current total download speed is: `{{down_speed | byteFmt: 2}}`.',
CURR_SCORE_INCOME_HOURS: 'Current estimated hourly earnings of `{{score_hour}}` scores, If you dont understand how to calculate the points, please refer to [{{"ABOUT.MENU_ABOUT_MANUAL_SCORE_RULES" | translate}}](/about/manual/scoreRules).',
EXCHANGE_INVITATION: 'Exchange an invitation ({{score}} scores)',
EXCHANGE_INVITATION_CONFIRM_OK: 'Exchange',
EXCHANGE_INVITATION_CONFIRM_CANCEL: 'Cancel',

View File

@@ -24,6 +24,10 @@
VALUE_SELECT_ALL: '全選',
BTN_REMOVE: '刪除',
BTN_CONTINUE: '繼續',
VALUE_TRUE: '是',
VALUE_FALSE: '否',
VALUE_ON: '開',
VALUE_OFF: '關',
//Support
SUPPORT_GROUP_NAME_DESC: '管理組',
@@ -1072,9 +1076,16 @@
//user score
SCORE: {
CURRENT_SCORE: '當前積分:',
INCOME_ESTIMATE: '我的積分收入預估',
HOW_TO_GET_LEVEL: '怎麼計算用戶級別?',
HOW_TO_GET_SCORE: '怎麼取得用戶積分?'
},
CURR_LEECHING_TORRENTS: '當前正在下載的種子:`{{count_leech}}`個。',
CURR_SEEDING_TORRENTS: '當前正在做種的種子:`{{count_seed}}`個。',
CURR_VIP_STATE: '當前 VIP 身份狀態:`{{vip_status | translate}}`。',
CURR_UP_TOTAL_SPEED: '當前上傳總速度為:`{{up_speed | byteFmt: 2}}`。',
CURR_DOWN_TOTAL_SPEED: '當前下載總速度為:`{{down_speed | byteFmt: 2}}`。',
CURR_SCORE_INCOME_HOURS: '當前預計每小時獲得 `{{score_hour}}` 積分,如果你不明白積分怎麼計算,請參閱 [{{"ABOUT.MENU_ABOUT_MANUAL_SCORE_RULES" | translate}}](/about/manual/scoreRules)。',
EXCHANGE_INVITATION: '兌換一個邀請 ({{score}} 積分)',
EXCHANGE_INVITATION_CONFIRM_OK: '兌換',
EXCHANGE_INVITATION_CONFIRM_CANCEL: '取消',

View File

@@ -24,6 +24,10 @@
VALUE_SELECT_ALL: '全选',
BTN_REMOVE: '删除',
BTN_CONTINUE: '继续',
VALUE_TRUE: '是',
VALUE_FALSE: '否',
VALUE_ON: '开',
VALUE_OFF: '关',
//Support
SUPPORT_GROUP_NAME_DESC: '管理组',
@@ -1072,9 +1076,16 @@
//user score
SCORE: {
CURRENT_SCORE: '当前积分:',
INCOME_ESTIMATE: '我的积分收入预估',
HOW_TO_GET_LEVEL: '怎么计算用户级别?',
HOW_TO_GET_SCORE: '怎么取得用户积分?'
},
CURR_LEECHING_TORRENTS: '当前正在下载的种子:`{{count_leech}}`个。',
CURR_SEEDING_TORRENTS: '当前正在做种的种子:`{{count_seed}}`个。',
CURR_VIP_STATE: '当前 VIP 身份状态:`{{vip_status | translate}}`。',
CURR_UP_TOTAL_SPEED: '当前上传总速度为:`{{up_speed | byteFmt: 2}}`。',
CURR_DOWN_TOTAL_SPEED: '当前下载总速度为:`{{down_speed | byteFmt: 2}}`。',
CURR_SCORE_INCOME_HOURS: '当前预计每小时获得 `{{score_hour}}` 积分,如果你不明白积分怎么计算,请参阅 [{{"ABOUT.MENU_ABOUT_MANUAL_SCORE_RULES" | translate}}](/about/manual/scoreRules)。',
EXCHANGE_INVITATION: '兑换一个邀请 ({{score}} 积分)',
EXCHANGE_INVITATION_CONFIRM_OK: '兑换',
EXCHANGE_INVITATION_CONFIRM_CANCEL: '取消',

View File

@@ -11,7 +11,7 @@
function PeersService($resource, CacheFactory) {
var peersCache = CacheFactory.get('peersCache') || CacheFactory.createCache('peersCache');
var Torrents = $resource('', {}, {
var Peers = $resource('', {}, {
getMySeedingList: {
method: 'GET',
url: '/api/my/seeding',
@@ -30,6 +30,12 @@
isArray: true,
cache: peersCache
},
getMyPeers: {
method: 'GET',
url: '/api/my/peers',
isArray: true,
cache: peersCache
},
getUserSeedingList: {
method: 'GET',
url: '/api/users/:userId/seeding',
@@ -59,6 +65,6 @@
}
});
return Torrents;
return Peers;
}
}());

View File

@@ -107,3 +107,27 @@ exports.getMyWarning = function (req, res) {
}
});
};
/**
* getMyPeers
* @param req
* @param res
*/
exports.getMyPeers = function (req, res) {
Peer.find({
user: req.user._id,
last_announce_at: {$gt: Date.now() - announceConfig.announceInterval - announceConfig.announceIdleTime}
}).populate({
path: 'torrent',
select: populateStrings.populate_torrent_string
})
.exec(function (err, peers) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(peers);
}
});
};

View File

@@ -51,6 +51,14 @@ var PeerSchema = new Schema({
type: Number,
default: 0
},
peer_cuspeed: {
type: Number,
default: 0
},
peer_cdspeed: {
type: Number,
default: 0
},
peer_ratio: {
type: Number,
default: 0

View File

@@ -53,6 +53,7 @@ exports.invokeRolesPolicies = function () {
{resources: '/api/my/seeding', permissions: '*'},
{resources: '/api/my/downloading', permissions: '*'},
{resources: '/api/my/warning', permissions: '*'},
{resources: '/api/my/peers', permissions: '*'},
{resources: '/api/torrents/siteInfo', permissions: ['get']},
{resources: '/api/completes/:completeId', permissions: ['put']}
@@ -88,6 +89,7 @@ exports.invokeRolesPolicies = function () {
{resources: '/api/my/seeding', permissions: ['get']},
{resources: '/api/my/downloading', permissions: ['get']},
{resources: '/api/my/warning', permissions: ['get']},
{resources: '/api/my/peers', permissions: ['get']},
{resources: '/api/torrents/siteInfo', permissions: ['get']},
{resources: '/api/completes/:completeId', permissions: ['put']}

View File

@@ -18,4 +18,7 @@ module.exports = function (app) {
app.route('/api/my/warning').all(torrentsPolicy.isAllowed)
.get(peers.getMyWarning);
app.route('/api/my/peers').all(torrentsPolicy.isAllowed)
.get(peers.getMyPeers);
};

View File

@@ -6,10 +6,12 @@
.controller('ScoreController', ScoreController);
ScoreController.$inject = ['$rootScope', '$scope', '$state', '$translate', '$timeout', 'Authentication', '$window', 'ScoreLevelService', 'getStorageLangService',
'MeanTorrentConfig', 'ModalConfirmService', 'NotifycationService', 'InvitationsService', '$templateRequest', 'marked', '$filter'];
'MeanTorrentConfig', 'ModalConfirmService', 'NotifycationService', 'InvitationsService', '$templateRequest', 'marked', '$filter', 'PeersService', 'moment',
'DebugConsoleService'];
function ScoreController($rootScope, $scope, $state, $translate, $timeout, Authentication, $window, ScoreLevelService, getStorageLangService, MeanTorrentConfig,
ModalConfirmService, NotifycationService, InvitationsService, $templateRequest, marked, $filter) {
ModalConfirmService, NotifycationService, InvitationsService, $templateRequest, marked, $filter, PeersService, moment,
mtDebug) {
var vm = this;
vm.scoreConfig = MeanTorrentConfig.meanTorrentConfig.score;
vm.inviteConfig = MeanTorrentConfig.meanTorrentConfig.invite;
@@ -111,7 +113,10 @@
closeButtonText: $translate.instant('EXCHANGE_INVITATION_CONFIRM_CANCEL'),
actionButtonText: $translate.instant('EXCHANGE_INVITATION_CONFIRM_OK'),
headerText: $translate.instant('EXCHANGE_INVITATION_CONFIRM_HEADER_TEXT'),
bodyText: $translate.instant('EXCHANGE_INVITATION_CONFIRM_BODY_TEXT', {score: vm.inviteConfig.scoreExchange, hours: vm.inviteConfig.expires_str})
bodyText: $translate.instant('EXCHANGE_INVITATION_CONFIRM_BODY_TEXT', {
score: vm.inviteConfig.scoreExchange,
hours: vm.inviteConfig.expires_str
})
};
ModalConfirmService.showModal({}, modalOptions)
@@ -138,5 +143,212 @@
}
});
};
/**
* getMyPeers
*/
vm.getMyPeers = function () {
PeersService.getMyPeers(function (items) {
vm.myPeers = items;
mtDebug.info(items);
vm.countByStatus = $filter('countBy')(vm.myPeers, 'peer_status');
vm.groupByStatus = $filter('groupBy')(vm.myPeers, 'peer_status');
vm.sumCUSpeed = vm.myPeers.map(function (x) {
return x.peer_cuspeed;
}).reduce(function (a, b) {
return a + b;
});
vm.sumCDSpeed = vm.myPeers.map(function (x) {
return x.peer_cdspeed;
}).reduce(function (a, b) {
return a + b;
});
});
};
/**
* getMarkedCurrDownloadingString
* @returns {*}
*/
vm.getMarkedCurrDownloadingString = function () {
if (vm.countByStatus) {
var tmp = $translate.instant('CURR_LEECHING_TORRENTS', {count_leech: vm.countByStatus.leecher || 0});
return marked(tmp, {sanitize: false});
}
};
/**
* getMarkedCurrSeedingString
* @returns {*}
*/
vm.getMarkedCurrSeedingString = function () {
if (vm.countByStatus) {
var tmp = $translate.instant('CURR_SEEDING_TORRENTS', {count_seed: vm.countByStatus.seeder || 0});
return marked(tmp, {sanitize: false});
}
};
/**
* getMarkedVipStatusString
* @returns {*}
*/
vm.getMarkedVipStatusString = function () {
var tmp = $translate.instant('CURR_VIP_STATE', {vip_status: vm.user.isVip ? 'VALUE_TRUE' : 'VALUE_FALSE'});
return marked(tmp, {sanitize: false});
};
/**
* getMarkedCurrUpSpeedString
* @returns {*}
*/
vm.getMarkedCurrUpSpeedString = function () {
var tmp = $translate.instant('CURR_UP_TOTAL_SPEED', {up_speed: vm.sumCUSpeed});
return marked(tmp, {sanitize: false});
};
/**
* getMarkedCurrDownSpeedString
* @returns {*}
*/
vm.getMarkedCurrDownSpeedString = function () {
var tmp = $translate.instant('CURR_DOWN_TOTAL_SPEED', {down_speed: vm.sumCDSpeed});
return marked(tmp, {sanitize: false});
};
/**
* getMarkedCurrScoreString
* @returns {*}
*/
vm.getMarkedCurrScoreString = function () {
var timedScore = getTimedScore();
var speedScore = getSpeedScore();
var seedScoreTotal = timedScore + speedScore;
seedScoreTotal = Math.round(seedScoreTotal * 100) / 100;
var tmp = $translate.instant('CURR_SCORE_INCOME_HOURS', {score_hour: seedScoreTotal});
return marked(tmp, {sanitize: false});
};
/**
* getTimedScore
* @returns {number}
*/
function getTimedScore() {
var timedScore = 0;
var action = vm.scoreConfig.action.seedTimed;
var slAction = vm.scoreConfig.action.seedSeederAndLife;
if (action.enable && vm.groupByStatus) {
angular.forEach(vm.groupByStatus.seeder, function (seed) {
if (seed.torrent.torrent_status === 'reviewed') {
var seedUnit = (60 * 60 * 1000) / action.additionTime;
var seedScore = seedUnit * action.timedValue;
if (seedScore > 0) {
//vip addition
if (action.vipRatio && vm.user.isVip) {
seedScore = seedScore * action.vipRatio;
}
if (slAction.enable) {
//torrent seeders count addition
if (seed.torrent.torrent_seeds <= slAction.seederCount) {
var seederUnit = slAction.seederBasicRatio + slAction.seederCoefficient * (slAction.seederCount - seed.torrent.torrent_seeds + 1);
seedScore = seedScore * seederUnit;
}
//torrent life addition
var life = moment(Date.now()) - moment(seed.torrent.createdat);
var days = life / (60 * 60 * 1000 * 24);
var lifeUnit = slAction.lifeBasicRatio + slAction.lifeCoefficientOfDay * days;
lifeUnit = lifeUnit > slAction.lifeMaxRatio ? slAction.lifeMaxRatio : lifeUnit;
seedScore = seedScore * lifeUnit;
}
}
timedScore = timedScore + seedScore;
}
});
}
return timedScore;
}
/**
* getSpeedScore
* @returns {number}
*/
function getSpeedScore() {
var totalScore = 0;
var action = vm.scoreConfig.action.seedUpDownload;
var slAction = vm.scoreConfig.action.seedSeederAndLife;
if (action.enable && vm.myPeers) {
angular.forEach(vm.myPeers, function (peer) {
var udScore = 0;
var upUnitScore = 1;
var downUnitScore = 1;
var seederUnit = 1;
var lifeUnit = 1;
var usize = peer.peer_cuspeed * 60 * 60;
var dsize = peer.peer_cdspeed * 60 * 60;
var uploadScore = 0;
var downloadScore = 0;
if (usize > 0 && action.uploadEnable) {
if (peer.torrent.torrent_size > action.additionSize) {
upUnitScore = Math.sqrt(peer.torrent.torrent_size / action.additionSize);
}
var upScore = usize / action.perlSize;
uploadScore = upUnitScore * action.uploadValue * upScore;
//uploader addition
if (vm.user._id == peer.torrent.user) {
uploadScore = uploadScore * action.uploaderRatio;
}
}
if (dsize > 0 && action.downloadEnable) {
if (peer.torrent.torrent_size > action.additionSize) {
downUnitScore = Math.sqrt(peer.torrent.torrent_size / action.additionSize);
}
var downScore = dsize / action.perlSize;
downloadScore = downUnitScore * action.downloadValue * downScore;
}
udScore = uploadScore + downloadScore;
if (udScore > 0) {
//vip addition
if (action.vipRatio && vm.user.isVip) {
udScore = udScore * action.vipRatio;
}
if (slAction.enable) {
//torrent seeders count addition
if (peer.torrent.torrent_seeds <= slAction.seederCount) {
seederUnit = slAction.seederBasicRatio + slAction.seederCoefficient * (slAction.seederCount - peer.torrent.torrent_seeds + 1);
udScore = udScore * seederUnit;
}
//torrent life addition
var life = moment(Date.now()) - moment(peer.torrent.createdat);
var days = life / (60 * 60 * 1000 * 24);
lifeUnit = slAction.lifeBasicRatio + slAction.lifeCoefficientOfDay * days;
lifeUnit = lifeUnit > slAction.lifeMaxRatio ? slAction.lifeMaxRatio : lifeUnit;
udScore = udScore * lifeUnit;
}
}
totalScore = totalScore + udScore;
});
}
return totalScore;
}
}
}());

View File

@@ -44,4 +44,17 @@
height: 150px;
line-height: 0.8;
overflow-y: scroll;
}
}
.curr-score-info {
p {
margin-bottom: 0;
}
h5 {
line-height: 1.5;
margin: 0;
}
li {
line-height: 1.8;
}
}

View File

@@ -1,6 +1,6 @@
1. 用戶積分級別數學計算公式為: `sqrt(score number / %(scoreConfig.levelStep)s)`.
1. 級別`1` 需要積分累計: `1 * 1 * %(scoreConfig.levelStep)s`.
1. 級別`2` 需要積分累計: `2 * 2 * %(scoreConfig.levelStep)s`.
1. 級別`3` 需要積分累計: `3 * 3 * %(scoreConfig.levelStep)s`.
1. 級別`4` 需要積分累計: `4 * 4 * %(scoreConfig.levelStep)s`.
1. 級別`x` 需要積分累計: `x * x * %(scoreConfig.levelStep)s`.
1. 用戶積分級別數學計算公式為: `sqrt(score number / %(scoreConfig.levelStep)s)`
1. 級別`1` 需要積分累計: `1 * 1 * %(scoreConfig.levelStep)s`
1. 級別`2` 需要積分累計: `2 * 2 * %(scoreConfig.levelStep)s`
1. 級別`3` 需要積分累計: `3 * 3 * %(scoreConfig.levelStep)s`
1. 級別`4` 需要積分累計: `4 * 4 * %(scoreConfig.levelStep)s`
1. 級別`x` 需要積分累計: `x * x * %(scoreConfig.levelStep)s`

View File

@@ -1,6 +1,6 @@
1. 用户积分级别数学计算公式为: `sqrt(score number / %(scoreConfig.levelStep)s)`.
1. 级别`1` 需要积分累计: `1 * 1 * %(scoreConfig.levelStep)s`.
1. 级别`2` 需要积分累计: `2 * 2 * %(scoreConfig.levelStep)s`.
1. 级别`3` 需要积分累计: `3 * 3 * %(scoreConfig.levelStep)s`.
1. 级别`4` 需要积分累计: `4 * 4 * %(scoreConfig.levelStep)s`.
1. 级别`x` 需要积分累计: `x * x * %(scoreConfig.levelStep)s`.
1. 用户积分级别数学计算公式为: `sqrt(score number / %(scoreConfig.levelStep)s)`
1. 级别`1` 需要积分累计: `1 * 1 * %(scoreConfig.levelStep)s`
1. 级别`2` 需要积分累计: `2 * 2 * %(scoreConfig.levelStep)s`
1. 级别`3` 需要积分累计: `3 * 3 * %(scoreConfig.levelStep)s`
1. 级别`4` 需要积分累计: `4 * 4 * %(scoreConfig.levelStep)s`
1. 级别`x` 需要积分累计: `x * x * %(scoreConfig.levelStep)s`

View File

@@ -1,5 +1,5 @@
1. 系統提供多種獲取積分的方式, 像每日簽到, 社群活動, 系統任務等.
1. 儘可能多的下載和上傳量.
1. 上傳種子檔案並長時間的為其它用戶做種.
1. 在論壇積極回答用戶的問題.
1. 系統提供多種獲取積分的方式, 像每日簽到, 社群活動, 系統任務等
1. 儘可能多的下載和上傳量
1. 上傳種子檔案並長時間的為其它用戶做種
1. 在論壇積極回答用戶的問題
1. 其它更多...

View File

@@ -1,5 +1,5 @@
1. 系统提供多种获取积分的方式, 像每日签到, 社区活动, 系统任务等.
1. 尽可能多的下载和上传量.
1. 上传种子文件并长时间的其它用户做种.
1. 在论坛积极回答用户的问题.
1. 系统提供多种获取积分的方式, 像每日签到, 社区活动, 系统任务等
1. 尽可能多的下载和上传量
1. 上传种子文件并长时间的其它用户做种
1. 在论坛积极回答用户的问题
1. 其它更多...

View File

@@ -6,7 +6,7 @@
</div>
<div class="row margin-top-30">
<div class="col-sm-8 col-sm-offset-2">
<div class="col-md-8 col-md-offset-2">
<div>
<span>{{ vm.scoreLevelData.currLevelValue | number: 2 }}</span>
<span class="pull-right">{{ vm.scoreLevelData.nextLevelValue | number: 2 }}</span>
@@ -24,8 +24,8 @@
</div>
<div class="row margin-top-30" ng-show="vm.inviteConfig.openInvite">
<div class="col-sm-8 col-sm-offset-2 text-center">
<button class="btn btn-default" ng-disabled="vm.user.score < vm.inviteConfig.scoreExchange"
<div class="col-md-8 col-md-offset-2 text-center">
<button class="btn btn-success" ng-disabled="vm.user.score < vm.inviteConfig.scoreExchange"
translate="EXCHANGE_INVITATION" translate-values='{ score: vm.inviteConfig.scoreExchange}'
ng-click="vm.exchangeInvitation();">
</button>
@@ -33,25 +33,41 @@
</div>
<div class="row margin-top-30" ng-hide="vm.inviteConfig.openInvite">
<div class="col-sm-8 col-sm-offset-2 text-center">
<div class="col-md-8 col-md-offset-2 text-center">
<div class="alert alert-warning" role="alert">
<strong>{{ 'NOTE_CAPTION' | translate }}</strong> {{ 'INVITE_CLOSED' | translate }}
</div>
</div>
</div>
<div class="row margin-top-30 padding-top-30"
<div class="row margin-top-30" ng-init="vm.getMyPeers()">
<div class="col-md-8 col-md-offset-2 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.INCOME_ESTIMATE' | translate}}</legend>
<ul>
<li ng-bind-html="vm.getMarkedCurrDownloadingString()"></li>
<li ng-bind-html="vm.getMarkedCurrSeedingString()"></li>
<li ng-bind-html="vm.getMarkedVipStatusString()"></li>
<li ng-bind-html="vm.getMarkedCurrUpSpeedString()"></li>
<li ng-bind-html="vm.getMarkedCurrDownSpeedString()"></li>
</ul>
<div class="alert alert-warning">
<h5 ng-bind-html="vm.getMarkedCurrScoreString()"></h5>
</div>
</div>
</div>
<div class="row margin-top-30"
ng-init="vm.getTemplateScoreFileContent('/modules/users/client/templates/how-level-'+vm.lang+'.md')">
<div class="col-sm-8 col-sm-offset-2">
<legend class="small-legend" translate="SCORE.HOW_TO_GET_LEVEL"></legend>
<div class="col-md-8 col-md-offset-2 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.HOW_TO_GET_LEVEL' | translate}}</legend>
<span ng-bind-html="vm.getTemplateMarkedContent(vm.templateScoreFileContent)"></span>
</div>
</div>
<div class="row margin-top-30 margin-bottom-30"
ng-init="vm.getTemplateLevelFileContent('/modules/users/client/templates/how-score-'+vm.lang+'.md')">
<div class="col-sm-8 col-sm-offset-2">
<legend class="small-legend" translate="SCORE.HOW_TO_GET_SCORE"></legend>
<div class="col-md-8 col-md-offset-2 curr-score-info">
<legend class="small-legend"><i class="fa fa-caret-right"></i> {{'SCORE.HOW_TO_GET_SCORE' | translate}}</legend>
<span ng-bind-html="vm.getTemplateMarkedContent(vm.templateLevelFileContent)"></span>
</div>
</div>