Skip to content

Commit 092c52a

Browse files
authoredMar 31, 2025
Merge branch 'master' into feature/xsolla-redirect-just-redirect
2 parents bcdd153 + 1103470 commit 092c52a

File tree

5 files changed

+89
-16
lines changed

5 files changed

+89
-16
lines changed
 

Diff for: ‎app/Http/Controllers/RankingController.php

+18-5
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public function __construct()
9494
abort(404);
9595
}
9696

97-
if (isset($this->params['country']) && $type === 'performance') {
97+
if (isset($this->params['country']) && static::hasCountryFilter($type)) {
9898
$this->countryStats = CountryStatistics::where('display', 1)
9999
->where('country_code', $this->params['country'])
100100
->where('mode', Beatmap::modeInt($mode))
@@ -108,7 +108,7 @@ public function __construct()
108108
}
109109

110110
$this->defaultViewVars['country'] = $this->country;
111-
if ($type === 'performance') {
111+
if (static::hasCountryFilter($type)) {
112112
$this->defaultViewVars['countries'] = json_collection(
113113
Country::whereHasRuleset($mode)->get(),
114114
new SelectOptionTransformer(),
@@ -133,7 +133,7 @@ public static function url(
133133
'multiplayer' => route('multiplayer.rooms.show', ['room' => 'latest']),
134134
'seasons' => route('seasons.show', ['season' => 'latest']),
135135
default => route('rankings', [
136-
'country' => $country !== null && $type === 'performance' ? $country->getKey() : null,
136+
'country' => $country !== null && static::hasCountryFilter($type) ? $country->getKey() : null,
137137
'mode' => $rulesetName,
138138
'sort' => $sort,
139139
'spotlight' => $spotlight !== null && $type === 'charts' ? $spotlight->getKey() : null,
@@ -142,6 +142,11 @@ public static function url(
142142
};
143143
}
144144

145+
private static function hasCountryFilter(string $type): bool
146+
{
147+
return $type === 'performance' || $type === 'score';
148+
}
149+
145150
/**
146151
* Get Ranking
147152
*
@@ -207,9 +212,17 @@ public function index($mode, $type, ?string $sort = null)
207212

208213
$stats->orderBy('rank_score', 'desc');
209214
} else { // 'score'
215+
if ($this->country !== null) {
216+
$stats->where('country_acronym', $this->country['acronym']);
217+
// preferrable to ranked_score when filtering by country.
218+
// On a few countries the default index is slightly better but much worse on the rest.
219+
$forceIndex = 'country_ranked_score';
220+
} else {
221+
// force to order by ranked_score instead of sucking down entire users table first.
222+
$forceIndex = 'ranked_score';
223+
}
224+
210225
$stats->orderBy('ranked_score', 'desc');
211-
// force to order by ranked_score instead of sucking down entire users table first.
212-
$forceIndex = 'ranked_score';
213226
}
214227

215228
if ($this->friendsOnly) {

Diff for: ‎app/Models/User.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public function usernameChangeCost()
329329
$tier = max(
330330
$this->usernameChangeHistory()
331331
->paid()
332-
->where('timestamp', '>', Carbon::now()->subYears(3))
332+
->where('timestamp', '>', Carbon::now()->subYearsNoOverflow(3))
333333
->count(),
334334
$minTier,
335335
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4+
// See the LICENCE file in the repository root for full licence text.
5+
6+
declare(strict_types=1);
7+
8+
use Illuminate\Database\Migrations\Migration;
9+
use Illuminate\Database\Schema\Blueprint;
10+
use Illuminate\Support\Facades\Schema;
11+
12+
return new class extends Migration
13+
{
14+
const TABLES = [
15+
'osu_user_stats',
16+
'osu_user_stats_fruits',
17+
'osu_user_stats_mania',
18+
'osu_user_stats_taiko',
19+
];
20+
21+
const TABLE_VARIANTS = [
22+
'osu_user_stats_mania_4k',
23+
'osu_user_stats_mania_7k',
24+
];
25+
26+
public function up(): void
27+
{
28+
foreach (static::TABLE_VARIANTS as $table) {
29+
Schema::table($table, function (Blueprint $table) {
30+
$table->bigInteger('ranked_score')->default(0)->after('rank_score_index');
31+
$table->index('ranked_score', 'ranked_score');
32+
});
33+
}
34+
35+
foreach ([...static::TABLES, ...static::TABLE_VARIANTS] as $table) {
36+
Schema::table($table, function (Blueprint $table) {
37+
$table->index(['country_acronym', 'ranked_score'], 'country_ranked_score');
38+
});
39+
}
40+
}
41+
42+
public function down(): void
43+
{
44+
foreach ([...static::TABLES, ...static::TABLE_VARIANTS] as $table) {
45+
Schema::table($table, function (Blueprint $table) {
46+
$table->dropIndex('country_ranked_score');
47+
});
48+
}
49+
50+
foreach (static::TABLE_VARIANTS as $table) {
51+
Schema::table($table, function (Blueprint $table) {
52+
$table->dropIndex('ranked_score', 'ranked_score');
53+
$table->dropColumn('ranked_score');
54+
});
55+
}
56+
}
57+
};

Diff for: ‎resources/views/rankings/score.blade.php

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
@section('ranking-header')
88
<div class="osu-page osu-page--ranking-info">
99
<div class="grid-items grid-items--ranking-filter">
10+
@include('rankings._country_filter')
1011
@include('rankings._user_filter')
1112
</div>
1213
</div>

Diff for: ‎tests/Models/UserTest.php

+12-10
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public function testResetSessions(): void
145145
public function testUsernameAvailableAtForDefaultGroup()
146146
{
147147
config_set('osu.user.allowed_rename_groups', ['default']);
148-
$allowedAtUpTo = now()->addYears(5);
148+
$allowedAtUpTo = now()->addYearsNoOverflow(5);
149149
$user = User::factory()->withGroup('default')->create();
150150

151151
$this->assertLessThanOrEqual($allowedAtUpTo, $user->getUsernameAvailableAt());
@@ -154,7 +154,7 @@ public function testUsernameAvailableAtForDefaultGroup()
154154
public function testUsernameAvailableAtForNonDefaultGroup()
155155
{
156156
config_set('osu.user.allowed_rename_groups', ['default']);
157-
$allowedAt = now()->addYears(10);
157+
$allowedAt = now()->addYearsNoOverflow(10);
158158
$user = User::factory()->withGroup('gmt')->create(['group_id' => app('groups')->byIdentifier('default')]);
159159

160160
$this->assertGreaterThanOrEqual($allowedAt, $user->getUsernameAvailableAt());
@@ -185,11 +185,11 @@ public function testUsernameChangeCostMultiple()
185185
]);
186186

187187
// 1 change in last 3 years
188-
$this->travelTo(CarbonImmutable::now()->addYears(3));
188+
$this->travelTo(CarbonImmutable::now()->addYearsNoOverflow(3));
189189
$this->assertSame(8, $user->usernameChangeCost());
190190

191191
// 0 changes in last 3 years
192-
$this->travelTo(CarbonImmutable::now()->addYears(1));
192+
$this->travelTo(CarbonImmutable::now()->addYearsNoOverflow(1));
193193
$this->assertSame(8, $user->usernameChangeCost());
194194

195195
$user->usernameChangeHistory()->create([
@@ -211,10 +211,10 @@ public function testUsernameChangeCostMultiple()
211211
$this->assertSame(16, $user->usernameChangeCost());
212212

213213
// 1 changes in last 3 years
214-
$this->travelTo(CarbonImmutable::now()->addYears(3));
214+
$this->travelTo(CarbonImmutable::now()->addYearsNoOverflow(3));
215215
$this->assertSame(8, $user->usernameChangeCost());
216216
// 0 changes in last 3 years
217-
$this->travelTo(CarbonImmutable::now()->addYears(1));
217+
$this->travelTo(CarbonImmutable::now()->addYearsNoOverflow(1));
218218
$this->assertSame(8, $user->usernameChangeCost());
219219
}
220220

@@ -236,20 +236,22 @@ public function testUsernameChangeCostType(string $type, int $cost)
236236
public function testUsernameChangeCostWindow(int $years, int $cost)
237237
{
238238
$now = CarbonImmutable::now();
239-
$this->travelTo(CarbonImmutable::now()->subYears(3));
239+
$this->travelTo($now->subYearsNoOverflow(3));
240240

241241
$user = User::factory()->create();
242-
while (CarbonImmutable::now()->isBefore($now)) {
242+
// every 6 months for 3 years = 6
243+
// using isBefore to setup adds too many when run at month boundaries.
244+
for ($i = 0; $i < 6; $i++) {
243245
$user->usernameChangeHistory()->create([
244246
'timestamp' => CarbonImmutable::now(),
245247
'type' => 'paid',
246248
'username' => 'marty',
247249
]);
248250

249-
$this->travelTo(CarbonImmutable::now()->addMonths(6));
251+
$this->travelTo(CarbonImmutable::now()->addMonthsNoOverflow(6));
250252
}
251253

252-
$this->travelTo($now->addYears($years));
254+
$this->travelTo($now->addYearsNoOverflow($years));
253255
$this->assertSame($cost, $user->usernameChangeCost());
254256
}
255257

0 commit comments

Comments
 (0)