Skip to content

Commit

Permalink
Store multiplayer score in solo score table
Browse files Browse the repository at this point in the history
  • Loading branch information
nanaya committed Aug 3, 2023
1 parent 263d1a8 commit f7a561a
Show file tree
Hide file tree
Showing 27 changed files with 737 additions and 585 deletions.
117 changes: 57 additions & 60 deletions app/Http/Controllers/Multiplayer/Rooms/Playlist/ScoresController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@

namespace App\Http\Controllers\Multiplayer\Rooms\Playlist;

use App\Exceptions\InvariantException;
use App\Http\Controllers\Controller as BaseController;
use App\Libraries\ClientCheck;
use App\Models\Multiplayer\PlaylistItem;
use App\Models\Multiplayer\PlaylistItemUserHighScore;
use App\Models\Multiplayer\Room;
use App\Transformers\Multiplayer\ScoreTransformer;
use Carbon\Carbon;
use App\Models\Solo\Score;
use App\Transformers\ScoreTransformer;

/**
* @group Multiplayer
Expand Down Expand Up @@ -53,14 +52,15 @@ public function index($roomId, $playlistId)
[$highScores, $hasMore] = $playlist
->highScores()
->cursorSort($cursorHelper, cursor_from_params($params))
->with(ScoreTransformer::BASE_PRELOAD)
->with(ScoreTransformer::MULTIPLAYER_BASE_PRELOAD)
->limit($limit)
->getWithHasMore();

$transformer = ScoreTransformer::newSolo();
$scoresJson = json_collection(
$highScores->pluck('score'),
'Multiplayer\Score',
ScoreTransformer::BASE_INCLUDES
$transformer,
ScoreTransformer::MULTIPLAYER_BASE_INCLUDES
);
$total = $playlist->highScores()->count();

Expand All @@ -70,7 +70,7 @@ public function index($roomId, $playlistId)
$userHighScore = $playlist->highScores()->where('user_id', $user->getKey())->first();

if ($userHighScore !== null) {
$userScoreJson = json_item($userHighScore->score, 'Multiplayer\Score', ScoreTransformer::BASE_INCLUDES);
$userScoreJson = json_item($userHighScore->score, $transformer, ScoreTransformer::BASE_INCLUDES);
}
}

Expand Down Expand Up @@ -102,12 +102,16 @@ public function show($roomId, $playlistId, $id)
{
$room = Room::find($roomId) ?? abort(404, 'Invalid room id');
$playlistItem = $room->playlist()->find($playlistId) ?? abort(404, 'Invalid playlist id');
$score = $playlistItem->scores()->findOrFail($id);
$scoreLinks = $playlistItem->scoreLinks()->findOrFail($id);

return json_item(
$score,
'Multiplayer\Score',
array_merge(['position', 'scores_around'], ScoreTransformer::BASE_INCLUDES)
$scoreLinks,
ScoreTransformer::newSolo(),
[
...ScoreTransformer::MULTIPLAYER_BASE_INCLUDES,
'position',
'scores_around',
],
);
}

Expand All @@ -134,8 +138,12 @@ public function showUser($roomId, $playlistId, $userId)

return json_item(
$score,
'Multiplayer\Score',
array_merge(['position', 'scores_around'], ScoreTransformer::BASE_INCLUDES)
ScoreTransformer::newSolo(),
[
...ScoreTransformer::MULTIPLAYER_BASE_INCLUDES,
'position',
'scores_around',
],
);
}

Expand All @@ -149,64 +157,53 @@ public function store($roomId, $playlistId)
$user = auth()->user();
$params = request()->all();

ClientCheck::findBuild($user, $params);
$buildId = ClientCheck::findBuild($user, $params)?->getKey()
?? config('osu.client.default_build_id');

$score = $room->startPlay($user, $playlistItem);
$score = $room->startPlay($user, $playlistItem, $buildId);

return json_item(
$score,
'Multiplayer\Score'
);
return json_item($score, ScoreTransformer::newSolo());
}

/**
* @group Undocumented
*/
public function update($roomId, $playlistId, $scoreId)
{
$room = Room::findOrFail($roomId);

$playlistItem = $room->playlist()
->where('id', $playlistId)
->firstOrFail();

$roomScore = $playlistItem->scores()
->where('user_id', auth()->user()->getKey())
->where('id', $scoreId)
->firstOrFail();

try {
$score = $room->completePlay(
$roomScore,
$this->extractScoreParams(request()->all(), $playlistItem)
);

return json_item(
$score,
'Multiplayer\Score',
array_merge(['position', 'scores_around'], ScoreTransformer::BASE_INCLUDES)
);
} catch (InvariantException $e) {
return error_popup($e->getMessage(), $e->getStatusCode());
$scoreLink = \DB::transaction(function () use ($roomId, $playlistId, $scoreId) {
$room = Room::findOrFail($roomId);

$scoreLink = $room
->scoreLinks()
->where([
'user_id' => \Auth::id(),
'playlist_item_id' => $playlistId,
])->with('playlistItem')
->lockForUpdate()
->findOrFail($scoreId);

$params = Score::extractParams(\Request::all(), $scoreLink);

$room->completePlay($scoreLink, $params);

return $scoreLink;
});

$score = $scoreLink->score;
$transformer = ScoreTransformer::newSolo();
if ($score->wasRecentlyCreated) {
$scoreJson = json_item($score, $transformer);
$score::queueForProcessing($scoreJson);
}
}

private function extractScoreParams(array $params, PlaylistItem $playlistItem)
{
$mods = app('mods')->parseInputArray(
$playlistItem->ruleset_id,
$params['mods'] ?? [],
return json_item(
$scoreLink,
$transformer,
[
...ScoreTransformer::MULTIPLAYER_BASE_INCLUDES,
'position',
'scores_around',
],
);

return [
'rank' => $params['rank'] ?? null,
'total_score' => get_int($params['total_score'] ?? null),
'accuracy' => get_float($params['accuracy'] ?? null),
'max_combo' => get_int($params['max_combo'] ?? null),
'ended_at' => Carbon::now(),
'passed' => get_bool($params['passed'] ?? null),
'mods' => $mods,
'statistics' => $params['statistics'] ?? null,
];
}
}
22 changes: 1 addition & 21 deletions app/Http/Controllers/Solo/ScoresController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,7 @@ public function store($beatmapId, $tokenId)

// return existing score otherwise (assuming duplicated submission)
if ($scoreToken->score_id === null) {
$params = get_params(request()->all(), null, [
'accuracy:float',
'max_combo:int',
'maximum_statistics:array',
'mods:array',
'passed:bool',
'rank:string',
'statistics:array',
'total_score:int',
]);

$params = array_merge($params, [
'beatmap_id' => $scoreToken->beatmap_id,
'build_id' => $scoreToken->build_id,
'ended_at' => json_time(now()),
'mods' => app('mods')->parseInputArray($scoreToken->ruleset_id, $params['mods'] ?? []),
'ruleset_id' => $scoreToken->ruleset_id,
'started_at' => $scoreToken->created_at_json,
'user_id' => $scoreToken->user_id,
]);

$params = Score::extractParams(\Request::all(), $scoreToken);
$score = Score::createFromJsonOrExplode($params);
$score->createLegacyEntryOrExplode();
$scoreToken->fill(['score_id' => $score->getKey()])->saveOrExplode();
Expand Down
2 changes: 2 additions & 0 deletions app/Libraries/MorphMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use App\Models\Comment;
use App\Models\Forum;
use App\Models\LegacyMatch;
use App\Models\Multiplayer\ScoreLink as MultiplayerScoreLink;
use App\Models\NewsPost;
use App\Models\Score;
use App\Models\Solo;
Expand All @@ -32,6 +33,7 @@ class MorphMap
Forum\Topic::class => 'forum_topic',
LegacyMatch\Score::class => 'legacy_match_score',
Message::class => 'message',
MultiplayerScoreLink::class => 'multiplayer_score_link',
NewsPost::class => 'news_post',
Score\Best\Fruits::class => 'score_best_fruits',
Score\Best\Mania::class => 'score_best_mania',
Expand Down
4 changes: 2 additions & 2 deletions app/Models/Contest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ public function assertVoteRequirement(?User $user): void
$mustPass = $requirement['must_pass'] ?? true;
$beatmapIdsQuery = Multiplayer\PlaylistItem::whereIn('room_id', $roomIds)->select('beatmap_id');
$requiredBeatmapsetCount = Beatmap::whereIn('beatmap_id', $beatmapIdsQuery)->distinct('beatmapset_id')->count();
$playedBeatmapIdsQuery = Multiplayer\Score
$playedBeatmapIdsQuery = Multiplayer\ScoreLink
::whereIn('room_id', $roomIds)
->where(['user_id' => $user->getKey()])
->completed()
->select('beatmap_id');
if ($mustPass) {
$playedBeatmapIdsQuery->where('passed', true);
$playedBeatmapIdsQuery->whereHas('playlistItemUserHighScore');
}
$playedBeatmapsetCount = Beatmap::whereIn('beatmap_id', $playedBeatmapIdsQuery)->distinct('beatmapset_id')->count();

Expand Down
10 changes: 5 additions & 5 deletions app/Models/Multiplayer/PlaylistItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @property Room $room
* @property int $room_id
* @property int|null $ruleset_id
* @property \Illuminate\Database\Eloquent\Collection $scores Score
* @property \Illuminate\Database\Eloquent\Collection $scoreLinks ScoreLink
* @property \Carbon\Carbon|null $updated_at
* @property bool expired
* @property \Carbon\Carbon|null $played_at
Expand Down Expand Up @@ -96,17 +96,17 @@ public function highScores()
return $this->hasMany(PlaylistItemUserHighScore::class);
}

public function scores()
public function scoreLinks()
{
return $this->hasMany(Score::class);
return $this->hasMany(ScoreLink::class);
}

public function topScores()
{
return $this->highScores()
->with('score')
->with('scoreLink.score')
->orderBy('total_score', 'desc')
->orderBy('score_id', 'asc');
->orderBy('score_link_id', 'asc');
}

private function assertValidMaxAttempts()
Expand Down
30 changes: 16 additions & 14 deletions app/Models/Multiplayer/PlaylistItemUserHighScore.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
* @property int $id
* @property int $playlist_item_id
* @property float|null $pp
* @property int $score_id
* @property Score $score
* @property int $total_score
* @property int $score_link_id
* @property ScoreLink $scoreLink
* @property \Carbon\Carbon $updated_at
* @property int $user_id
*/
Expand All @@ -30,42 +29,45 @@ class PlaylistItemUserHighScore extends Model
const SORTS = [
'score_desc' => [
['column' => 'total_score', 'order' => 'DESC'],
['column' => 'score_id', 'order' => 'ASC'],
['column' => 'score_link_id', 'order' => 'ASC'],
],
'score_asc' => [
['column' => 'total_score', 'order' => 'ASC'],
['column' => 'score_id', 'order' => 'DESC'],
['column' => 'score_link_id', 'order' => 'DESC'],
],
];

const DEFAULT_SORT = 'score_desc';

protected $table = 'multiplayer_scores_high';

public static function lookupOrDefault(Score $score): static
public static function lookupOrDefault(ScoreLink $scoreLink): static
{
return static::firstOrNew([
'playlist_item_id' => $score->playlist_item_id,
'user_id' => $score->user_id,
'playlist_item_id' => $scoreLink->playlist_item_id,
'user_id' => $scoreLink->user_id,
], [
'accuracy' => 0,
'pp' => 0,
'total_score' => 0,
]);
}

public function score()
public function scoreLink()
{
return $this->belongsTo(Score::class);
return $this->belongsTo(ScoreLink::class);
}

public function updateWithScore(Score $score): void
public function updateWithScoreLink(ScoreLink $scoreLink): void
{
$score = $scoreLink->score;

$this->fill([
'accuracy' => $score->accuracy,
'accuracy' => $score->data->accuracy,
'pp' => $score->pp,
'score_id' => $score->getKey(),
'total_score' => $score->total_score,
'score_id' => 0, // TODO: remove after migrated
'score_link_id' => $scoreLink->getKey(),
'total_score' => $score->data->totalScore,
])->save();
}
}
Loading

0 comments on commit f7a561a

Please sign in to comment.