Next scheduled rescrape ... never
Version 2
Last scraped
Scraped on 30/05/2025, 17:30:54 UTC
~snip
I'm not a big php coder but here's what I could try to do
The bug arises when `$sendableUserMerit - $excessSent` results in a negative value for merit sources which actually causes  a negative spendable merit balance. So I thought the easiest fix is to cap `$sendableUserMerit` at 0 after subtracting `$excessSent` in the source branch. I may be wrong though and I don't mind an hint.

function calculate_smerit($user){
        
$sendableUserMerit db_query("select sum(amount) from merit_ledger where ID_MEMBER_TO=$user"__FILE____LINE__);
        if(
mysql_num_rows($sendableUserMerit))
                
$sendableUserMerit = (int)(mysql_fetch_array($sendableUserMerit)[0]/2);
        else
                
$sendableUserMerit 0;
        
        
// merit_sources is a log of when users' source merit was changed: "source merit becomes 'amount' at timestamp 'time'"
        
$q db_query("select time, amount from merit_sources where ID_MEMBER=$user order by time asc"__FILE____LINE__);
        if(!
mysql_num_rows($q)) {
                
$sent db_query("select sum(amount) from merit_ledger where ID_MEMBER_FROM=$user"__FILE____LINE__);
                if(
mysql_num_rows($sent))
                        
$sent = (int)mysql_fetch_array($sent)[0];
                else
                        
$sent 0;
                return array(
max(0$sendableUserMerit $sent)0);
        }
        
        
// this user is/was a source, so the calculation is more complex
        
$sourceAmtLog = array();
        while(
$row=mysql_fetch_array($q))
                
$sourceAmtLog[] = $row;
        
mysql_free_result($q);

        
$timeWindow 60*60*24*30;
        list(
$excessSent) = mysql_fetch_array(db_query("
                select sum(amount) from merit_ledger where ID_MEMBER_FROM=
$user and time<{$sourceAmtLog[0][0]}"__FILE____LINE__));
        if(empty(
$excessSent))
                
$excessSent 0;

        
$sourceMeritSendsRange = array();
        
$sourceMeritSendsRangeSum 0;
        
$sourcePos 0;

        
$q db_query("select time, amount from merit_ledger where ID_MEMBER_FROM=$user and time>={$sourceAmtLog[0][0]}"__FILE____LINE__);
        
$sends = array();
        while(
$row mysql_fetch_array($q))
                
$sends[] = $row;
        
mysql_free_result($q);

        foreach(
$sends as $send) {
                if(
$sourcePos count($sourceAmtLog)-&& $send[0] >= $sourceAmtLog[$sourcePos+1][0]) {
                        
$sourcePos++;
                        
$sourceMeritSendsRangeSum=0;
                        
$sourceMeritSendsRange = array();
                }
                while(
count($sourceMeritSendsRange)>&& ($send[0] - $sourceMeritSendsRange[0][0] > $timeWindow)) {
                        
$sourceMeritSendsRangeSum -= array_shift($sourceMeritSendsRange)[1];
                }
                
$remainingSource max($sourceAmtLog[$sourcePos][1]-$sourceMeritSendsRangeSum0);
                
$excessSent += max($send[1]-$remainingSource0);
                
$sourceMeritSendAmount min($remainingSource$send[1]);
                if(
$sourceMeritSendAmount>0) {
                        
$sourceMeritSendsRange[] = array($send[0], $sourceMeritSendAmount);
                        
$sourceMeritSendsRangeSum += $sourceMeritSendAmount;
                }
        }

        
// FIX: Cap at 0 to prevent negative values
        
$sendableUserMerit max(0$sendableUserMerit $excessSent);

        if(
$sourcePos != count($sourceAmtLog)-1) {
                
$sourcePos count($sourceAmtLog)-1;
                
$sourceMeritSendsRangeSum=0;
                
$sourceMeritSendsRange = array();
        }
        while(
count($sourceMeritSendsRange) > && (time() - $sourceMeritSendsRange[0][0] > $timeWindow)) {
                
$sourceMeritSendsRangeSum -= array_shift($sourceMeritSendsRange)[1];
        }

        
$sendableSourceMerit max($sourceAmtLog[$sourcePos][1] - $sourceMeritSendsRangeSum0);
        return array(
$sendableUserMerit$sendableSourceMerit);
}

Version 1
Scraped on 30/05/2025, 17:05:39 UTC
~snip
I'm not a big php coder but here's what I could try to do
The bug arises when `$sendableUserMerit - $excessSent` results in a negative value for merit sources which actually causes  a negative spendable merit balance. So I thought the easiest fix is to cap `$sendableUserMerit` at 0 after subtracting `$excessSent` in the source branch. I may be wrong though and I don't mind an hint.

function calculate_smerit($user){
        
$sendableUserMerit db_query("select sum(amount) from merit_ledger where ID_MEMBER_TO=$user"__FILE____LINE__);
        if(
mysql_num_rows($sendableUserMerit))
                
$sendableUserMerit = (int)(mysql_fetch_array($sendableUserMerit)[0]/2);
        else
                
$sendableUserMerit 0;
        
        
// merit_sources is a log of when users' source merit was changed: "source merit becomes 'amount' at timestamp 'time'"
        
$q db_query("select time, amount from merit_sources where ID_MEMBER=$user order by time asc"__FILE____LINE__);
        if(!
mysql_num_rows($q)) {
                
$sent db_query("select sum(amount) from merit_ledger where ID_MEMBER_FROM=$user"__FILE____LINE__);
                if(
mysql_num_rows($sent))
                        
$sent = (int)mysql_fetch_array($sent)[0];
                else
                        
$sent 0;
                return array(
$sendableUserMerit $sent0);
        }
        
        
// this user is/was a source, so the calculation is more complex
        
$sourceAmtLog = array();
        while(
$row=mysql_fetch_array($q))
                
$sourceAmtLog[] = $row;
        
mysql_free_result($q);

        
$timeWindow 60*60*24*30;
        list(
$excessSent) = mysql_fetch_array(db_query("
                select sum(amount) from merit_ledger where ID_MEMBER_FROM=
$user and time<{$sourceAmtLog[0][0]}"__FILE____LINE__));
        if(empty(
$excessSent))
                
$excessSent 0;

        
$sourceMeritSendsRange = array();
        
$sourceMeritSendsRangeSum 0;
        
$sourcePos 0;

        
$q db_query("select time, amount from merit_ledger where ID_MEMBER_FROM=$user and time>={$sourceAmtLog[0][0]}"__FILE____LINE__);
        
$sends = array();
        while(
$row mysql_fetch_array($q))
                
$sends[] = $row;
        
mysql_free_result($q);

        foreach(
$sends as $send) {
                if(
$sourcePos count($sourceAmtLog)-&& $send[0] >= $sourceAmtLog[$sourcePos+1][0]) {
                        
$sourcePos++;
                        
$sourceMeritSendsRangeSum=0;
                        
$sourceMeritSendsRange = array();
                }
                while(
count($sourceMeritSendsRange)>&& ($send[0] - $sourceMeritSendsRange[0][0] > $timeWindow)) {
                        
$sourceMeritSendsRangeSum -= array_shift($sourceMeritSendsRange)[1];
                }
                
$remainingSource max($sourceAmtLog[$sourcePos][1]-$sourceMeritSendsRangeSum0);
                
$excessSent += max($send[1]-$remainingSource0);
                
$sourceMeritSendAmount min($remainingSource$send[1]);
                if(
$sourceMeritSendAmount>0) {
                        
$sourceMeritSendsRange[] = array($send[0], $sourceMeritSendAmount);
                        
$sourceMeritSendsRangeSum += $sourceMeritSendAmount;
                }
        }

        
// FIX: Cap at 0 to prevent negative values
        
$sendableUserMerit max(0$sendableUserMerit $excessSent);

        if(
$sourcePos != count($sourceAmtLog)-1) {
                
$sourcePos count($sourceAmtLog)-1;
                
$sourceMeritSendsRangeSum=0;
                
$sourceMeritSendsRange = array();
        }
        while(
count($sourceMeritSendsRange) > && (time() - $sourceMeritSendsRange[0][0] > $timeWindow)) {
                
$sourceMeritSendsRangeSum -= array_shift($sourceMeritSendsRange)[1];
        }

        
$sendableSourceMerit max($sourceAmtLog[$sourcePos][1] - $sourceMeritSendsRangeSum0);
        return array(
$sendableUserMerit$sendableSourceMerit);
}

Original archived Re: Negative Sendable Merits. A bug?
Scraped on 30/05/2025, 17:00:46 UTC
~snip
I'm not a big php coder but here's what I could try to do
The bug arises when `$sendableUserMerit - $excessSent` results in a negative value for merit sources which actually causes  a negative spendable merit balance. So I thought the easiest fix is to cap `$sendableUserMerit` at 0 after subtracting `$excessSent` in the source branch.

function calculate_smerit($user){
        
$sendableUserMerit db_query("select sum(amount) from merit_ledger where ID_MEMBER_TO=$user"__FILE____LINE__);
        if(
mysql_num_rows($sendableUserMerit))
                
$sendableUserMerit = (int)(mysql_fetch_array($sendableUserMerit)[0]/2);
        else
                
$sendableUserMerit 0;
        
        
// merit_sources is a log of when users' source merit was changed: "source merit becomes 'amount' at timestamp 'time'"
        
$q db_query("select time, amount from merit_sources where ID_MEMBER=$user order by time asc"__FILE____LINE__);
        if(!
mysql_num_rows($q)) {
                
$sent db_query("select sum(amount) from merit_ledger where ID_MEMBER_FROM=$user"__FILE____LINE__);
                if(
mysql_num_rows($sent))
                        
$sent = (int)mysql_fetch_array($sent)[0];
                else
                        
$sent 0;
                return array(
$sendableUserMerit $sent0);
        }
        
        
// this user is/was a source, so the calculation is more complex
        
$sourceAmtLog = array();
        while(
$row=mysql_fetch_array($q))
                
$sourceAmtLog[] = $row;
        
mysql_free_result($q);

        
$timeWindow 60*60*24*30;
        list(
$excessSent) = mysql_fetch_array(db_query("
                select sum(amount) from merit_ledger where ID_MEMBER_FROM=
$user and time<{$sourceAmtLog[0][0]}"__FILE____LINE__));
        if(empty(
$excessSent))
                
$excessSent 0;

        
$sourceMeritSendsRange = array();
        
$sourceMeritSendsRangeSum 0;
        
$sourcePos 0;

        
$q db_query("select time, amount from merit_ledger where ID_MEMBER_FROM=$user and time>={$sourceAmtLog[0][0]}"__FILE____LINE__);
        
$sends = array();
        while(
$row mysql_fetch_array($q))
                
$sends[] = $row;
        
mysql_free_result($q);

        foreach(
$sends as $send) {
                if(
$sourcePos count($sourceAmtLog)-&& $send[0] >= $sourceAmtLog[$sourcePos+1][0]) {
                        
$sourcePos++;
                        
$sourceMeritSendsRangeSum=0;
                        
$sourceMeritSendsRange = array();
                }
                while(
count($sourceMeritSendsRange)>&& ($send[0] - $sourceMeritSendsRange[0][0] > $timeWindow)) {
                        
$sourceMeritSendsRangeSum -= array_shift($sourceMeritSendsRange)[1];
                }
                
$remainingSource max($sourceAmtLog[$sourcePos][1]-$sourceMeritSendsRangeSum0);
                
$excessSent += max($send[1]-$remainingSource0);
                
$sourceMeritSendAmount min($remainingSource$send[1]);
                if(
$sourceMeritSendAmount>0) {
                        
$sourceMeritSendsRange[] = array($send[0], $sourceMeritSendAmount);
                        
$sourceMeritSendsRangeSum += $sourceMeritSendAmount;
                }
        }

        
// FIX: Cap at 0 to prevent negative values
        
$sendableUserMerit max(0$sendableUserMerit $excessSent);

        if(
$sourcePos != count($sourceAmtLog)-1) {
                
$sourcePos count($sourceAmtLog)-1;
                
$sourceMeritSendsRangeSum=0;
                
$sourceMeritSendsRange = array();
        }
        while(
count($sourceMeritSendsRange) > && (time() - $sourceMeritSendsRange[0][0] > $timeWindow)) {
                
$sourceMeritSendsRangeSum -= array_shift($sourceMeritSendsRange)[1];
        }

        
$sendableSourceMerit max($sourceAmtLog[$sourcePos][1] - $sourceMeritSendsRangeSum0);
        return array(
$sendableUserMerit$sendableSourceMerit);
}