ycyxc
This commit is contained in:
@@ -1189,44 +1189,116 @@ final class AnalyticsService
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dogePerDayPerMh = $dogePerDay / $currentHashrateMh;
|
$dogePerDayPerMh = $dogePerDay / $currentHashrateMh;
|
||||||
$cumulativeRevenue = 0.0;
|
|
||||||
$maxDays = 3650;
|
$maxDays = 3650;
|
||||||
|
$horizonTs = $baseTs + ($maxDays * 86400);
|
||||||
|
$entries = [];
|
||||||
|
|
||||||
for ($day = 0; $day <= $maxDays; $day++) {
|
|
||||||
$dayHashrate = 0.0;
|
|
||||||
$dayTs = $baseTs + ($day * 86400);
|
|
||||||
foreach ($costPlans as $plan) {
|
foreach ($costPlans as $plan) {
|
||||||
if (!empty($plan['is_active']) && $this->entryIsCovered($plan, $dayTs)) {
|
if (empty($plan['is_active'])) {
|
||||||
$dayHashrate += $this->normalizeHashrateMh($plan['mining_speed_value'] ?? null, $plan['mining_speed_unit'] ?? null);
|
continue;
|
||||||
$dayHashrate += $this->normalizeHashrateMh($plan['bonus_speed_value'] ?? null, $plan['bonus_speed_unit'] ?? null);
|
|
||||||
}
|
}
|
||||||
|
$entries[] = ['data' => $plan, 'start_field' => 'starts_at'];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($purchasedMiners as $miner) {
|
foreach ($purchasedMiners as $miner) {
|
||||||
if ((array_key_exists('is_active', $miner) && empty($miner['is_active'])) || !$this->entryIsCovered($miner, $dayTs, 'purchased_at')) {
|
if (array_key_exists('is_active', $miner) && empty($miner['is_active'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$dayHashrate += $this->normalizeHashrateMh($miner['mining_speed_value'] ?? null, $miner['mining_speed_unit'] ?? null);
|
$entries[] = ['data' => $miner, 'start_field' => 'purchased_at'];
|
||||||
$dayHashrate += $this->normalizeHashrateMh($miner['bonus_speed_value'] ?? null, $miner['bonus_speed_unit'] ?? null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($dayHashrate <= 0) {
|
$events = [$baseTs, $horizonTs];
|
||||||
|
foreach ($entries as $entryMeta) {
|
||||||
|
$entry = $entryMeta['data'];
|
||||||
|
$startField = $entryMeta['start_field'];
|
||||||
|
$startTs = $this->utcTimestamp((string) ($entry[$startField] ?? ''));
|
||||||
|
if ($startTs > $baseTs && $startTs < $horizonTs) {
|
||||||
|
$events[] = $startTs;
|
||||||
|
}
|
||||||
|
|
||||||
|
$endTs = $this->entryCoverageEndTimestamp($entry, $startField);
|
||||||
|
if ($endTs !== null) {
|
||||||
|
$afterEndTs = $endTs + 1;
|
||||||
|
if ($afterEndTs > $baseTs && $afterEndTs < $horizonTs) {
|
||||||
|
$events[] = $afterEndTs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$events = array_values(array_unique(array_map('intval', $events)));
|
||||||
|
sort($events, SORT_NUMERIC);
|
||||||
|
|
||||||
|
$cumulativeRevenue = 0.0;
|
||||||
|
for ($index = 0, $maxIndex = count($events) - 1; $index < $maxIndex; $index++) {
|
||||||
|
$segmentStartTs = $events[$index];
|
||||||
|
$segmentEndTs = $events[$index + 1];
|
||||||
|
if ($segmentEndTs <= $segmentStartTs) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dayRevenue = $dayHashrate * $dogePerDayPerMh * $pricePerCoin;
|
$segmentHashrate = 0.0;
|
||||||
$cumulativeRevenue += $dayRevenue;
|
foreach ($entries as $entryMeta) {
|
||||||
if ($cumulativeRevenue >= $remainingAmount) {
|
$entry = $entryMeta['data'];
|
||||||
$etaTs = (int) round($baseTs + ($day * 86400));
|
$startField = $entryMeta['start_field'];
|
||||||
|
if (!$this->entryIsCovered($entry, $segmentStartTs, $startField)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$segmentHashrate += $this->normalizeHashrateMh($entry['mining_speed_value'] ?? null, $entry['mining_speed_unit'] ?? null);
|
||||||
|
$segmentHashrate += $this->normalizeHashrateMh($entry['bonus_speed_value'] ?? null, $entry['bonus_speed_unit'] ?? null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($segmentHashrate <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$segmentDays = ($segmentEndTs - $segmentStartTs) / 86400;
|
||||||
|
if ($segmentDays <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$segmentRevenuePerDay = $segmentHashrate * $dogePerDayPerMh * $pricePerCoin;
|
||||||
|
if ($segmentRevenuePerDay <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$segmentRevenue = $segmentRevenuePerDay * $segmentDays;
|
||||||
|
if ($cumulativeRevenue + $segmentRevenue >= $remainingAmount) {
|
||||||
|
$remainingSegmentAmount = $remainingAmount - $cumulativeRevenue;
|
||||||
|
$segmentOffsetDays = $remainingSegmentAmount / $segmentRevenuePerDay;
|
||||||
|
$etaTs = (int) round($segmentStartTs + ($segmentOffsetDays * 86400));
|
||||||
return [
|
return [
|
||||||
'days' => (float) $day,
|
'days' => round(($etaTs - $baseTs) / 86400, 4),
|
||||||
'eta' => $this->formatUtcTimestamp($etaTs),
|
'eta' => $this->formatUtcTimestamp($etaTs),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$cumulativeRevenue += $segmentRevenue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['days' => null, 'eta' => null];
|
return ['days' => null, 'eta' => null];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function entryCoverageEndTimestamp(array $entry, string $startField = 'starts_at'): ?int
|
||||||
|
{
|
||||||
|
if (!empty($entry['auto_renew'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$runtimeMonths = (int) ($entry['runtime_months'] ?? 0);
|
||||||
|
if ($runtimeMonths <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$startTs = $this->utcTimestamp((string) ($entry[$startField] ?? ''));
|
||||||
|
if ($startTs <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$runtimeDays = $runtimeMonths * 30.4375;
|
||||||
|
return (int) round($startTs + ($runtimeDays * 86400));
|
||||||
|
}
|
||||||
|
|
||||||
private function utcTimestamp(?string $value): int
|
private function utcTimestamp(?string $value): int
|
||||||
{
|
{
|
||||||
$normalized = trim((string) $value);
|
$normalized = trim((string) $value);
|
||||||
|
|||||||
Reference in New Issue
Block a user