Skip to content

Commit

Permalink
Merge pull request #11821 from notbakaneko/feature/username-cost-chan…
Browse files Browse the repository at this point in the history
…ge-simpler

Simpler username cost reduction
  • Loading branch information
nanaya authored Jan 27, 2025
2 parents 10f260e + 4aaf280 commit 73b6491
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 51 deletions.
17 changes: 9 additions & 8 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,15 @@ public function getAuthPassword()

public function usernameChangeCost()
{
$tier = min($this->usernameChangeHistory()->paid()->count(), 5);

if ($tier > 1) {
$lastChange = $this->usernameChangeHistory()->paid()->last()?->timestamp;
if ($lastChange !== null) {
$tier = max($tier - $lastChange->diffInYears(Carbon::now(), false), 1);
}
}
$minTier = $this->usernameChangeHistory()->paid()->exists() ? 1 : 0;

$tier = max(
$this->usernameChangeHistory()
->paid()
->where('timestamp', '>', Carbon::now()->subYears(3))
->count(),
$minTier,
);

return match ($tier) {
0 => 0,
Expand Down
106 changes: 63 additions & 43 deletions tests/Models/UserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,6 @@ public static function dataProviderForUsernameChangeCost()
];
}

public static function dataProviderForUsernameChangeCostLastChange()
{
// assume there are 6 changes (max tier + 1)
return [
[0, 100],
[1, 64],
[2, 32],
[3, 16],
[4, 8],
[5, 8],
[6, 8],
[10, 8],
];
}

public static function dataProviderForUsernameChangeCostType()
{
return [
Expand All @@ -68,14 +53,16 @@ public static function dataProviderForUsernameChangeCostType()
];
}

public static function dataProviderForUsernameChangeCostTypeLastChange()
public static function dataProviderForUsernameChangeCostWindow()
{
// years with no name changes, cost
// test is setup with name change every 6 months.
return [
['admin', 8],
['inactive', 8],
['paid', 32],
['revert', 8],
['support', 32],
[0, 100],
[1, 32],
[2, 8],
[3, 8],
[4, 8],
];
}

Expand Down Expand Up @@ -185,20 +172,50 @@ public function testUsernameChangeCost(int $changes, int $cost)
$this->assertSame($cost, $user->usernameChangeCost());
}

/**
* @dataProvider dataProviderForUsernameChangeCostLastChange
*/
public function testUsernameChangeCostLastChange(int $years, int $cost)
public function testUsernameChangeCostMultiple()
{
$this->travelTo(CarbonImmutable::now()->subYears($years));
$user = User::factory()->create();

$user = User::factory()
->has(UsernameChangeHistory::factory()->count(6)) // 6 = max tier + 1
->create();
$this->assertSame(0, $user->usernameChangeCost());

$user->usernameChangeHistory()->create([
'timestamp' => CarbonImmutable::now(),
'type' => 'paid',
'username' => 'marty',
]);

$this->travelBack();
// 1 change in last 3 years
$this->travelTo(CarbonImmutable::now()->addYears(3));
$this->assertSame(8, $user->usernameChangeCost());

$this->assertSame($cost, $user->usernameChangeCost());
// 0 changes in last 3 years
$this->travelTo(CarbonImmutable::now()->addYears(1));
$this->assertSame(8, $user->usernameChangeCost());

$user->usernameChangeHistory()->create([
'timestamp' => CarbonImmutable::now(),
'type' => 'paid',
'username' => 'mcfly',
]);

// 1 change in last 3 years
$this->assertSame(8, $user->usernameChangeCost());

$user->usernameChangeHistory()->create([
'timestamp' => CarbonImmutable::now(),
'type' => 'paid',
'username' => 'futuremarty',
]);

// 2 changes in last 3 years
$this->assertSame(16, $user->usernameChangeCost());

// 1 changes in last 3 years
$this->travelTo(CarbonImmutable::now()->addYears(3));
$this->assertSame(8, $user->usernameChangeCost());
// 0 changes in last 3 years
$this->travelTo(CarbonImmutable::now()->addYears(1));
$this->assertSame(8, $user->usernameChangeCost());
}

/**
Expand All @@ -214,22 +231,25 @@ public function testUsernameChangeCostType(string $type, int $cost)
}

/**
* This tests the correct last UsernameChangeHistory is used when applying the cost changes.
*
* @dataProvider dataProviderForUsernameChangeCostTypeLastChange
* @dataProvider dataProviderForUsernameChangeCostWindow
*/
public function testUsernameChangeCostTypeLastChange(string $type, int $cost)
public function testUsernameChangeCostWindow(int $years, int $cost)
{
$this->travelTo(CarbonImmutable::now()->subYears(1));

$user = User::factory()
->has(UsernameChangeHistory::factory()->count(2))
->create();
$now = CarbonImmutable::now();
$this->travelTo(CarbonImmutable::now()->subYears(3));

$this->travelBack();

UsernameChangeHistory::factory()->state(['type' => $type, 'user_id' => $user])->create();
$user = User::factory()->create();
while (CarbonImmutable::now()->isBefore($now)) {
$user->usernameChangeHistory()->create([
'timestamp' => CarbonImmutable::now(),
'type' => 'paid',
'username' => 'marty',
]);

$this->travelTo(CarbonImmutable::now()->addMonths(6));
}

$this->travelTo($now->addYears($years));
$this->assertSame($cost, $user->usernameChangeCost());
}

Expand Down

0 comments on commit 73b6491

Please sign in to comment.