api to export games of a swiss tournament

pull/6604/head
Thibault Duplessis 2020-05-11 12:34:44 -06:00
parent 8309a9d6b5
commit de1d0005eb
4 changed files with 89 additions and 0 deletions

View File

@ -276,6 +276,31 @@ final class Api(
}
}
def swissGames(id: String) =
Action.async { req =>
env.swiss.api byId lila.swiss.Swiss.Id(id) flatMap {
_ ?? { swiss =>
val config = GameApiV2.BySwissConfig(
swissId = swiss.id,
format = GameApiV2.Format byRequest req,
flags = gameC.requestPgnFlags(req, extended = false),
perSecond = MaxPerSecond(20)
)
GlobalConcurrencyLimitPerIP(HTTPRequest lastRemoteAddress req)(
env.api.gameApiV2.exportBySwiss(config)
) { source =>
val filename = env.api.gameApiV2.filename(swiss, config.format)
Ok.chunked(source)
.withHeaders(
noProxyBufferHeader,
CONTENT_DISPOSITION -> s"attachment; filename=$filename"
)
.as(gameC gameContentType config)
}.fuccess
}
}
}
def gamesByUsersStream =
AnonOrScopedBody(parse.tolerantText)()(
anon = gamesByUsers(300),

View File

@ -555,6 +555,7 @@ GET /api/tournament/:id/games controllers.Api.tournamentGames(id: Strin
GET /api/tournament/:id/results controllers.Api.tournamentResults(id: String)
POST /api/tournament controllers.Tournament.apiCreate
POST /api/swiss/new/:teamId controllers.Swiss.apiCreate(teamId: String)
GET /api/swiss/:id/games controllers.Api.swissGames(id: String)
GET /api/simul controllers.Simul.apiList
GET /api/status controllers.Api.status
GET /api/users/status controllers.Api.usersStatus

View File

@ -22,6 +22,7 @@ final class GameApiV2(
pgnDump: PgnDump,
gameRepo: lila.game.GameRepo,
pairingRepo: lila.tournament.PairingRepo,
swissApi: lila.swiss.SwissApi,
analysisRepo: lila.analyse.AnalysisRepo,
getLightUser: LightUser.Getter
)(implicit ec: scala.concurrent.ExecutionContext, system: akka.actor.ActorSystem) {
@ -73,6 +74,16 @@ final class GameApiV2(
),
"_"
)
def filename(swiss: lila.swiss.Swiss, format: Format): String =
fileR.replaceAllIn(
"lichess_swiss_%s_%s_%s.%s".format(
Tag.UTCDate.format.print(swiss.startsAt),
swiss.id,
lila.common.String.slugify(swiss.name),
format.toString.toLowerCase
),
"_"
)
def exportByUser(config: ByUserConfig): Source[String, _] =
gameRepo
@ -138,6 +149,37 @@ final class GameApiV2(
}
}
def exportBySwiss(config: BySwissConfig): Source[String, _] =
swissApi
.pairingCursor(
swissId = config.swissId,
batchSize = config.perSecond.value
)
.documentSource()
.grouped(config.perSecond.value)
.throttle(1, 1 second)
.mapAsync(1) { pairings =>
gameRepo.gameOptionsFromSecondary(pairings.map(_.gameId)) map {
_.zip(pairings) collect {
case (Some(game), pairing) => game -> pairing
}
}
}
.mapConcat(identity)
.mapAsync(4) {
case (game, pairing) => enrich(config.flags)(game) dmap { _ -> pairing }
}
.mapAsync(4) {
case ((game, fen, analysis), pairing) =>
config.format match {
case Format.PGN => pgnDump.formatter(config.flags)(game, fen, analysis)
case Format.JSON =>
toJson(game, fen, analysis, config.flags) dmap { json =>
s"${Json.stringify(json)}\n"
}
}
}
private def preparationFlow(config: Config) =
Flow[Game]
.mapAsync(4)(enrich(config.flags))
@ -277,4 +319,11 @@ object GameApiV2 {
flags: WithFlags,
perSecond: MaxPerSecond
) extends Config
case class BySwissConfig(
swissId: lila.swiss.Swiss.Id,
format: Format,
flags: WithFlags,
perSecond: MaxPerSecond
) extends Config
}

View File

@ -2,6 +2,7 @@ package lila.swiss
import org.joda.time.DateTime
import ornicar.scalalib.Zero
import reactivemongo.akkastream.{ cursorProducer, AkkaStreamCursor }
import reactivemongo.api._
import reactivemongo.api.bson._
import scala.concurrent.duration._
@ -139,6 +140,19 @@ final class SwissApi(
.list[SwissPairing]()
}
def pairingCursor(
swissId: Swiss.Id,
batchSize: Int = 0,
readPreference: ReadPreference = ReadPreference.secondaryPreferred
): AkkaStreamCursor[SwissPairing] =
SwissPairing.fields { f =>
colls.pairing.ext
.find($doc(f.swissId -> swissId))
.sort($sort asc f.round)
.batchSize(batchSize)
.cursor[SwissPairing](readPreference)
}
def featuredInTeam(teamId: TeamID): Fu[List[Swiss]] =
cache.featuredInTeam.get(teamId) flatMap { ids =>
colls.swiss.byOrderedIds[Swiss, Swiss.Id](ids)(_.id)