Compare commits
2 Commits
4dcbe38309
...
702fa937e8
| Author | SHA1 | Date |
|---|---|---|
|
|
702fa937e8 | |
|
|
8b8d1f7d16 |
|
|
@ -136,11 +136,11 @@ export class BatchMiningService {
|
|||
/**
|
||||
* 预览批量补发(计算但不执行)
|
||||
*
|
||||
* 简化计算逻辑:
|
||||
* - 每日产出 = 每秒分配量 × 86400
|
||||
* - 用户收益 = (用户算力 / 全网算力) × 每日产出 × 天数
|
||||
* - 用户占全网70%,所以全网算力 = 用户算力 / 0.7
|
||||
* - 公式验证: (1000000/365/2)*70%*74 = 70958.90411
|
||||
* 分阶段计算逻辑:
|
||||
* - 阶段1(3天):只有批次1在挖,批次1独占全部产出
|
||||
* - 阶段2(2天):批次1+2一起挖,按算力比例分
|
||||
* - 阶段3(1天):批次1+2+3一起挖,按算力比例分
|
||||
* - 阶段4(剩余天数):所有批次一起挖到今天
|
||||
*/
|
||||
async preview(items: BatchMiningItem[]): Promise<BatchMiningPreviewResult> {
|
||||
this.logger.log(`[preview] 开始预览批量补发, 共 ${items.length} 条数据`);
|
||||
|
|
@ -170,8 +170,7 @@ export class BatchMiningService {
|
|||
}
|
||||
|
||||
const secondDistribution = config.secondDistribution.value;
|
||||
const dailyDistribution = secondDistribution.times(SECONDS_PER_DAY);
|
||||
this.logger.log(`[preview] 每秒分配量: ${secondDistribution.toString()}, 每日分配量: ${dailyDistribution.toFixed(6)}`);
|
||||
this.logger.log(`[preview] 每秒分配量: ${secondDistribution.toString()}`);
|
||||
|
||||
// 按批次分组并排序
|
||||
const batchGroups = this.groupByBatch(items);
|
||||
|
|
@ -190,40 +189,61 @@ export class BatchMiningService {
|
|||
this.logger.log(`[preview] 批次${batchNum}算力: ${batchTotal.toFixed(2)}`);
|
||||
}
|
||||
|
||||
// 计算用户总算力和全网算力
|
||||
let totalUserContribution = new Decimal(0);
|
||||
for (const contribution of batchContributions.values()) {
|
||||
totalUserContribution = totalUserContribution.plus(contribution);
|
||||
}
|
||||
// 用户只占全网的70%(30%是系统、运营、层级、团队),所以全网算力 = 用户算力 / 0.7
|
||||
const networkContribution = totalUserContribution.dividedBy(USER_NETWORK_RATIO);
|
||||
this.logger.log(`[preview] 用户总算力: ${totalUserContribution.toFixed(2)}, 全网算力(用户占70%): ${networkContribution.toFixed(2)}`);
|
||||
|
||||
// 获取最大总挖矿天数
|
||||
let maxTotalMiningDays = 0;
|
||||
// 计算每个用户的算力
|
||||
const userContributions = new Map<string, Decimal>();
|
||||
for (const item of items) {
|
||||
if (item.totalMiningDays && item.totalMiningDays > maxTotalMiningDays) {
|
||||
maxTotalMiningDays = item.totalMiningDays;
|
||||
userContributions.set(item.accountSequence, this.calculateUserContribution(item.treeCount));
|
||||
}
|
||||
}
|
||||
this.logger.log(`[preview] 最大总挖矿天数: ${maxTotalMiningDays}`);
|
||||
|
||||
// 简化计算:所有用户按各自的总挖矿天数计算收益
|
||||
// 用户收益 = (用户算力 / 全网算力) × 每日产出 × 天数
|
||||
// 定义挖矿阶段
|
||||
// 阶段1: 批次1独挖3天
|
||||
// 阶段2: 批次1+2共挖2天
|
||||
// 阶段3: 批次1+2+3共挖1天
|
||||
// 阶段4: 所有批次共挖(剩余天数)
|
||||
const phases = this.buildMiningPhases(items, sortedBatches, batchContributions);
|
||||
this.logger.log(`[preview] 挖矿阶段: ${JSON.stringify(phases.map(p => ({
|
||||
phase: p.phaseNumber,
|
||||
days: p.daysInPhase,
|
||||
batches: p.participatingBatches,
|
||||
networkContribution: p.networkContribution.toFixed(2)
|
||||
})))}`);
|
||||
|
||||
// 计算每个用户在各阶段的收益
|
||||
const userAmounts = new Map<string, Decimal>();
|
||||
for (const item of items) {
|
||||
const userContribution = this.calculateUserContribution(item.treeCount);
|
||||
const ratio = userContribution.dividedBy(networkContribution);
|
||||
const days = item.totalMiningDays || maxTotalMiningDays;
|
||||
const amount = dailyDistribution.times(ratio).times(days);
|
||||
userAmounts.set(item.accountSequence, amount);
|
||||
this.logger.debug(`[preview] 用户 ${item.accountSequence}: 算力=${userContribution.toFixed(2)}, 占比=${ratio.toFixed(6)}, 天数=${days}, 金额=${amount.toFixed(8)}`);
|
||||
userAmounts.set(item.accountSequence, new Decimal(0));
|
||||
}
|
||||
|
||||
for (const phase of phases) {
|
||||
const dailyDistribution = secondDistribution.times(SECONDS_PER_DAY);
|
||||
const phaseDistribution = dailyDistribution.times(phase.daysInPhase);
|
||||
|
||||
for (const item of items) {
|
||||
// 检查该用户的批次是否参与此阶段
|
||||
if (phase.participatingBatches.includes(item.batch)) {
|
||||
const userContribution = userContributions.get(item.accountSequence)!;
|
||||
const ratio = userContribution.dividedBy(phase.networkContribution);
|
||||
const phaseAmount = phaseDistribution.times(ratio);
|
||||
|
||||
const currentAmount = userAmounts.get(item.accountSequence)!;
|
||||
userAmounts.set(item.accountSequence, currentAmount.plus(phaseAmount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 构建返回结果
|
||||
let grandTotalAmount = new Decimal(0);
|
||||
const batchResults: BatchMiningPreviewResult['batches'] = [];
|
||||
|
||||
// 计算累计全网算力(最终状态)
|
||||
// 用户只占全网的70%(30%是系统、运营、层级、团队),所以全网算力 = 用户算力 / 0.7
|
||||
let totalUserContribution = new Decimal(0);
|
||||
for (const contribution of batchContributions.values()) {
|
||||
totalUserContribution = totalUserContribution.plus(contribution);
|
||||
}
|
||||
const finalNetworkContribution = totalUserContribution.dividedBy(USER_NETWORK_RATIO);
|
||||
this.logger.log(`[preview] 用户总算力: ${totalUserContribution.toFixed(2)}, 全网算力(用户占70%): ${finalNetworkContribution.toFixed(2)}`);
|
||||
|
||||
for (const batchNum of sortedBatches) {
|
||||
const batchItems = batchGroups.get(batchNum)!;
|
||||
const batchContribution = batchContributions.get(batchNum)!;
|
||||
|
|
@ -287,14 +307,16 @@ export class BatchMiningService {
|
|||
* 根据批次的"提前天数"构建各挖矿阶段:
|
||||
* - preMineDays 表示该批次比下一批次提前开始的天数
|
||||
* - 批次1的 preMineDays=3 意味着批次1比批次2提前3天
|
||||
* - 批次2的 preMineDays=2 意味着批次2比批次3提前2天
|
||||
* - 批次3的 preMineDays=1 意味着批次3比批次4提前1天
|
||||
* - 批次1的 preMineDays=3 意味着批次1先独挖3天
|
||||
* - 批次2的 preMineDays=2 意味着批次1+2一起挖2天
|
||||
* - 批次3的 preMineDays=1 意味着批次1+2+3一起挖1天
|
||||
*
|
||||
* 阶段划分:
|
||||
* - 阶段1: 只有批次1,持续 (批次1的preMineDays - 批次2的preMineDays) 天
|
||||
* - 阶段2: 批次1+2,持续 (批次2的preMineDays - 批次3的preMineDays) 天
|
||||
* - 阶段1: 只有批次1,持续 preMineDays 天
|
||||
* - 阶段2: 批次1+2,持续 preMineDays 天
|
||||
* - 阶段3: 批次1+2+3,持续 preMineDays 天
|
||||
* - ...
|
||||
* - 最后阶段: 所有批次一起挖 (totalMiningDays - 提前天数的总和)
|
||||
* - 最后阶段: 所有批次一起挖 (totalMiningDays - 所有提前天数之和)
|
||||
*/
|
||||
private buildMiningPhases(
|
||||
items: BatchMiningItem[],
|
||||
|
|
@ -323,8 +345,6 @@ export class BatchMiningService {
|
|||
this.logger.log(`[buildMiningPhases] 各批次提前天数: ${JSON.stringify(Object.fromEntries(batchPreMineDays))}`);
|
||||
this.logger.log(`[buildMiningPhases] 最大总挖矿天数: ${maxTotalMiningDays}`);
|
||||
|
||||
// 获取第一批次的提前天数
|
||||
const firstBatchPreMineDays = batchPreMineDays.get(sortedBatches[0]) || 0;
|
||||
if (maxTotalMiningDays <= 0) {
|
||||
this.logger.warn('[buildMiningPhases] 总挖矿天数<=0,无法计算');
|
||||
return phases;
|
||||
|
|
@ -335,17 +355,16 @@ export class BatchMiningService {
|
|||
let usedDays = 0; // 已分配的天数
|
||||
|
||||
// 按批次顺序添加阶段(提前挖矿阶段)
|
||||
// 每个批次加入后,挖该批次的 preMineDays 天
|
||||
for (let i = 0; i < sortedBatches.length; i++) {
|
||||
const currentBatch = sortedBatches[i];
|
||||
const currentPreMineDays = batchPreMineDays.get(currentBatch) || 0;
|
||||
const nextBatch = sortedBatches[i + 1];
|
||||
const nextPreMineDays = nextBatch !== undefined ? (batchPreMineDays.get(nextBatch) || 0) : 0;
|
||||
|
||||
// 当前批次加入挖矿
|
||||
participatingBatches.push(currentBatch);
|
||||
|
||||
// 计算当前阶段持续的天数 = 当前批次提前天数 - 下一批次提前天数
|
||||
const phaseDays = currentPreMineDays - nextPreMineDays;
|
||||
// 该阶段持续天数 = 当前批次的提前天数
|
||||
const phaseDays = currentPreMineDays;
|
||||
|
||||
if (phaseDays > 0) {
|
||||
// 计算该阶段参与用户的算力
|
||||
|
|
|
|||
Loading…
Reference in New Issue