turnley.dev

PHP and MySQL code for faucet operators

Tools & Calculators

LDG-007

A minimum unit floor, so nothing pays zero

Cheap inventory rounds below one unit and displays as +0, which reads as broken. A floor of one unit costs a fraction of a cent and removes the whole class of complaint.

Mixed inventory spans a wide range of values, and at the bottom end a conversion is worth less than one of your units. The arithmetic rounds it to zero, the interface shows "+0", and the user concludes the site is broken or dishonest. Some ad networks' own walls do exactly this, which is where the complaint usually comes from.

A floor fixes it: anything that credits at all credits at least one unit. The cost is bounded and small — it only applies to inventory that was nearly worthless anyway.

The alternative, scaling the whole currency so nothing rounds to zero, makes every other number unwieldy. The floor is the cheaper fix.

PHP
function award_units(PDO $pdo, int $userId, float $revenueUsd, string $source): int
{
    $usdPerUnit = (float) setting('usd_per_unit', '0.0000001');
    $share      = setting_int('user_share_pct', 60) / 100;

    $exact = ($revenueUsd * $share) / max($usdPerUnit, 1e-12);
    $units = (int) floor($exact);

    // Anything that credits at all credits something visible.
    $floor = setting_int('min_award_units', 1);
    if ($units < $floor && $revenueUsd > 0) {
        $units = $floor;
        // Worth counting: it is a real, if tiny, subsidy.
        $pdo->prepare('UPDATE house_daily SET floored_awards = floored_awards + 1 WHERE day = CURDATE()')
            ->execute();
    }

    if ($units > 0) {
        credit_user($pdo, $userId, $units, $source);
    }
    return $units;
}

/** What the floor is costing you, so it stays a decision and not a leak. */
function floor_subsidy(PDO $pdo, int $days = 30): array
{
    $st = $pdo->prepare(
        'SELECT SUM(floored_awards) AS n FROM house_daily WHERE day >= DATE_SUB(CURDATE(), INTERVAL ? DAY)'
    );
    $st->execute([$days]);
    $n = (int) $st->fetchColumn();

    return [
        'floored'  => $n,
        'cost_usd' => $n * setting_int('min_award_units', 1) * (float) setting('usd_per_unit', '0.0000001'),
    ];
}

Using it

Count the floored awards. If the subsidy grows past a few dollars a month, the real problem is that your unit is too large.

Round display values rather than the stored ones. The ledger keeps integers; the page can say "under 0.01" when that is the truth.

Whole numbers read better than fractions on an earning site. If users see fractional rewards everywhere, scale the unit rather than showing them.

What bites people

Apply the floor to credits, not to withdrawals. A minimum withdrawal is a separate decision and must stay where the operator set it.

A floor on an item that fires thousands of times a day is not a rounding fix, it is a pricing decision. Check the volume before you set it.

Never floor a reversal. Taking back one unit when the credit was floored to one leaves the user whole; scaling it up does not.

This one touches real money. Point it at a throwaway wallet and watch a full cycle before you trust it with a live balance.

Also in Money and Ledger