download arena tournament results as CSV - closes #8869
parent
c8e280c51c
commit
63a89e6303
|
@ -235,15 +235,17 @@ final class Api(
|
|||
|
||||
def tournamentResults(id: String) =
|
||||
Action.async { implicit req =>
|
||||
env.tournament.tournamentRepo byId id flatMap {
|
||||
val csv = HTTPRequest.acceptsCsv(req) || get("as", req).has("csv")
|
||||
env.tournament.tournamentRepo byId id map {
|
||||
_ ?? { tour =>
|
||||
import lila.tournament.JsonView.playerResultWrites
|
||||
val nb = getInt("nb", req) | Int.MaxValue
|
||||
jsonStream {
|
||||
val source =
|
||||
env.tournament.api
|
||||
.resultStream(tour, MaxPerSecond(40), nb)
|
||||
.map(playerResultWrites.writes)
|
||||
}.fuccess
|
||||
.resultStream(tour, MaxPerSecond(40), getInt("nb", req) | Int.MaxValue)
|
||||
val result =
|
||||
if (csv) csvStream(lila.tournament.TournamentCsv(source))
|
||||
else jsonStream(source.map(lila.tournament.JsonView.playerResultWrites.writes))
|
||||
result.pipe(asAttachment(env.api.gameApiV2.filename(tour, if (csv) "csv" else "ndjson")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,12 +79,15 @@ final class GameApiV2(
|
|||
}
|
||||
|
||||
def filename(tour: Tournament, format: Format): String =
|
||||
filename(tour, format.toString.toLowerCase)
|
||||
|
||||
def filename(tour: Tournament, format: String): String =
|
||||
fileR.replaceAllIn(
|
||||
"lichess_tournament_%s_%s_%s.%s".format(
|
||||
Tag.UTCDate.format.print(tour.startsAt),
|
||||
tour.id,
|
||||
lila.common.String.slugify(tour.name),
|
||||
format.toString.toLowerCase
|
||||
format
|
||||
),
|
||||
"_"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package lila.tournament
|
||||
|
||||
import akka.stream.scaladsl.Source
|
||||
|
||||
object TournamentCsv {
|
||||
|
||||
def apply(results: Source[Player.Result, _]): Source[String, _] =
|
||||
Source(
|
||||
List(
|
||||
toCsv(
|
||||
"Rank",
|
||||
"Title",
|
||||
"Username",
|
||||
"Rating",
|
||||
"Score",
|
||||
"Performance",
|
||||
"Team"
|
||||
)
|
||||
)
|
||||
) concat
|
||||
results.map(apply)
|
||||
|
||||
def apply(p: Player.Result): String = p match {
|
||||
case Player.Result(player, user, rank) =>
|
||||
toCsv(
|
||||
rank.toString,
|
||||
~user.title,
|
||||
user.name,
|
||||
player.rating.toString,
|
||||
player.score.toString,
|
||||
player.performanceOption.??(_.toString),
|
||||
~player.team
|
||||
)
|
||||
}
|
||||
|
||||
private def toCsv(values: String*) = values mkString ","
|
||||
}
|
|
@ -227,7 +227,6 @@ function stats(ctrl: SwissCtrl): VNode | undefined {
|
|||
const s = ctrl.data.stats,
|
||||
noarg = ctrl.trans.noarg,
|
||||
slots = ctrl.data.round * ctrl.data.nbPlayers;
|
||||
console.log(ctrl.data);
|
||||
return s
|
||||
? h('div.swiss__stats', [
|
||||
h('h2', noarg('tournamentComplete')),
|
||||
|
|
|
@ -72,7 +72,18 @@ function stats(data: TournamentData, trans: Trans): VNode {
|
|||
download: true,
|
||||
},
|
||||
},
|
||||
'Download results'
|
||||
'Download results as NDJSON'
|
||||
),
|
||||
h(
|
||||
'a.text',
|
||||
{
|
||||
attrs: {
|
||||
'data-icon': 'x',
|
||||
href: `/api/tournament/${data.id}/results?as=csv`,
|
||||
download: true,
|
||||
},
|
||||
},
|
||||
'Download results as CSV'
|
||||
),
|
||||
h('br'),
|
||||
h(
|
||||
|
|
Loading…
Reference in New Issue