Skip to content

Commit 3033898

Browse files
authoredFeb 29, 2024
Merge branch 'master' into score-docs
2 parents c18d334 + 1d9b60f commit 3033898

22 files changed

+113
-91
lines changed
 

Diff for: ‎Dockerfile.deployment

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ RUN curl -fsSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.o
77
RUN echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
88

99
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg
10-
RUN echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
10+
RUN echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
1111

1212
RUN apt-get update
1313
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \

Diff for: ‎Dockerfile.development

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ RUN curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.or
77
RUN echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
88

99
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg
10-
RUN echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
10+
RUN echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
1111

1212
RUN apt-get update
1313
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \

Diff for: ‎app/Jobs/Notifications/UserAchievementUnlock.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212
class UserAchievementUnlock extends BroadcastNotificationBase
1313
{
14-
const NOTIFICATION_OPTION_NAME = Notification::USER_ACHIEVEMENT_UNLOCK;
14+
// Mainly to ensure client always getting the event.
15+
// Also it probably doesn't really make sense to mail the event
16+
// in the first place.
17+
const DELIVERY_MODE_DEFAULTS = ['mail' => false, 'push' => true];
1518

1619
protected $achievement;
1720

@@ -45,6 +48,7 @@ public function getDetails(): array
4548
'cover_url' => $this->achievement->iconUrl(),
4649
'slug' => $this->achievement->slug,
4750
'title' => $this->achievement->name,
51+
'description' => $this->achievement->description,
4852
'user_id' => $this->source->getKey(),
4953
];
5054
}

Diff for: ‎app/Libraries/LocaleMeta.php

+2-10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
class LocaleMeta
1111
{
12+
// Keys must be a superset of app.available_locales. Additional locales are
13+
// available for use only in wiki articles
1214
const MAPPINGS = [
1315
'ar' => [
1416
'flag' => 'SA',
@@ -143,10 +145,6 @@ class LocaleMeta
143145
'flag' => 'TH',
144146
'name' => 'ไทย',
145147
],
146-
'tl' => [
147-
'flag' => 'PH',
148-
'name' => 'Tagalog',
149-
],
150148
'tr' => [
151149
'flag' => 'TR',
152150
'name' => 'Türkçe',
@@ -164,12 +162,6 @@ class LocaleMeta
164162
'moment' => 'zh-cn',
165163
'name' => '简体中文',
166164
],
167-
'zh-hk' => [
168-
'flag' => 'HK',
169-
'html' => 'zh-HK',
170-
'laravelPlural' => 'zh_HK',
171-
'name' => '繁體中文(香港)',
172-
],
173165
'zh-tw' => [
174166
'flag' => 'TW',
175167
'html' => 'zh-TW',

Diff for: ‎app/Models/CountryStatistics.php

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public static function recalculate($countryAcronym, $modeInt)
3131
{
3232
$stats = UserStatistics\Model::getClass(Beatmap::modeStr($modeInt))
3333
::where('country_acronym', $countryAcronym)
34+
->where('rank_score', '>', 0)
3435
->whereHas('user', function ($userQuery) {
3536
return $userQuery->default();
3637
})->select(DB::raw('sum(ranked_score) AS ranked_score, sum(playcount) AS playcount, count(*) AS usercount, sum(rank_score) AS rank_score'))

Diff for: ‎app/Models/Multiplayer/PlaylistItemUserHighScore.php

+7-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
* @property \Carbon\Carbon $created_at
1919
* @property int $id
2020
* @property int $playlist_item_id
21-
* @property float|null $pp
2221
* @property int $score_id
2322
* @property ScoreLink $scoreLink
2423
* @property int $total_score
@@ -51,7 +50,6 @@ public static function lookupOrDefault(int $userId, int $playlistItemId): static
5150
'user_id' => $userId,
5251
], [
5352
'accuracy' => 0,
54-
'pp' => 0,
5553
'total_score' => 0,
5654
]);
5755
}
@@ -112,14 +110,17 @@ public function updateUserAttempts()
112110
$this->incrementInstance('attempts');
113111
}
114112

115-
public function updateWithScoreLink(ScoreLink $scoreLink): void
113+
public function updateWithScoreLink(ScoreLink $scoreLink): bool
116114
{
117115
$score = $scoreLink->score;
118116

119-
$this->fill([
117+
if ($score === null || !$score->passed || $score->total_score < $this->total_score) {
118+
return false;
119+
}
120+
121+
return $this->fill([
120122
'accuracy' => $score->accuracy,
121-
'pp' => $score->pp,
122-
'score_id' => $scoreLink->getKey(),
123+
'score_id' => $score->getKey(),
123124
'total_score' => $score->total_score,
124125
])->save();
125126
}

Diff for: ‎app/Models/Multiplayer/UserScoreAggregate.php

+28-40
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
* @property int $id
2121
* @property int|null $last_score_id
2222
* @property bool $in_room
23-
* @property float|null $pp
2423
* @property int $room_id
2524
* @property int $total_score
2625
* @property \Carbon\Carbon $updated_at
@@ -53,7 +52,6 @@ public static function lookupOrDefault(User $user, Room $room): static
5352
'accuracy' => 0,
5453
'attempts' => 0,
5554
'completed' => 0,
56-
'pp' => 0,
5755
'total_score' => 0,
5856
]);
5957
}
@@ -72,20 +70,14 @@ public static function new(User $user, Room $room): self
7270

7371
public function addScoreLink(ScoreLink $scoreLink, ?PlaylistItemUserHighScore $highestScore = null)
7472
{
75-
return $this->getConnection()->transaction(function () use ($highestScore, $scoreLink) {
76-
$score = $scoreLink->score;
77-
if ($score === null) {
78-
return false;
79-
}
80-
81-
$highestScore ??= PlaylistItemUserHighScore::lookupOrDefault(
73+
return $this->getConnection()->transaction(function () use ($scoreLink) {
74+
$isNewHighScore = PlaylistItemUserHighScore::lookupOrDefault(
8275
$scoreLink->user_id,
8376
$scoreLink->playlist_item_id,
84-
);
77+
)->updateWithScoreLink($scoreLink);
8578

86-
if ($score->passed && $score->total_score > $highestScore->total_score) {
87-
$this->updateUserTotal($scoreLink, $highestScore);
88-
$highestScore->updateWithScoreLink($scoreLink);
79+
if ($isNewHighScore) {
80+
$this->refreshStatistics();
8981
}
9082

9183
return true;
@@ -97,11 +89,6 @@ public function averageAccuracy()
9789
return $this->completed > 0 ? $this->accuracy / $this->completed : 0;
9890
}
9991

100-
public function averagePp()
101-
{
102-
return $this->completed > 0 ? $this->pp / $this->completed : 0;
103-
}
104-
10592
public function playlistItemAttempts(): array
10693
{
10794
$playlistItemAggs = PlaylistItemUserHighScore
@@ -137,11 +124,14 @@ public function recalculate()
137124
->with('score')
138125
->get();
139126
foreach ($scoreLinks as $scoreLink) {
140-
$this->addScoreLink(
141-
$scoreLink,
142-
$playlistItemAggs[$scoreLink->playlist_item_id] ?? null,
143-
);
127+
($playlistItemAggs[$scoreLink->playlist_item_id]
128+
?? PlaylistItemUserHighScore::lookupOrDefault(
129+
$scoreLink->user_id,
130+
$scoreLink->playlist_item_id,
131+
)
132+
)->updateWithScoreLink($scoreLink);
144133
}
134+
$this->refreshStatistics();
145135
$this->save();
146136
});
147137
}
@@ -162,7 +152,6 @@ public function removeRunningTotals()
162152
'attempts',
163153
'completed',
164154
'last_score_id',
165-
'pp',
166155
'total_score',
167156
];
168157

@@ -210,23 +199,22 @@ public function userRank()
210199
return 1 + $query->count();
211200
}
212201

213-
private function updateUserTotal(ScoreLink $currentScoreLink, PlaylistItemUserHighScore $prev)
202+
private function refreshStatistics(): void
214203
{
215-
if ($prev->score_id !== null) {
216-
$this->total_score -= $prev->total_score;
217-
$this->accuracy -= $prev->accuracy;
218-
$this->pp -= $prev->pp;
219-
$this->completed--;
220-
}
221-
222-
$current = $currentScoreLink->score;
223-
224-
$this->total_score += $current->total_score;
225-
$this->accuracy += $current->accuracy;
226-
$this->pp += $current->pp;
227-
$this->completed++;
228-
$this->last_score_id = $currentScoreLink->getKey();
229-
230-
$this->save();
204+
$agg = PlaylistItemUserHighScore
205+
::whereHas('playlistItem', fn ($q) => $q->where('room_id', $this->room_id))
206+
->selectRaw('
207+
SUM(accuracy) AS accuracy_sum,
208+
SUM(total_score) AS total_score_sum,
209+
COUNT(*) AS completed,
210+
MAX(score_id) AS last_score_id
211+
')->firstWhere('user_id', $this->user_id);
212+
213+
$this->fill([
214+
'accuracy' => $agg->getRawAttribute('accuracy_sum') ?? 0,
215+
'completed' => $agg->getRawAttribute('completed') ?? 0,
216+
'last_score_id' => $agg->getRawAttribute('last_score_id'),
217+
'total_score' => $agg->getRawAttribute('total_score_sum') ?? 0,
218+
])->save();
231219
}
232220
}

Diff for: ‎app/Models/Solo/Score.php

+4
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,10 @@ public function url(): string
427427

428428
public function userRank(?array $params = null): int
429429
{
430+
if (!$this->ranked || !$this->preserve) {
431+
return 0;
432+
}
433+
430434
// Non-legacy score always has its rank checked against all score types.
431435
if (!$this->isLegacy()) {
432436
$params['is_legacy'] = null;

Diff for: ‎app/Models/UserNotificationOption.php

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ class UserNotificationOption extends Model
3939
Notification::CHANNEL_MESSAGE,
4040
Notification::COMMENT_NEW,
4141
self::FORUM_TOPIC_REPLY,
42-
Notification::USER_ACHIEVEMENT_UNLOCK,
4342
];
4443

4544
const SUPPORTS_NOTIFICATIONS = [

Diff for: ‎app/Transformers/Multiplayer/UserScoreAggregateTransformer.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public function transform(UserScoreAggregate $score)
2323
'accuracy' => $score->averageAccuracy(),
2424
'attempts' => $score->attempts,
2525
'completed' => $score->completed,
26-
'pp' => $score->averagePp(),
26+
'pp' => 0,
2727
'room_id' => $score->room_id,
2828
'total_score' => $score->total_score,
2929
'user_id' => $score->user_id,

Diff for: ‎database/factories/BanchoStatsFactory.php

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public function definition(): array
1919
return [
2020
'users_irc' => fn() => 100 + $this->faker->randomNumber(2),
2121
'users_osu' => fn() => 10000 + $this->faker->randomNumber(4),
22+
'users_lazer' => fn() => 1000 + $this->faker->randomNumber(3),
2223
'multiplayer_games' => fn() => 200 + $this->faker->randomNumber(3),
2324
'date' => fn() => Carbon::now(),
2425
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
public function up(): void
15+
{
16+
Schema::table('osu_banchostats', function (Blueprint $table) {
17+
$table->smallInteger('users_irc')->default(0)->change();
18+
$table->mediumInteger('users_osu')->default(0)->change();
19+
$table->unsignedMediumInteger('users_lazer')->default(0)->change();
20+
$table->smallInteger('multiplayer_games')->default(0)->change();
21+
});
22+
}
23+
24+
public function down(): void
25+
{
26+
Schema::table('osu_banchostats', function (Blueprint $table) {
27+
$table->smallInteger('users_irc')->change();
28+
$table->mediumInteger('users_osu')->change();
29+
$table->unsignedMediumInteger('users_lazer')->change();
30+
$table->smallInteger('multiplayer_games')->change();
31+
});
32+
}
33+
};

Diff for: ‎resources/css/bem/supporter-icon.less

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
width: @user-card-icon-size;
2929
font-size: @user-card-icon-size / 2;
3030
border-radius: 50%;
31-
padding: unset;
31+
padding: 1px 0 0;
3232
}
3333

3434
&--user-list {

Diff for: ‎resources/js/components/supporter-icon.tsx

+8-7
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33

44
import { times } from 'lodash';
55
import * as React from 'react';
6-
import { classWithModifiers } from 'utils/css';
6+
import { classWithModifiers, Modifiers } from 'utils/css';
77
import { trans } from 'utils/lang';
88

99
interface Props {
1010
level?: number;
11-
modifiers?: string[];
11+
modifiers?: Modifiers;
1212
}
1313

14-
export const SupporterIcon = (props: Props) => {
15-
const className = classWithModifiers('supporter-icon', props.modifiers);
16-
14+
export default function SupporterIcon(props: Props) {
1715
return (
18-
<span className={className} title={trans('users.show.is_supporter')}>
16+
<span
17+
className={classWithModifiers('supporter-icon', props.modifiers)}
18+
title={trans('users.show.is_supporter')}
19+
>
1920
{
2021
times(props.level ?? 1, (n) => <span key={n} className='fas fa-heart' />)
2122
}
2223
</span>
2324
);
24-
};
25+
}

Diff for: ‎resources/js/components/user-card.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { PopupMenuPersistent } from './popup-menu-persistent';
1818
import { ReportReportable } from './report-reportable';
1919
import { Spinner } from './spinner';
2020
import StringWithComponent from './string-with-component';
21-
import { SupporterIcon } from './supporter-icon';
21+
import SupporterIcon from './supporter-icon';
2222
import TimeWithTooltip from './time-with-tooltip';
2323
import UserCardBrick from './user-card-brick';
2424
import UserGroupBadges from './user-group-badges';
@@ -228,7 +228,7 @@ export class UserCard extends React.PureComponent<Props, State> {
228228
<>
229229
{this.user.is_supporter && (
230230
<a className='user-card__icon' href={route('support-the-game')}>
231-
<SupporterIcon modifiers={['user-card']} />
231+
<SupporterIcon modifiers='user-card' />
232232
</a>
233233
)}
234234
<div className='user-card__icon'>
@@ -254,7 +254,7 @@ export class UserCard extends React.PureComponent<Props, State> {
254254
<div className='user-card__icons'>
255255
{this.user.is_supporter && (
256256
<a className='user-card__icon' href={route('support-the-game')}>
257-
<SupporterIcon level={this.user.support_level} modifiers={['user-list']} />
257+
<SupporterIcon level={this.user.support_level} modifiers='user-list' />
258258
</a>
259259
)}
260260

0 commit comments

Comments
 (0)