forked from lichess-org/lila
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RoundApi.scala
142 lines (127 loc) · 5.44 KB
/
RoundApi.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package lila.api
import play.api.libs.json._
import chess.format.pgn.Pgn
import lila.analyse.{ Analysis, Info }
import lila.common.LightUser
import lila.common.PimpedJson._
import lila.game.{ Pov, Game, GameRepo }
import lila.pref.Pref
import lila.round.{ JsonView, Forecast }
import lila.security.Granter
import lila.simul.Simul
import lila.tournament.{ Tournament, SecondsToDoFirstMove, TourAndRanks }
import lila.user.User
private[api] final class RoundApi(
jsonView: JsonView,
noteApi: lila.round.NoteApi,
forecastApi: lila.round.ForecastApi,
analysisApi: AnalysisApi,
bookmarkApi: lila.bookmark.BookmarkApi,
getTourAndRanks: Game => Fu[Option[TourAndRanks]],
getSimul: Simul.ID => Fu[Option[Simul]],
lightUser: String => Option[LightUser]) {
def player(pov: Pov, apiVersion: Int)(implicit ctx: Context): Fu[JsObject] =
GameRepo.initialFen(pov.game) flatMap { initialFen =>
jsonView.playerJson(pov, ctx.pref, apiVersion, ctx.me,
initialFen = initialFen,
withBlurs = ctx.me ?? Granter(_.ViewBlurs)) zip
getTourAndRanks(pov.game) zip
(pov.game.simulId ?? getSimul) zip
(ctx.me ?? (me => noteApi.get(pov.gameId, me.id))) zip
forecastApi.loadForDisplay(pov) map {
case ((((json, tourOption), simulOption), note), forecast) => (
blindMode _ compose
withTournament(pov, tourOption)_ compose
withSimul(pov, simulOption)_ compose
withSteps(pov, none, initialFen)_ compose
withNote(note)_ compose
withBookmark(ctx.me ?? { bookmarkApi.bookmarked(pov.game, _) })_ compose
withForecastCount(forecast.map(_.steps.size))_
)(json)
}
}
def watcher(pov: Pov, apiVersion: Int, tv: Option[lila.round.OnTv],
analysis: Option[(Pgn, Analysis)] = None,
initialFenO: Option[Option[String]] = None,
withMoveTimes: Boolean = false)(implicit ctx: Context): Fu[JsObject] =
initialFenO.fold(GameRepo initialFen pov.game)(fuccess) flatMap { initialFen =>
jsonView.watcherJson(pov, ctx.pref, apiVersion, ctx.me, tv,
withBlurs = ctx.me ?? Granter(_.ViewBlurs),
initialFen = initialFen,
withMoveTimes = withMoveTimes) zip
getTourAndRanks(pov.game) zip
(pov.game.simulId ?? getSimul) zip
(ctx.me ?? (me => noteApi.get(pov.gameId, me.id))) map {
case (((json, tourOption), simulOption), note) => (
blindMode _ compose
withTournament(pov, tourOption)_ compose
withSimul(pov, simulOption)_ compose
withNote(note)_ compose
withBookmark(ctx.me ?? { bookmarkApi.bookmarked(pov.game, _) })_ compose
withSteps(pov, analysis, initialFen)_ compose
withAnalysis(analysis)_
)(json)
}
}
def userAnalysisJson(pov: Pov, pref: Pref, initialFen: Option[String], orientation: chess.Color, owner: Boolean) =
owner.??(forecastApi loadForDisplay pov).flatMap { fco =>
jsonView.userAnalysisJson(pov, pref, orientation, owner = owner) map
withSteps(pov, none, initialFen)_ map
withForecast(pov, owner, fco)_
}
private def withSteps(pov: Pov, a: Option[(Pgn, Analysis)], initialFen: Option[String])(obj: JsObject) =
obj + ("steps" -> lila.round.StepBuilder(
id = pov.game.id,
pgnMoves = pov.game.pgnMoves,
variant = pov.game.variant,
a = a,
initialFen = initialFen | pov.game.variant.initialFen))
private def withNote(note: String)(json: JsObject) =
if (note.isEmpty) json else json + ("note" -> JsString(note))
private def withBookmark(v: Boolean)(json: JsObject) =
if (v) json + ("bookmarked" -> JsBoolean(true)) else json
private def withForecastCount(count: Option[Int])(json: JsObject) =
count.filter(0 !=).fold(json) { c =>
json + ("forecastCount" -> JsNumber(c))
}
private def withForecast(pov: Pov, owner: Boolean, fco: Option[Forecast])(json: JsObject) =
if (pov.game.forecastable && owner) json + (
"forecast" -> {
if (pov.forecastable) fco.fold[JsValue](Json.obj("none" -> true)) { fc =>
import Forecast.forecastJsonWriter
Json toJson fc
}
else Json.obj("onMyTurn" -> true)
})
else json
private def withAnalysis(a: Option[(Pgn, Analysis)])(json: JsObject) = a.fold(json) {
case (pgn, analysis) => json + ("analysis" -> Json.obj(
"white" -> analysisApi.player(chess.Color.White)(analysis),
"black" -> analysisApi.player(chess.Color.Black)(analysis)
))
}
private def withTournament(pov: Pov, tourOption: Option[TourAndRanks])(json: JsObject) =
tourOption.fold(json) { data =>
json + ("tournament" -> Json.obj(
"id" -> data.tour.id,
"name" -> data.tour.name,
"running" -> data.tour.isStarted,
"berserkable" -> data.tour.berserkable,
"nbSecondsForFirstMove" -> SecondsToDoFirstMove.secondsToMoveFor(data.tour),
"ranks" -> Json.obj(
"white" -> data.whiteRank,
"black" -> data.blackRank)
))
}
private def withSimul(pov: Pov, simulOption: Option[Simul])(json: JsObject) =
simulOption.fold(json) { simul =>
json + ("simul" -> Json.obj(
"id" -> simul.id,
"hostId" -> simul.hostId,
"name" -> simul.name,
"nbPlaying" -> simul.playingPairings.size
))
}
private def blindMode(js: JsObject)(implicit ctx: Context) =
ctx.blindMode.fold(js + ("blind" -> JsBoolean(true)), js)
}