update
This commit is contained in:
@@ -131,6 +131,38 @@
|
||||
}).format(Number(value));
|
||||
}
|
||||
|
||||
function recentMeasurementWindow(rows, windowDays) {
|
||||
if (!Array.isArray(rows) || rows.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const normalizedWindowDays = Number(windowDays);
|
||||
if (!Number.isFinite(normalizedWindowDays) || normalizedWindowDays <= 0) {
|
||||
return rows;
|
||||
}
|
||||
|
||||
const sortedRows = rows
|
||||
.filter((row) => row && row.measured_at)
|
||||
.slice()
|
||||
.sort((left, right) => new Date(left.measured_at).getTime() - new Date(right.measured_at).getTime());
|
||||
if (sortedRows.length === 0) {
|
||||
return rows;
|
||||
}
|
||||
|
||||
const latestTs = new Date(sortedRows[sortedRows.length - 1].measured_at).getTime();
|
||||
if (!Number.isFinite(latestTs)) {
|
||||
return sortedRows;
|
||||
}
|
||||
|
||||
const minTs = latestTs - (normalizedWindowDays * 86400 * 1000);
|
||||
const filteredRows = sortedRows.filter((row) => {
|
||||
const measuredTs = new Date(row.measured_at).getTime();
|
||||
return Number.isFinite(measuredTs) && measuredTs >= minTs;
|
||||
});
|
||||
|
||||
return filteredRows.length ? filteredRows : [sortedRows[sortedRows.length - 1]];
|
||||
}
|
||||
|
||||
function parseStoredUtcDate(value) {
|
||||
const raw = String(value || '').trim();
|
||||
if (!raw) {
|
||||
@@ -1258,8 +1290,10 @@
|
||||
}, [payload, projectKey]);
|
||||
|
||||
const overviewCharts = useMemo(() => {
|
||||
const overviewWindowDays = Number(payload?.bootstrap_meta?.overview_window_days || 15);
|
||||
const overviewRows = recentMeasurementWindow(measurements, overviewWindowDays);
|
||||
const chartCoinCurrency = String(currentSettings.crypto_currency || 'DOGE').toUpperCase();
|
||||
const comparisonRows = measurements.filter((row) => {
|
||||
const comparisonRows = overviewRows.filter((row) => {
|
||||
const miningRate = Number(row.doge_per_hour_per_mh_interval);
|
||||
const price = Number(row.effective_price_per_coin ?? row.price_per_coin);
|
||||
return Number.isFinite(miningRate) && miningRate > 0 && Number.isFinite(price) && price > 0;
|
||||
@@ -1269,10 +1303,10 @@
|
||||
const basePrice = baseComparison ? Number(baseComparison.effective_price_per_coin ?? baseComparison.price_per_coin) : null;
|
||||
|
||||
return {
|
||||
mining: measurements.map((row) => ({ x: fmtDate(row.measured_at), y: row.coins_total })),
|
||||
performance: measurements.filter((row) => row.doge_per_day_interval !== null)
|
||||
mining: overviewRows.map((row) => ({ x: fmtDate(row.measured_at), y: row.coins_total })),
|
||||
performance: overviewRows.filter((row) => row.doge_per_day_interval !== null)
|
||||
.map((row) => ({ x: fmtDate(row.measured_at), y: row.doge_per_day_interval })),
|
||||
pricing: measurements.filter((row) => row.price_per_coin !== null)
|
||||
pricing: overviewRows.filter((row) => row.price_per_coin !== null)
|
||||
.map((row) => ({ x: fmtDate(row.measured_at), y: row.price_per_coin })),
|
||||
miningVsPrice: baseMining && basePrice ? [
|
||||
{
|
||||
@@ -1295,7 +1329,7 @@
|
||||
},
|
||||
] : [],
|
||||
};
|
||||
}, [currentSettings.crypto_currency, measurements]);
|
||||
}, [currentSettings.crypto_currency, measurements, payload?.bootstrap_meta?.overview_window_days]);
|
||||
|
||||
async function submitMeasurement(fromPreview) {
|
||||
const preview = normalizeOcrPreview(ocrPreview);
|
||||
|
||||
@@ -1285,7 +1285,10 @@ final class Router
|
||||
];
|
||||
}
|
||||
|
||||
return $this->analytics()->buildSummary($measurements, $settings, $targets);
|
||||
return $this->analytics()->buildSummary($measurements, $settings, $targets, [
|
||||
'include_offer_scenarios' => $view === 'mining',
|
||||
'include_long_term_projection' => $view === 'mining',
|
||||
]);
|
||||
}
|
||||
|
||||
private function filterMeasurementsToRecentWindow(array $rows, int $windowDays): array
|
||||
|
||||
@@ -201,8 +201,11 @@ final class AnalyticsService
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function buildSummary(array $measurements, array $settings, array $targets): array
|
||||
public function buildSummary(array $measurements, array $settings, array $targets, array $options = []): array
|
||||
{
|
||||
$includeOfferScenarios = !array_key_exists('include_offer_scenarios', $options) || (bool) $options['include_offer_scenarios'];
|
||||
$includeLongTermProjection = !array_key_exists('include_long_term_projection', $options) || (bool) $options['include_long_term_projection'];
|
||||
|
||||
if ($measurements === []) {
|
||||
return [
|
||||
'latest_measurement' => null,
|
||||
@@ -355,28 +358,35 @@ final class AnalyticsService
|
||||
'break_even_days_overall' => $this->roundOrNull($breakEvenDaysOverall, 4),
|
||||
'break_even_eta_at' => $breakEvenProjection['eta'] ?? null,
|
||||
]);
|
||||
$currentProjection = $this->projectPerformance(
|
||||
is_array($settings['cost_plans'] ?? null) ? $settings['cost_plans'] : [],
|
||||
$purchasedMiners,
|
||||
$latestSummary,
|
||||
730
|
||||
);
|
||||
$latestSummary = array_merge($latestSummary, [
|
||||
'projection_days' => $currentProjection['days'],
|
||||
'projection_two_year_revenue' => $this->roundOrNull($currentProjection['revenue'], 8),
|
||||
'projection_two_year_cost' => $this->roundOrNull($currentProjection['cost'], 8),
|
||||
'projection_two_year_profit' => $this->roundOrNull($currentProjection['profit'], 8),
|
||||
]);
|
||||
$offerSummary = array_map(
|
||||
fn (array $offer): array => $this->enrichOfferScenario(
|
||||
$offer,
|
||||
$latestSummary,
|
||||
$currentHashrateMh,
|
||||
if ($includeLongTermProjection) {
|
||||
$currentProjection = $this->projectPerformance(
|
||||
is_array($settings['cost_plans'] ?? null) ? $settings['cost_plans'] : [],
|
||||
$purchasedMiners
|
||||
),
|
||||
$offerSummary
|
||||
);
|
||||
$purchasedMiners,
|
||||
$latestSummary,
|
||||
730
|
||||
);
|
||||
$latestSummary = array_merge($latestSummary, [
|
||||
'projection_days' => $currentProjection['days'],
|
||||
'projection_two_year_revenue' => $this->roundOrNull($currentProjection['revenue'], 8),
|
||||
'projection_two_year_cost' => $this->roundOrNull($currentProjection['cost'], 8),
|
||||
'projection_two_year_profit' => $this->roundOrNull($currentProjection['profit'], 8),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($includeOfferScenarios) {
|
||||
$offerSummary = array_map(
|
||||
fn (array $offer): array => $this->enrichOfferScenario(
|
||||
$offer,
|
||||
$latestSummary,
|
||||
$currentHashrateMh,
|
||||
is_array($settings['cost_plans'] ?? null) ? $settings['cost_plans'] : [],
|
||||
$purchasedMiners
|
||||
),
|
||||
$offerSummary
|
||||
);
|
||||
} else {
|
||||
$offerSummary = [];
|
||||
}
|
||||
|
||||
return [
|
||||
'latest_measurement' => $latestSummary,
|
||||
|
||||
Reference in New Issue
Block a user