give a bonus reward for the first uploads of a user

This commit is contained in:
Spine
2025-10-02 04:59:56 +00:00
parent d8058f7b77
commit 2dee8ef9b8
9 changed files with 105 additions and 27 deletions

View File

@@ -5,6 +5,23 @@ declare(strict_types=1);
namespace Gazelle;
class BonusUploadReward extends Base {
public function boost(User $user): int {
if (
!BONUS_UPLOAD_BOOST_ACTIVE
||
$user->classLevel() > BONUS_UPLOAD_BOOST_MAX_LEVEL
) {
return 0;
}
$index = $user->ordinal()->value('bonus-upload-boost');
if (!isset(BONUS_UPLOAD_BOOST[$index])) {
return 0;
}
$boost = BONUS_UPLOAD_BOOST[$index];
$user->ordinal()->set('bonus-upload-boost', $index + 1);
return $boost;
}
public function reward(Torrent $torrent): int {
$categoryId = $torrent->group()->categoryId();
if ($torrent->isPerfectFlac()) {

View File

@@ -13,7 +13,7 @@ namespace Gazelle\User;
*/
class Ordinal extends \Gazelle\BaseUser {
final protected const CACHE_KEY = 'u_ord_%s';
final protected const CACHE_KEY = 'u_ord2_%s';
protected array $info;

View File

@@ -736,9 +736,19 @@ defined('BONUS_POOL_TAX_STAFF') or define('BONUS_POOL_TAX_STAFF', 0.5);
// Pricing of tokens to other scales up at every interval of tokens received.
defined('BONUS_OTHER_TOKEN_INTERVAL') or define('BONUS_OTHER_TOKEN_INTERVAL', 100);
// At each interval, prices are raised by SCALE percent. Set to 0 to disable scaling.
// At each interval, prices are raised by SCALE percent. Set to 0 to enable flat pricing.
defined('BONUS_OTHER_TOKEN_SCALE') or define('BONUS_OTHER_TOKEN_SCALE', 20);
// Do initial uploads get a boost?
defined('BONUS_UPLOAD_BOOST_ACTIVE') or define('BONUS_UPLOAD_BOOST_ACTIVE', true);
// What are the (and how many) rewards for upload boosts
defined('BONUS_UPLOAD_BOOST') or define('BONUS_UPLOAD_BOOST', [5000, 4000, 3000, 2000, 1000]);
// What is the highest userclass level that benefits from boosts? (200 == Power User)
defined('BONUS_UPLOAD_BOOST_MAX_LEVEL') or define('BONUS_UPLOAD_BOOST_MAX_LEVEL', 200);
// ------------------------------------------------------------------------
// Pagination

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class BonusUploadBoost extends AbstractMigration {
public function up(): void {
$this->table('user_ordinal')
->insert([[
'name' => 'bonus-upload-boost',
'description' => 'How many upload boosts has this user earned',
'default_value' => 0,
]])
->save();
}
public function down(): void {
$this->query("
delete from user_ordinal where name = 'bonus-upload-boost';
");
}
}

View File

@@ -71,6 +71,7 @@ parameters:
- AJAX
- BITCOIN_DONATION_XYZPUB
- BLOCK_TOR
- BONUS_UPLOAD_BOOST_ACTIVE
- DISABLE_IRC
- DISABLE_TRACKER
- DEBUG

View File

@@ -616,7 +616,10 @@ $Debug->mark('upload: database committed');
$tracker = new Tracker();
$uploadReward = new BonusUploadReward();
$bonusTotal = 0;
$bonusTotal = $uploadReward->boost($Viewer);
if ($bonusTotal > 0) {
$Viewer->addStaffNote("$bonusTotal points boost for {$torrent->publicLocation()}")->modify();
}
$folderCheck = [];
foreach ($upload['new'] as $t) {
$t->flush()->unlockUpload();

View File

@@ -156,28 +156,28 @@ None
</li>
{% endif %}
{% set visible = user.propertyVisible(preview_user, 'uploaded') %}
{%- set visible = user.propertyVisible(preview_user, 'uploaded') %}
{% if visible %}
<li class="tooltip{{ override(visible) }}" title="{{ user.uploadedSize|octet_size(5) }}">Uploaded: {{ user.uploadedSize|octet_size }}</li>
{% endif %}
{% set visible = user.propertyVisible(preview_user, 'downloaded') %}
{%- set visible = user.propertyVisible(preview_user, 'downloaded') %}
{% if visible %}
<li class="tooltip{{ override(visible) }}" title="{{ user.downloadedSize|octet_size(5) }}">Downloaded: {{ user.downloadedSize|octet_size }}</li>
{% endif %}
{% set visible = min(user.propertyVisible(preview_user, 'downloaded'), user.propertyVisible(preview_user, 'uploaded')) %}
{%- set visible = min(user.propertyVisible(preview_user, 'downloaded'), user.propertyVisible(preview_user, 'uploaded')) %}
{% if visible %}
{% set buffer = user.buffer[1] %}
<li class="tooltip{{ override(visible) }}" title="{{ buffer|octet_size(5) }}">Buffer: {{ buffer|octet_size }}</li>
{% endif %}
{% set visible = user.propertyVisible(preview_user, 'ratio') %}
{%- set visible = user.propertyVisible(preview_user, 'ratio') %}
{% if visible %}
<li{{ class_override(visible) }}>Ratio: {{ ratio(user.uploadedSize, user.downloadedSize) }} </li>
{% endif %}
{% if own_profile or viewer.permitted('users_mod') %}
{%- if own_profile or viewer.permitted('users_mod') %}
{% set recovered = user.recoveryFinalSize %}
{% if recovered %}
<li class="tooltip" title="Recovered from previous site: {{ recovered|octet_size(5) }}">Recovered: {{ recovered|octet_size }}</li>
@@ -186,24 +186,34 @@ None
{% endif %}
{% endif %}
{% set visible = user.propertyVisible(preview_user, 'requiredratio') %}
{%- set visible = user.propertyVisible(preview_user, 'requiredratio') %}
{% if visible %}
{% set required = user.buffer[0] %}
<li{{ class_override(visible) }}>Required Ratio: <span class="tooltip" title="{{ user.requiredRatio|number_format(5) }}">{{ user.requiredRatio|number_format(2) }}</span></li>
<li{{ class_override(visible) }}>Required Class Ratio: <span class="tooltip" title="{{ required|number_format(5) }}">{{ required|number_format(2) }}</span></li>
{% endif %}
{% set visible = user.propertyVisible(preview_user, 'requiredratio') %}
{%- set visible = user.propertyVisible(preview_user, 'requiredratio') %}
{% if visible %}
{% set size = user.seedingSize %}
<li class="tooltip{{ override(visible) }}" title="{{ size|number_format }}">Seeding Size: {{ size|octet_size }}</li>
{% endif %}
{% set visible = user.propertyVisible(preview_user, 'bonuspoints') %}
{%- set visible = user.propertyVisible(preview_user, 'bonuspoints') %}
{% if visible %}
{% if viewer.permitted('admin_bp_history') %}
<li{{ class_override(visible) }}>Bonus Points: {{ user.bonusPointsTotal|number_format }}
<a href="bonus.php?action=history&amp;userid={{ user_id }}" class="brackets">History</a></li>
{% if constant('BONUS_UPLOAD_BOOST_ACTIVE') %}
{% set boost = user.ordinal.value('bonus-upload-boost') %}
{% set total = 0 %}
{% if boost %}
{% for n in range(1, boost) %}
{% set total = total + constant('BONUS_UPLOAD_BOOST')[n - 1] %}
{% endfor %}
{% endif %}
<li>Upload boosts: {{ boost }}{% if total %} ({{ total|number_format }} points){% endif %}</li>
{% endif %}
<li{{ class_override(visible) }}><a href="bonus.php?action=bprates&amp;userid={{ user_id }}">Points Per Hour</a>: {{ bonus.hourlyRate|number_format(2) }}
{% elseif own_profile %}
<li{{ class_override(visible) }}>Bonus Points: {{ user.bonusPointsTotal|number_format }}
@@ -215,12 +225,12 @@ None
{% endif %}
{% endif %}
{% if own_profile or viewer.permitted('users_mod') %}
{%- if own_profile or viewer.permitted('users_mod') %}
<li{{ class_override(viewer.permitted('users_mod') ? constant('PARANOIA_OVERRIDDEN') : constant('PARANOIA_ALLOWED'))
}}><a href="userhistory.php?action=token_history&amp;userid={{ user_id }}">Tokens</a>: {{ user.tokenCount|number_format }}</li>
{% endif %}
{% if user.isWarned and (own_profile or viewer.permitted('users_mod')) %}
{%- if user.isWarned and (own_profile or viewer.permitted('users_mod')) %}
<li{{ class_override(viewer.permitted('users_mod') ? constant('PARANOIA_OVERRIDDEN') : constant('PARANOIA_ALLOWED'))
}}>Warning expires in: {{ user.warningExpiry|time_diff }}</li>
{% endif %}

View File

@@ -3,27 +3,26 @@
<ul class="stats nobullet">
<li>Class: <strong>{{ user.userclassName }}</strong></li>
{% for id, name in user.privilege.secondaryClassList %}
{% if loop.first %}
{% if loop.first %}
<li>
<ul class="stats">
{% endif %}
{% if id != constant('DONOR') or user.propertyVisible(viewer, 'hide_donor_heart') %}
{% endif %}
{% if id != constant('DONOR') or user.propertyVisible(viewer, 'hide_donor_heart') %}
<li>{{ name }}</li>
{% endif %}
{% if loop.last %}
{% endif %}
{% if loop.last %}
</ul>
</li>
{% endif %}
{% endif %}
{% endfor %}
{% set own_profile = user.id == viewer.id %}
{%- set own_profile = user.id == viewer.id %}
<li>Paranoia level: {{ user.paranoiaLabel }}</li>
{%- if own_profile or viewer.permitted('users_view_email') %}
{% if own_profile or viewer.permitted('users_view_email') %}
<li>Email: <a href="mailto:{{ user.email }}">{{ user.email }}</a>
{% if viewer.permitted('users_view_email') %}
{% if viewer.permitted('users_view_email') %}
<a href="user.php?action=search&amp;email_history=on&amp;email={{ user.email }}" title="Search" class="brackets tooltip">S</a>
{%- endif -%}
{% endif %}
</li>
{% endif %}
@@ -35,7 +34,7 @@
<li>Passkey: <a href="#" id="passkey" data-key="{{ user.announceKey }}" class="brackets">View</a></li>
{% endif %}
{% if viewer.permitted('users_view_invites') %}
{%- if viewer.permitted('users_view_invites') %}
<li>Invited by:
{% if user.referral %}
self from {{ user.referral }}.
@@ -61,9 +60,9 @@
{%- if viewer.permitted('users_view_invites') or (own_profile and user.canPurchaseInvite) %}
<li>Invites: {% if user.disableInvites %}<span title="Invites are disabled">X</span>{% else %}{{ user.unusedInviteTotal|number_format }}{% endif %}
({{ user.invite.pendingTotal|number_format }} in use)</li>
{% set total = user.stats.invitedTotal %}
{% set total = user.stats.invitedTotal %}
<li>Invited: {{ total|number_format }}
{% if total %} <a class="brackets" href="user.php?id={{ user.id }}&amp;action=invite">View</a>{% endif %}
{% if total %} <a class="brackets" href="user.php?id={{ user.id }}&amp;action=invite">View</a>{% endif -%}
</li>
{% endif %}

View File

@@ -699,6 +699,21 @@ class BonusTest extends TestCase {
);
}
public function testUploadBoost(): void {
$this->userList[] = $user = Helper::makeUser('bonusboost.' . randomString(6), 'bonus');
$reward = new BonusUploadReward();
$user->setField('PermissionID', ELITE)->modify();
$this->assertEquals(0, $reward->boost($user), 'bonus-boost-elite');
$user->setField('PermissionID', MEMBER)->modify();
$this->assertEquals(BONUS_UPLOAD_BOOST[0], $reward->boost($user), 'bonus-boost-01');
$this->assertEquals(BONUS_UPLOAD_BOOST[1], $reward->boost($user), 'bonus-boost-02');
$this->assertEquals(BONUS_UPLOAD_BOOST[2], $reward->boost($user), 'bonus-boost-03');
$this->assertEquals(BONUS_UPLOAD_BOOST[3], $reward->boost($user), 'bonus-boost-04');
$this->assertEquals(BONUS_UPLOAD_BOOST[4], $reward->boost($user), 'bonus-boost-05');
$this->assertEquals(0, $reward->boost($user), 'bonus-boost-06');
}
public function testStats(): void {
$eco = new Stats\Economic();
$eco->flush();