Skip to content

Commit

Permalink
recent tournaments played, API endpoint, WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Oct 21, 2024
1 parent c730bc7 commit 54497c7
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 22 deletions.
8 changes: 8 additions & 0 deletions app/controllers/Api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,14 @@ final class Api(
.byOwnerStream(user, status.flatMap(lila.core.tournament.Status.byId.get), MaxPerSecond(20), nb)
.mapAsync(1)(env.tournament.apiJsonView.fullJson)

def tournamentsByPlayer(name: UserStr, status: List[Int]) = Anon:
Found(meOrFetch(name).map(_.filterNot(_.is(UserId.lichess)))): user =>
val nb = getInt("nb") | Int.MaxValue
jsonDownload:
env.tournament.api
.byPlayerStream(user, status.flatMap(lila.core.tournament.Status.byId.get), MaxPerSecond(20), nb)
.mapAsync(1)(env.tournament.apiJsonView.fullJson)

def swissGames(id: SwissId) = AnonOrScoped(): ctx ?=>
Found(env.swiss.cache.swissCache.byId(id)): swiss =>
val config = GameApiV2.BySwissConfig(
Expand Down
1 change: 1 addition & 0 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ GET /api/puzzle/$id<\w{5}> controllers.Puzzle.apiShow(id: PuzzleId)
GET /api/puzzle/batch/:angle controllers.Puzzle.apiBatchSelect(angle)
POST /api/puzzle/batch/:angle controllers.Puzzle.apiBatchSolve(angle)
GET /api/user/:user/tournament/created controllers.Api.tournamentsByOwner(user: UserStr, status: List[Int])
GET /api/user/:user/tournament/played controllers.Api.tournamentsByPlayer(user: UserStr, status: List[Int])
GET /api/user/:user controllers.Api.user(user: UserStr)
GET /api/user/:user/activity controllers.Api.activity(user: UserStr)
GET /api/user/:user/note controllers.User.apiReadNote(user: UserStr)
Expand Down
76 changes: 54 additions & 22 deletions modules/tournament/src/main/LeaderboardApi.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package lila.tournament

import akka.stream.scaladsl.*
import reactivemongo.api.bson.*
import reactivemongo.akkastream.cursorProducer
import scalalib.Maths
import scalalib.paginator.{ AdapterLike, Paginator }

import lila.core.chess.Rank
import lila.core.perf.PerfId
import lila.db.dsl.{ *, given }
import lila.rating.PerfType
import lila.core.tournament.Status

final class LeaderboardApi(
repo: LeaderboardRepo,
val repo: LeaderboardRepo,
tournamentRepo: TournamentRepo
)(using Executor)
)(using Executor, akka.stream.Materializer)
extends lila.core.tournament.leaderboard.Api:

import LeaderboardApi.*
Expand Down Expand Up @@ -72,6 +75,45 @@ final class LeaderboardApi(
.inject(entries.map(_.tourId))
}

def byPlayerStream(
user: User,
status: List[Status],
perSecond: MaxPerSecond,
nb: Int
): Source[TourEntry, ?] =
repo.coll
.aggregateWith[Bdoc](): framework =>
import framework.*
val sort = framework.Descending("d")
aggregateByPlayer(user, framework, sort, nb, offset = 0).toList
.documentSource()
.mapConcat: doc =>
doc.getAsOpt[Tournament]("tour").toList

private def aggregateByPlayer(
user: User,
framework: repo.coll.AggregationFramework.type,
sort: framework.SortOrder,
nb: Int,
offset: Int = 0
): NonEmptyList[framework.PipelineOperator] =
import framework.*
NonEmptyList.of(
Match($doc("u" -> user.id)),
Sort(sort),
Skip(offset),
Limit(nb),
PipelineOperator(
$lookup.simple(
from = tournamentRepo.coll,
as = "tour",
local = "t",
foreign = "_id"
)
),
UnwindField("tour")
)

private def paginator(user: User, page: Int, sortBest: Boolean): Fu[Paginator[TourEntry]] =
Paginator(
currentPage = page,
Expand All @@ -83,28 +125,18 @@ final class LeaderboardApi(
repo.coll
.aggregateList(length, _.sec): framework =>
import framework.*
Match(selector) -> List(
Sort(if sortBest then Ascending("w") else Descending("d")),
Skip(offset),
Limit(length),
PipelineOperator(
$lookup.simple(
from = tournamentRepo.coll,
as = "tour",
local = "t",
foreign = "_id"
)
),
UnwindField("tour")
)
.map: docs =>
for
doc <- docs
entry <- doc.asOpt[Entry]
tour <- doc.getAsOpt[Tournament]("tour")
yield TourEntry(tour, entry)
val sort = if sortBest then framework.Ascending("w") else framework.Descending("d")
val pipe = aggregateByPlayer(user, framework, sort, length, offset)
pipe.head -> pipe.tail
.map(readTourEntries)
)

private def readTourEntries(docs: List[Bdoc]): List[TourEntry] = for
doc <- docs
entry <- doc.asOpt[Entry]
tour <- doc.getAsOpt[Tournament]("tour")
yield TourEntry(tour, entry)

object LeaderboardApi:

import lila.core.tournament.leaderboard.Ratio
Expand Down
1 change: 1 addition & 0 deletions modules/tournament/src/main/TournamentApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ final class TournamentApi(
pairingSystem: arena.PairingSystem,
callbacks: TournamentApi.Callbacks,
socket: TournamentSocket,
leaderboard: LeaderboardApi,
roundApi: lila.core.round.RoundApi,
gameProxy: lila.core.game.GameProxy,
trophyApi: lila.core.user.TrophyApi,
Expand Down

0 comments on commit 54497c7

Please sign in to comment.