togethere.cloud/private_html/cron/process_rewards_jobs.php

141 lines
6.1 KiB
PHP

<?php
/**
* CRON worker: processes queued rewards jobs.
*
* Example cron:
* */
if (php_sapi_name() !== 'cli') {
if (!isset($_SERVER['REMOTE_ADDR']) || $_SERVER['REMOTE_ADDR'] !== '127.0.0.1') {
die('Access denied - tylko z CLI lub localhost');
}
}
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('log_errors', 1);
require_once __DIR__ . '/../administration/includes/config.php';
if (!isset($pdo) || !($pdo instanceof PDO)) {
die("DB not initialized\n");
}
function logLine($s) {
echo '[' . date('Y-m-d H:i:s') . '] ' . $s . "\n";
}
$limit = 50;
// Claim jobs (simple approach: select queued and update to processing)
$stmt = $pdo->prepare("SELECT id, payload_json, attempts FROM rewards_jobs WHERE status = 'queued' ORDER BY created_at ASC LIMIT :lim");
$stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
$stmt->execute();
$jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($jobs as $job) {
$jobId = (int) $job['id'];
// optimistic lock
$upd = $pdo->prepare("UPDATE rewards_jobs SET status = 'processing', attempts = attempts + 1 WHERE id = :id AND status = 'queued'");
$upd->execute([':id' => $jobId]);
if ($upd->rowCount() === 0) continue;
$payload = json_decode($job['payload_json'], true);
if (!$payload) {
$fail = $pdo->prepare("UPDATE rewards_jobs SET status = 'failed', last_error = :err WHERE id = :id");
$fail->execute([':id' => $jobId, ':err' => 'Invalid payload JSON']);
continue;
}
// TODO: tutaj wstaw Waszą logikę nagród:
// - policz nagrodę na podstawie stawki/rate, wyniku, itd.
// - dopisz transakcje do tabeli `transactions`
// - zaktualizuj `user_stats.balance`
// - zwróć strukturę pod animacje w UI (np. coins, xp, items)
$winnerId = (int)($payload['winnerUserId'] ?? 0);
$loserId = (int)($payload['loserUserId'] ?? 0);
// Minimalny przykład: +1.00 dla zwycięzcy, +0.20 dla przegranego
// TODO: podmień na Waszą logikę (stawka/rate/ligy/tabele nagród)
$winnerReward = 1.00;
$loserReward = 0.20;
$matchId = (int)($payload['matchId'] ?? 0);
$score = (string)($payload['score'] ?? '');
try {
$pdo->beginTransaction();
// ensure user_stats exists
$pdo->prepare("INSERT IGNORE INTO user_stats (user_id, balance, matches_played, matches_won, matches_lost, matches_draw, tournaments_played, tournaments_won, leagues_participated, total_income, total_expenses, total_transactions, account_status)
VALUES (?, 0, 0,0,0,0,0,0,0,0,0,0,'active')")
->execute([$winnerId]);
$pdo->prepare("INSERT IGNORE INTO user_stats (user_id, balance, matches_played, matches_won, matches_lost, matches_draw, tournaments_played, tournaments_won, leagues_participated, total_income, total_expenses, total_transactions, account_status)
VALUES (?, 0, 0,0,0,0,0,0,0,0,0,0,'active')")
->execute([$loserId]);
// Update stats + balance
$pdo->prepare("UPDATE user_stats
SET balance = balance + ?,
matches_played = matches_played + 1,
matches_won = matches_won + 1,
total_income = total_income + ?,
total_transactions = total_transactions + 1
WHERE user_id = ?")
->execute([$winnerReward, $winnerReward, $winnerId]);
$pdo->prepare("UPDATE user_stats
SET balance = balance + ?,
matches_played = matches_played + 1,
matches_lost = matches_lost + 1,
total_income = total_income + ?,
total_transactions = total_transactions + 1
WHERE user_id = ?")
->execute([$loserReward, $loserReward, $loserId]);
// Insert transactions (if table exists)
// Schema inferred from mds/transactions_add_example.sql: (user_id, type, amount, title, description, category)
$pdo->exec("CREATE TABLE IF NOT EXISTS transactions (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
type VARCHAR(20) NOT NULL,
amount DECIMAL(12,2) NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT NULL,
category VARCHAR(50) NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_created (user_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
$tx = $pdo->prepare("INSERT INTO transactions (user_id, type, amount, title, description, category) VALUES (?, 'income', ?, ?, ?, ?)");
$titleW = 'Ping-Pong 1v1 - wygrana';
$descW = 'Mecz #' . $matchId . ' wynik ' . $score;
$tx->execute([$winnerId, $winnerReward, $titleW, $descW, 'match']);
$titleL = 'Ping-Pong 1v1 - udział';
$descL = 'Mecz #' . $matchId . ' wynik ' . $score;
$tx->execute([$loserId, $loserReward, $titleL, $descL, 'match']);
$result = [
'winner' => ['userId' => $winnerId, 'reward' => (float)$winnerReward, 'currency' => 'balance'],
'loser' => ['userId' => $loserId, 'reward' => (float)$loserReward, 'currency' => 'balance'],
'animation' => ['type' => 'coins', 'durationMs' => 2500],
'match' => ['matchId' => $matchId, 'score' => $score]
];
$ok = $pdo->prepare("UPDATE rewards_jobs SET status = 'done', result_json = :res, last_error = NULL WHERE id = :id");
$ok->execute([':id' => $jobId, ':res' => json_encode($result, JSON_UNESCAPED_UNICODE)]);
$pdo->commit();
logLine("Job #$jobId done");
} catch (Throwable $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
$fail = $pdo->prepare("UPDATE rewards_jobs SET status = 'failed', last_error = :err WHERE id = :id");
$fail->execute([':id' => $jobId, ':err' => $e->getMessage()]);
logLine("Job #$jobId failed: " . $e->getMessage());
}
}