Files
vic-server-mongo/src/jobs/mine.js
chaosBreaking cd7d093fc7 job
2019-10-15 14:21:46 +08:00

202 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const bunyan = require('bunyan');
const PrettyStream = require('bunyan-pretty-colors');
const path = require('path');
const fs = require('fs');
const prettyStdOut = new PrettyStream();
prettyStdOut.pipe(process.stdout);
if (!fs.existsSync('minelog')) {
fs.mkdirSync('minelog');
}
const logger = function (option) {
option = option || {};
return bunyan.createLogger({
name: "log",
src: false,
streams: [
{
level: 'info',
stream: prettyStdOut
},
{
level: 'info',
type: 'rotating-file',
path: path.join(option.root, option.file || 'info.log'),
period: '1d', // daily rotation
count: 365 // keep 30 days
}
]
});
};
const filename = 'minelog' + new Date().getFullYear() + new Date().getMonth() + new Date().getDate();
const mylog = logger(({ root: 'minelog', file: filename }));
const mongoose = require('mongoose');
const User = require('./src/modules/user/user.model');
const Fund = require('./src/modules/fund/fund.model');
const system = require('./src/modules/system/system.model');
const { createAction } = require('./src/modules/action/action.handler');
const tokenReleaseRate = 0.02;
const inviteReward = 2.5;
async function awardMine(user, fund) {
if (!user || !fund || fund.fundList.length === 0) return 0;
let sum = 0;
for (let i = 0, len = fund.fundList.length; i < len; ++i) {
const released = fund.releasedAmout || 0;
if (released === fund.releasedAmout) {
console.log('矿晶失效,开始标记');
await Fund.findByIdAndUpdate(fund.id, {
$set: {
[`fundList.${i}.status`]: 2 //标记失效
}
});
return 0;
}
sum += +fund.fundList[i].amount * tokenReleaseRate;
}
return sum.toFixed(2);
}
function awardInvite(user, fund) {
const follerNum = user.group.length || 0;
const hasAwardFoller = fund.option && fund.option.usedGroupReward / 10 || 0; // 求增量: 总额 - 已领取总额(fundSum)
const newFoller = follerNum - hasAwardFoller;
if (newFoller < 0) return 0;
// 挖矿奖励 = 充值金额奖励 + 社区奖励
return (newFoller * inviteReward).toFixed(2);
}
// fund.option.usedGroupReward : 已领取的社群奖励总额
const doReward = async (user, fund) => {
// 1.对于充值的fundList的每一项按照2%进行发放累加到asset.vic添加action类型为1
// 2.对于社团成员进行人头数目按照10vic/人进行奖励累加到asset.vic添加action类型为2
if (!user || !fund) return 0;
const rewardMine = await awardMine(user, fund);
// const rewardInvite = awardInvite(user, fund);
const rewardInvite = 0;
const reward = +rewardMine + rewardInvite;
console.log('挖矿奖励: ', rewardMine);
console.log('社群奖励: ', rewardInvite);
reward && await Fund.findByIdAndUpdate(fund.id, {
$inc: {
'asset.vic': reward,
'asset.usdt': rewardInvite, // 用来记录所有社群奖励总额
},
$set: {
'option.newFoller': rewardInvite / 5,
'option.usedGroupReward': rewardInvite, // 本次的奖励值累加到已领取团队奖励总和内
'lastMine': new Date().toISOString()
}
}).then(() => {
rewardMine > 0 && createAction(1, {
userId: user.id,
tokenType: 'vic',
amount: rewardMine,
remain: fund.asset
}).save();
rewardInvite > 0 && createAction(2, {
userId: user.id,
tokenType: 'vic',
amount: rewardInvite,
remain: fund.asset
}).save();
});
};
const mock = {
touch: () => {console.log('-----------------\n');},
done: () => {console.log('done');},
};
async function mine (job = mock, done = mock) {
//todo: 程序内检查是否可以执行,保证不会启动时错误的自动执行一次
mylog.info('[Schedule Job] 挖矿程序 开始定时计算作业...');
let currentIndex = await system.findOne({
key: 'userIndex4job'
}).exec();
currentIndex = currentIndex.value;
if (typeof currentIndex !== 'number') {
currentIndex = 0;
await new system({
key: 'userIndex4job',
value: currentIndex
}).save();
}
let allFundNum = await Fund.countDocuments();
await system.updateOne({
key: 'restFundNum',
}, {
value: allFundNum
});
// 批量更新,每次十个
for (; currentIndex < allFundNum;) {
const userFundList = await Fund.find().sort('_id').limit(10).skip(currentIndex);
typeof job.touch === 'function' && job.touch();
if (!userFundList || !Array.isArray(userFundList)) return 0;
for (let i = 0, len = userFundList.length; i < len; ++i) {
const fund = userFundList[i]; // 一条数据库fund表记录
// if (fund.lastMine && new Date(fund.lastMine).getDate() === new Date().getDate()) {
// mylog.info('已经计算过...跳过');
// continue;
// }
const user = await User.findById(fund.userId).exec();
console.log('No. ', currentIndex, ' - ', i);
mylog.info('开始更新用户: ', user.id);
await doReward(user, fund);
mylog.info('用户: ', user.id, '更新完毕\n');
typeof job.touch === 'function' && job.touch();
await system.updateOne({ key: 'userIndex4job' }, {
$set: {
value: currentIndex
}
});
await system.updateOne({ key: 'restFundNum' }, {
$inc: {
value: -1
}
});
}
currentIndex += 10;
}
mylog.info('收益计算分配完成');
await system.findOneAndUpdate({
key: 'userIndex4job'
}, { $set: { value: 0 } }).exec();
await system.findOneAndUpdate({
key: 'mineCount',
}, {
$inc: {
value: 1
}
}, { upsert: true });
await system.findOneAndUpdate({
key: 'lastMine',
}, {
value: new Date().toISOString()
}, { upsert: true });
typeof done === 'function' && done('收益计算分配完成');
process.exit();
}
const start = async () => {
const SysConfig = require('./configSec');
mongoose.set('useCreateIndex', true);
const { DB_USER_NAME, DB_PASSWD, DB_HOST, DB_PORT, DB_NAME } = SysConfig;
const db = mongoose.connection;
db.on('error', mylog.error);
db.once('open', function() {
mylog.info('数据库连接成功...');
});
mylog.info('开始连接数据库...');
await mongoose.connect(`mongodb://${DB_USER_NAME}:${DB_PASSWD}@${DB_HOST}:${DB_PORT}/${DB_NAME}`, {
useNewUrlParser: true,
bufferMaxEntries: 0,
autoReconnect: true,
useFindAndModify: false,
useUnifiedTopology: true
});
mine();
};
start();