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; namespace Gazelle;
class BonusUploadReward extends Base { 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 { public function reward(Torrent $torrent): int {
$categoryId = $torrent->group()->categoryId(); $categoryId = $torrent->group()->categoryId();
if ($torrent->isPerfectFlac()) { if ($torrent->isPerfectFlac()) {

View File

@@ -13,7 +13,7 @@ namespace Gazelle\User;
*/ */
class Ordinal extends \Gazelle\BaseUser { class Ordinal extends \Gazelle\BaseUser {
final protected const CACHE_KEY = 'u_ord_%s'; final protected const CACHE_KEY = 'u_ord2_%s';
protected array $info; 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. // 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); 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); 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 // 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 - AJAX
- BITCOIN_DONATION_XYZPUB - BITCOIN_DONATION_XYZPUB
- BLOCK_TOR - BLOCK_TOR
- BONUS_UPLOAD_BOOST_ACTIVE
- DISABLE_IRC - DISABLE_IRC
- DISABLE_TRACKER - DISABLE_TRACKER
- DEBUG - DEBUG

View File

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

View File

@@ -156,28 +156,28 @@ None
</li> </li>
{% endif %} {% endif %}
{% set visible = user.propertyVisible(preview_user, 'uploaded') %} {%- set visible = user.propertyVisible(preview_user, 'uploaded') %}
{% if visible %} {% if visible %}
<li class="tooltip{{ override(visible) }}" title="{{ user.uploadedSize|octet_size(5) }}">Uploaded: {{ user.uploadedSize|octet_size }}</li> <li class="tooltip{{ override(visible) }}" title="{{ user.uploadedSize|octet_size(5) }}">Uploaded: {{ user.uploadedSize|octet_size }}</li>
{% endif %} {% endif %}
{% set visible = user.propertyVisible(preview_user, 'downloaded') %} {%- set visible = user.propertyVisible(preview_user, 'downloaded') %}
{% if visible %} {% if visible %}
<li class="tooltip{{ override(visible) }}" title="{{ user.downloadedSize|octet_size(5) }}">Downloaded: {{ user.downloadedSize|octet_size }}</li> <li class="tooltip{{ override(visible) }}" title="{{ user.downloadedSize|octet_size(5) }}">Downloaded: {{ user.downloadedSize|octet_size }}</li>
{% endif %} {% 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 %} {% if visible %}
{% set buffer = user.buffer[1] %} {% set buffer = user.buffer[1] %}
<li class="tooltip{{ override(visible) }}" title="{{ buffer|octet_size(5) }}">Buffer: {{ buffer|octet_size }}</li> <li class="tooltip{{ override(visible) }}" title="{{ buffer|octet_size(5) }}">Buffer: {{ buffer|octet_size }}</li>
{% endif %} {% endif %}
{% set visible = user.propertyVisible(preview_user, 'ratio') %} {%- set visible = user.propertyVisible(preview_user, 'ratio') %}
{% if visible %} {% if visible %}
<li{{ class_override(visible) }}>Ratio: {{ ratio(user.uploadedSize, user.downloadedSize) }} </li> <li{{ class_override(visible) }}>Ratio: {{ ratio(user.uploadedSize, user.downloadedSize) }} </li>
{% endif %} {% endif %}
{% if own_profile or viewer.permitted('users_mod') %} {%- if own_profile or viewer.permitted('users_mod') %}
{% set recovered = user.recoveryFinalSize %} {% set recovered = user.recoveryFinalSize %}
{% if recovered %} {% if recovered %}
<li class="tooltip" title="Recovered from previous site: {{ recovered|octet_size(5) }}">Recovered: {{ recovered|octet_size }}</li> <li class="tooltip" title="Recovered from previous site: {{ recovered|octet_size(5) }}">Recovered: {{ recovered|octet_size }}</li>
@@ -186,24 +186,34 @@ None
{% endif %} {% endif %}
{% endif %} {% endif %}
{% set visible = user.propertyVisible(preview_user, 'requiredratio') %} {%- set visible = user.propertyVisible(preview_user, 'requiredratio') %}
{% if visible %} {% if visible %}
{% set required = user.buffer[0] %} {% 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 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> <li{{ class_override(visible) }}>Required Class Ratio: <span class="tooltip" title="{{ required|number_format(5) }}">{{ required|number_format(2) }}</span></li>
{% endif %} {% endif %}
{% set visible = user.propertyVisible(preview_user, 'requiredratio') %} {%- set visible = user.propertyVisible(preview_user, 'requiredratio') %}
{% if visible %} {% if visible %}
{% set size = user.seedingSize %} {% set size = user.seedingSize %}
<li class="tooltip{{ override(visible) }}" title="{{ size|number_format }}">Seeding Size: {{ size|octet_size }}</li> <li class="tooltip{{ override(visible) }}" title="{{ size|number_format }}">Seeding Size: {{ size|octet_size }}</li>
{% endif %} {% endif %}
{% set visible = user.propertyVisible(preview_user, 'bonuspoints') %} {%- set visible = user.propertyVisible(preview_user, 'bonuspoints') %}
{% if visible %} {% if visible %}
{% if viewer.permitted('admin_bp_history') %} {% if viewer.permitted('admin_bp_history') %}
<li{{ class_override(visible) }}>Bonus Points: {{ user.bonusPointsTotal|number_format }} <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> <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) }} <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 %} {% elseif own_profile %}
<li{{ class_override(visible) }}>Bonus Points: {{ user.bonusPointsTotal|number_format }} <li{{ class_override(visible) }}>Bonus Points: {{ user.bonusPointsTotal|number_format }}
@@ -215,12 +225,12 @@ None
{% endif %} {% endif %}
{% 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')) <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> }}><a href="userhistory.php?action=token_history&amp;userid={{ user_id }}">Tokens</a>: {{ user.tokenCount|number_format }}</li>
{% endif %} {% 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')) <li{{ class_override(viewer.permitted('users_mod') ? constant('PARANOIA_OVERRIDDEN') : constant('PARANOIA_ALLOWED'))
}}>Warning expires in: {{ user.warningExpiry|time_diff }}</li> }}>Warning expires in: {{ user.warningExpiry|time_diff }}</li>
{% endif %} {% endif %}

View File

@@ -3,27 +3,26 @@
<ul class="stats nobullet"> <ul class="stats nobullet">
<li>Class: <strong>{{ user.userclassName }}</strong></li> <li>Class: <strong>{{ user.userclassName }}</strong></li>
{% for id, name in user.privilege.secondaryClassList %} {% for id, name in user.privilege.secondaryClassList %}
{% if loop.first %} {% if loop.first %}
<li> <li>
<ul class="stats"> <ul class="stats">
{% endif %} {% endif %}
{% if id != constant('DONOR') or user.propertyVisible(viewer, 'hide_donor_heart') %} {% if id != constant('DONOR') or user.propertyVisible(viewer, 'hide_donor_heart') %}
<li>{{ name }}</li> <li>{{ name }}</li>
{% endif %} {% endif %}
{% if loop.last %} {% if loop.last %}
</ul> </ul>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% set own_profile = user.id == viewer.id %} {%- set own_profile = user.id == viewer.id %}
<li>Paranoia level: {{ user.paranoiaLabel }}</li> <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> <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> <a href="user.php?action=search&amp;email_history=on&amp;email={{ user.email }}" title="Search" class="brackets tooltip">S</a>
{%- endif -%} {% endif %}
</li> </li>
{% endif %} {% endif %}
@@ -35,7 +34,7 @@
<li>Passkey: <a href="#" id="passkey" data-key="{{ user.announceKey }}" class="brackets">View</a></li> <li>Passkey: <a href="#" id="passkey" data-key="{{ user.announceKey }}" class="brackets">View</a></li>
{% endif %} {% endif %}
{% if viewer.permitted('users_view_invites') %} {%- if viewer.permitted('users_view_invites') %}
<li>Invited by: <li>Invited by:
{% if user.referral %} {% if user.referral %}
self from {{ user.referral }}. self from {{ user.referral }}.
@@ -61,9 +60,9 @@
{%- if viewer.permitted('users_view_invites') or (own_profile and user.canPurchaseInvite) %} {%- 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 %} <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> ({{ user.invite.pendingTotal|number_format }} in use)</li>
{% set total = user.stats.invitedTotal %} {% set total = user.stats.invitedTotal %}
<li>Invited: {{ total|number_format }} <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> </li>
{% endif %} {% 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 { public function testStats(): void {
$eco = new Stats\Economic(); $eco = new Stats\Economic();
$eco->flush(); $eco->flush();