Skip to content

Commit

Permalink
Use new index for score leaderboard
Browse files Browse the repository at this point in the history
  • Loading branch information
nanaya committed Sep 8, 2023
1 parent d0b11a3 commit 880caf3
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 436 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ CLIENT_CHECK_VERSION=false
# TWITCH_CLIENT_SECRET=

# SCORES_ES_CACHE_DURATION=
# SCORES_ES_ENABLE_LEGACY_FILTER=true
# SCORES_EXPERIMENTAL_RANK_AS_DEFAULT=false
# SCORES_EXPERIMENTAL_RANK_AS_EXTRA=false
# SCORES_RANK_CACHE_LOCAL_SERVER=0
Expand Down
170 changes: 64 additions & 106 deletions app/Http/Controllers/BeatmapsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,66 @@ private static function baseScoreQuery(Beatmap $beatmap, $mode, $mods, $type = n
return $query;
}

private static function beatmapScores(string $id, ?string $scoreTransformerType, bool $isLegacy): array
{
$beatmap = Beatmap::findOrFail($id);
if ($beatmap->approved <= 0) {
return ['scores' => []];
}

$params = get_params(request()->all(), null, [
'limit:int',
'mode',
'mods:string[]',
'type:string',
], ['null_missing' => true]);

if ($params['mode'] !== null) {
$rulesetId = Beatmap::MODES[$params['mode']] ?? null;
if ($rulesetId === null) {
throw new InvariantException('invalid mode specified');
}
}
$rulesetId ??= $beatmap->playmode;
$mods = array_values(array_filter($params['mods'] ?? []));
$type = presence($params['type'], 'global');
$currentUser = auth()->user();

static::assertSupporterOnlyOptions($currentUser, $type, $mods);

$esFetch = new BeatmapScores([
'beatmap_ids' => [$beatmap->getKey()],
'is_legacy' => $isLegacy,
'limit' => $params['limit'],
'mods' => $mods,
'ruleset_id' => $rulesetId,
'type' => $type,
'user' => $currentUser,
]);
$scores = $esFetch->all()->loadMissing(['beatmap', 'performance', 'user.country', 'user.userProfileCustomization']);
$userScore = $esFetch->userBest();
$scoreTransformer = new ScoreTransformer($scoreTransformerType);

$results = [
'scores' => json_collection(
$scores,
$scoreTransformer,
static::DEFAULT_SCORE_INCLUDES
),
];

if (isset($userScore)) {
$results['user_score'] = [
'position' => $esFetch->rank($userScore),
'score' => json_item($userScore, $scoreTransformer, static::DEFAULT_SCORE_INCLUDES),
];
// TODO: remove this old camelCased json field
$results['userScore'] = $results['user_score'];
}

return $results;
}

public function __construct()
{
parent::__construct();
Expand Down Expand Up @@ -273,7 +333,7 @@ public function show($id)
}

/**
* Get Beatmap scores
* Get Beatmap scores (legacy)
*
* Returns the top scores for a beatmap
*
Expand All @@ -291,61 +351,14 @@ public function show($id)
*/
public function scores($id)
{
$beatmap = Beatmap::findOrFail($id);
if ($beatmap->approved <= 0) {
return ['scores' => []];
}

$params = get_params(request()->all(), null, [
'limit:int',
'mode:string',
'mods:string[]',
'type:string',
], ['null_missing' => true]);

$mode = presence($params['mode']) ?? $beatmap->mode;
$mods = array_values(array_filter($params['mods'] ?? []));
$type = presence($params['type']) ?? 'global';
$currentUser = auth()->user();

static::assertSupporterOnlyOptions($currentUser, $type, $mods);

$query = static::baseScoreQuery($beatmap, $mode, $mods, $type);

if ($currentUser !== null) {
// own score shouldn't be filtered by visibleUsers()
$userScore = (clone $query)->where('user_id', $currentUser->user_id)->first();
}

$scoreTransformer = new ScoreTransformer();

$results = [
'scores' => json_collection(
$query->visibleUsers()->forListing($params['limit']),
$scoreTransformer,
static::DEFAULT_SCORE_INCLUDES
),
];

if (isset($userScore)) {
$results['user_score'] = [
'position' => $userScore->userRank(compact('type', 'mods')),
'score' => json_item($userScore, $scoreTransformer, static::DEFAULT_SCORE_INCLUDES),
];
// TODO: remove this old camelCased json field
$results['userScore'] = $results['user_score'];
}

return $results;
return static::beatmapScores($id, null, true);
}

/**
* Get Beatmap scores (temp)
* Get Beatmap scores (non-legacy)
*
* Returns the top scores for a beatmap from newer client.
*
* This is a temporary endpoint.
*
* ---
*
* ### Response Format
Expand All @@ -360,62 +373,7 @@ public function scores($id)
*/
public function soloScores($id)
{
$beatmap = Beatmap::findOrFail($id);
if ($beatmap->approved <= 0) {
return ['scores' => []];
}

$params = get_params(request()->all(), null, [
'limit:int',
'mode',
'mods:string[]',
'type:string',
], ['null_missing' => true]);

if ($params['mode'] !== null) {
$rulesetId = Beatmap::MODES[$params['mode']] ?? null;
if ($rulesetId === null) {
throw new InvariantException('invalid mode specified');
}
}
$rulesetId ??= $beatmap->playmode;
$mods = array_values(array_filter($params['mods'] ?? []));
$type = presence($params['type'], 'global');
$currentUser = auth()->user();

static::assertSupporterOnlyOptions($currentUser, $type, $mods);

$esFetch = new BeatmapScores([
'beatmap_ids' => [$beatmap->getKey()],
'is_legacy' => false,
'limit' => $params['limit'],
'mods' => $mods,
'ruleset_id' => $rulesetId,
'type' => $type,
'user' => $currentUser,
]);
$scores = $esFetch->all()->loadMissing(['beatmap', 'performance', 'user.country', 'user.userProfileCustomization']);
$userScore = $esFetch->userBest();
$scoreTransformer = new ScoreTransformer(ScoreTransformer::TYPE_SOLO);

$results = [
'scores' => json_collection(
$scores,
$scoreTransformer,
static::DEFAULT_SCORE_INCLUDES
),
];

if (isset($userScore)) {
$results['user_score'] = [
'position' => $esFetch->rank($userScore),
'score' => json_item($userScore, $scoreTransformer, static::DEFAULT_SCORE_INCLUDES),
];
// TODO: remove this old camelCased json field
$results['userScore'] = $results['user_score'];
}

return $results;
return static::beatmapScores($id, ScoreTransformer::TYPE_SOLO, false);
}

public function updateOwner($id)
Expand Down
5 changes: 4 additions & 1 deletion app/Libraries/Search/ScoreSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function getQuery(): BoolQuery
{
$query = new BoolQuery();

if ($this->params->isLegacy !== null) {
if (config('osu.scores.es_enable_legacy_filter') && $this->params->isLegacy !== null) {
$query->filter(['term' => ['is_legacy' => $this->params->isLegacy]]);
}
if ($this->params->rulesetId !== null) {
Expand Down Expand Up @@ -141,6 +141,9 @@ private function addModsFilter(BoolQuery $query): void
? $modsHelper->allIds
: new Set(array_keys($modsHelper->mods[$this->params->rulesetId]));
$allMods->remove('PF', 'SD', 'MR');
if ($this->params->isLegacy || !config('osu.scores.es_enable_legacy_filter')) {
$allMods->remove('CL');
}

$allSearchMods = [];
foreach ($mods as $mod) {
Expand Down
1 change: 1 addition & 0 deletions config/osu.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
],
'scores' => [
'es_cache_duration' => 60 * (get_float(env('SCORES_ES_CACHE_DURATION')) ?? 0.5), // in minutes, converted to seconds
'es_enable_legacy_filter' => get_bool(env('SCORES_ES_ENABLE_LEGACY_FILTER')) ?? true,
'experimental_rank_as_default' => get_bool(env('SCORES_EXPERIMENTAL_RANK_AS_DEFAULT')) ?? false,
'experimental_rank_as_extra' => get_bool(env('SCORES_EXPERIMENTAL_RANK_AS_EXTRA')) ?? false,
'rank_cache' => [
Expand Down
Loading

0 comments on commit 880caf3

Please sign in to comment.