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

This commit is contained in:
2026-05-09 01:52:09 +02:00
parent c6642c0ef5
commit 8aa52ec639
2 changed files with 84 additions and 38 deletions

View File

@@ -491,47 +491,50 @@ final class OcrService
$flags[] = 'wallet_total_missing';
}
preg_match_all(
'/([A-Z][A-Za-z0-9]+(?:\s+[A-Z][A-Za-z0-9]+)*)\s+(\d+(?:[.,]\d+)?)\s+([A-Z]{2,10})\s+(?:\d+(?:[.,]\d+)?)\s+USD\s+(\d+(?:[.,]\d+)?)\s+USD/u',
$normalizedText,
$assetRowMatches,
PREG_SET_ORDER
);
foreach ($assetRowMatches as $match) {
$balanceAmount = round((float) str_replace(',', '.', $match[2]), 10);
$assetCurrency = strtoupper((string) $match[3]);
$priceAmount = round((float) str_replace(',', '.', $match[4]), 8);
if ($balanceAmount <= 0 || $assetCurrency === '') {
$assetRows = [];
foreach ($lines as $lineIndex => $line) {
if (!preg_match('/(\d+(?:[.,]\d+)?)\s*([A-Z]{2,10})\b/u', $line, $match)) {
continue;
}
$balances[$assetCurrency] = [
'balance' => $balanceAmount,
'price_amount' => $priceAmount > 0 ? $priceAmount : null,
'price_currency' => $priceAmount > 0 ? 'USD' : null,
];
}
preg_match_all('/(\d+(?:[.,]\d+)?)\s*([A-Z]{2,10})\b/u', $normalizedText, $balanceMatches, PREG_SET_ORDER);
foreach ($balanceMatches as $match) {
$amount = round((float) str_replace(',', '.', $match[1]), 10);
$currency = strtoupper((string) $match[2]);
if ($amount <= 0 || $currency === '' || in_array($currency, ['USD', 'EUR'], true)) {
continue;
}
if (!isset($balances[$currency])) {
$balances[$currency] = [
'balance' => $amount,
'price_amount' => null,
'price_currency' => null,
];
continue;
$assetRows[] = [
'index' => $lineIndex,
'currency' => $currency,
'balance' => $amount,
];
}
foreach ($assetRows as $assetIndex => $assetRow) {
$currency = (string) $assetRow['currency'];
$balanceAmount = (float) $assetRow['balance'];
$startIndex = (int) $assetRow['index'];
$endIndex = isset($assetRows[$assetIndex + 1]['index'])
? (int) $assetRows[$assetIndex + 1]['index']
: count($lines);
$usdCandidates = [];
for ($i = $startIndex; $i < $endIndex; $i++) {
if (!isset($lines[$i])) {
continue;
}
if (preg_match_all('/(\d+(?:[.,]\d+)?)\s*USD\b/u', $lines[$i], $usdMatches, PREG_SET_ORDER)) {
foreach ($usdMatches as $usdMatch) {
$usdCandidates[] = round((float) str_replace(',', '.', $usdMatch[1]), 8);
}
}
}
$existingBalance = is_array($balances[$currency]) ? (float) ($balances[$currency]['balance'] ?? 0.0) : (float) $balances[$currency];
if ($amount > $existingBalance) {
$balances[$currency]['balance'] = $amount;
}
$priceAmount = $this->pickWalletUnitPrice($balanceAmount, $usdCandidates);
$balances[$currency] = [
'balance' => $balanceAmount,
'price_amount' => $priceAmount,
'price_currency' => $priceAmount !== null ? 'USD' : null,
];
}
if ($walletCurrencyHint !== '' && array_key_exists($walletCurrencyHint, $balances)) {
@@ -597,4 +600,49 @@ final class OcrService
'score' => $score,
];
}
/**
* @param list<float|int> $candidates
*/
private function pickWalletUnitPrice(float $balance, array $candidates): ?float
{
$candidates = array_values(array_filter(array_map(
static fn (mixed $value): float => round((float) $value, 8),
$candidates
), static fn (float $value): bool => $value > 0));
if ($balance <= 0 || $candidates === []) {
return null;
}
if (count($candidates) === 1) {
return $candidates[0];
}
$bestPrice = null;
$bestError = null;
$candidateCount = count($candidates);
for ($i = 0; $i < $candidateCount; $i++) {
$priceCandidate = $candidates[$i];
for ($j = 0; $j < $candidateCount; $j++) {
if ($i === $j) {
continue;
}
$totalCandidate = $candidates[$j];
$estimatedTotal = $balance * $priceCandidate;
$denominator = max(abs($totalCandidate), 0.00000001);
$error = abs($estimatedTotal - $totalCandidate) / $denominator;
if ($bestError === null || $error < $bestError) {
$bestError = $error;
$bestPrice = $priceCandidate;
}
}
}
if ($bestPrice !== null && $bestError !== null && $bestError <= 0.2) {
return round($bestPrice, 8);
}
return round($candidates[count($candidates) - 1], 8);
}
}