'use strict'; global.mylog = {}; global.mylog.info = console.log; global.mylog.error = console.log; 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.01; 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('收益计算分配完成'); typeof done === 'function' && done('收益计算分配完成'); } async function confirm (job = mock, done = mock) { mylog.info('[Schedule Job] 矿晶确认程序开始执行......'); const unconfirmed = await Fund.find({ 'fundList.status': 0 }); mylog.info('共有' + unconfirmed.length + '用户需要确认'); unconfirmed.forEach(async (fund) => { const len = fund.fundList.length || 0; let acc = 0; for (let i = 0; i < len; ++i) { const fundItem = fund.fundList[i]; if (fundItem && fundItem.status === 0) { ++acc; await Fund.findByIdAndUpdate(fund.id, { $set: { [`fundList.${i}.status`]: 1 // 确认激活 } }); } } mylog.info(`用户${fund.userId} 共更新${acc}条`); job.touch(); }); return typeof done === 'function' && done('矿晶确认完成'); } 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(); module.exports = { Fund, User };