asdsad
All checks were successful
Deploy / deploy-staging (push) Successful in 45s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-06-09 01:22:55 +02:00
parent 84e76bff6c
commit 94c985b118
13 changed files with 1213 additions and 4 deletions

View File

@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace MiningChecker;
final class MiningCheckerCalculator
{
/**
* @param array<string, mixed> $settings
* @return array<string, float|null>
*/
public function calculate(array $settings): array
{
$hashrate = $this->toHashrateHps(
(float) ($settings['hashrate'] ?? 0),
(string) ($settings['hashrate_unit'] ?? 'MH/s')
);
$networkHashrate = $this->toHashrateHps(
(float) ($settings['network_hashrate'] ?? 0),
(string) ($settings['network_hashrate_unit'] ?? 'TH/s')
);
$powerWatts = max(0.0, (float) ($settings['power_watts'] ?? 0));
$electricityPrice = max(0.0, (float) ($settings['electricity_price'] ?? 0));
$poolFeePercent = max(0.0, min(100.0, (float) ($settings['pool_fee_percent'] ?? 0)));
$coinPrice = max(0.0, (float) ($settings['coin_price'] ?? 0));
$blockReward = max(0.0, (float) ($settings['block_reward'] ?? 0));
$blockTimeSeconds = max(1.0, (float) ($settings['block_time_seconds'] ?? 60));
$hardwareCost = max(0.0, (float) ($settings['hardware_cost'] ?? 0));
$share = $networkHashrate > 0 ? $hashrate / $networkHashrate : null;
$blocksPerDay = 86400 / $blockTimeSeconds;
$dailyCoinsGross = $share !== null ? $share * $blocksPerDay * $blockReward : null;
$dailyCoinsNet = $dailyCoinsGross !== null ? $dailyCoinsGross * (1 - ($poolFeePercent / 100)) : null;
$dailyRevenue = $dailyCoinsNet !== null ? $dailyCoinsNet * $coinPrice : null;
$dailyPowerCost = ($powerWatts / 1000) * 24 * $electricityPrice;
$dailyProfit = $dailyRevenue !== null ? $dailyRevenue - $dailyPowerCost : null;
$monthlyProfit = $dailyProfit !== null ? $dailyProfit * 30 : null;
$annualProfit = $dailyProfit !== null ? $dailyProfit * 365 : null;
$breakEvenDays = ($dailyProfit !== null && $dailyProfit > 0.0 && $hardwareCost > 0.0)
? $hardwareCost / $dailyProfit
: null;
$efficiency = $hashrate > 0 ? $powerWatts / ($hashrate / 1000000) : null;
return [
'hashrate_hps' => $hashrate > 0 ? $hashrate : null,
'network_hashrate_hps' => $networkHashrate > 0 ? $networkHashrate : null,
'share_ratio' => $share,
'blocks_per_day' => $blocksPerDay,
'daily_coins_gross' => $dailyCoinsGross,
'daily_coins_net' => $dailyCoinsNet,
'daily_revenue' => $dailyRevenue,
'daily_power_cost' => $dailyPowerCost,
'daily_profit' => $dailyProfit,
'monthly_profit' => $monthlyProfit,
'annual_profit' => $annualProfit,
'break_even_days' => $breakEvenDays,
'efficiency_w_per_mh' => $efficiency,
];
}
private function toHashrateHps(float $value, string $unit): float
{
if ($value <= 0) {
return 0.0;
}
$normalized = strtoupper(trim($unit));
$multipliers = [
'H/S' => 1,
'KH/S' => 1000,
'MH/S' => 1000000,
'GH/S' => 1000000000,
'TH/S' => 1000000000000,
'PH/S' => 1000000000000000,
'EH/S' => 1000000000000000000,
];
$multiplier = $multipliers[$normalized] ?? 1000000;
return $value * $multiplier;
}
}

View File

@@ -0,0 +1,92 @@
<?php
declare(strict_types=1);
namespace MiningChecker;
use RuntimeException;
final class MiningCheckerStore
{
public function __construct(
private readonly string $projectRoot,
private readonly string $userScope,
) {
}
/**
* @return array<string, mixed>
*/
public function load(): array
{
$path = $this->path();
if (!is_file($path)) {
return $this->defaultState();
}
$raw = file_get_contents($path);
if ($raw === false || trim($raw) === '') {
return $this->defaultState();
}
$data = json_decode($raw, true);
return is_array($data) ? array_replace_recursive($this->defaultState(), $data) : $this->defaultState();
}
/**
* @param array<string, mixed> $state
*/
public function save(array $state): void
{
$directory = dirname($this->path());
if (!is_dir($directory) && !mkdir($directory, 0775, true) && !is_dir($directory)) {
throw new RuntimeException('Mining-Checker-Verzeichnis konnte nicht erstellt werden.');
}
$json = json_encode($state, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($json === false) {
throw new RuntimeException('Mining-Checker-Daten konnten nicht serialisiert werden.');
}
if (file_put_contents($this->path(), $json . PHP_EOL, LOCK_EX) === false) {
throw new RuntimeException('Mining-Checker-Daten konnten nicht gespeichert werden.');
}
}
private function path(): string
{
$safeScope = preg_replace('/[^a-zA-Z0-9_-]+/', '-', $this->userScope) ?: 'guest';
return $this->projectRoot . '/data/mining-checker/' . $safeScope . '.json';
}
/**
* @return array<string, mixed>
*/
private function defaultState(): array
{
return [
'settings' => [
'project_name' => 'DOGE Mining',
'coin_symbol' => 'DOGE',
'algorithm' => 'Scrypt',
'currency' => 'EUR',
'hashrate' => 950,
'hashrate_unit' => 'MH/s',
'network_hashrate' => 920,
'network_hashrate_unit' => 'TH/s',
'block_reward' => 10000,
'block_time_seconds' => 60,
'coin_price' => 0.14,
'power_watts' => 3420,
'electricity_price' => 0.32,
'pool_fee_percent' => 1.5,
'hardware_cost' => 8400,
'notes' => '',
],
'history' => [],
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace MiningChecker;
final class MiningCheckerUserScope
{
public static function current(): string
{
$auth = $_SESSION['desktop_auth'] ?? null;
if (!is_array($auth)) {
return 'guest';
}
$user = is_array($auth['user'] ?? null) ? $auth['user'] : [];
return (string) ($user['sub'] ?? $user['username'] ?? 'guest');
}
}