forked from lichess-org/lila
-
Notifications
You must be signed in to change notification settings - Fork 0
/
JsonView.scala
103 lines (91 loc) · 3.2 KB
/
JsonView.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
package lila.simul
import play.api.libs.json._
import lila.common.LightUser
import lila.game.{ Game, GameRepo }
import lila.user.User
final class JsonView(
getLightUser: LightUser.Getter,
proxyGame: Game.ID => Fu[Option[Game]]
) {
private def fetchGames(simul: Simul) =
if (simul.isFinished) GameRepo gamesFromSecondary simul.gameIds
else simul.gameIds.map(proxyGame).sequenceFu.map(_.flatten)
def apply(simul: Simul, team: Option[SimulTeam]): Fu[JsObject] = for {
games <- fetchGames(simul)
lightHost <- getLightUser(simul.hostId)
applicants <- simul.applicants.sortBy(-_.player.rating).map(applicantJson).sequenceFu
pairingOptions <- simul.pairings
.sortBy(-_.player.rating)
.map(pairingJson(games, simul.hostId))
.sequenceFu
pairings = pairingOptions.flatten
} yield Json.obj(
"id" -> simul.id,
"host" -> lightHost.map { host =>
Json.obj(
"id" -> host.id,
"username" -> host.name,
"patron" -> host.isPatron,
"title" -> host.title,
"rating" -> simul.hostRating,
"gameId" -> simul.hostGameId
)
},
"name" -> simul.name,
"fullName" -> simul.fullName,
"variants" -> simul.variants.map(variantJson(chess.Speed(simul.clock.config.some))),
"applicants" -> applicants,
"pairings" -> pairings,
"isCreated" -> simul.isCreated,
"isRunning" -> simul.isRunning,
"isFinished" -> simul.isFinished,
"quote" -> lila.quote.Quote.one(simul.id),
"text" -> simul.text
).add("team", team)
private def variantJson(speed: chess.Speed)(v: chess.variant.Variant) = Json.obj(
"key" -> v.key,
"icon" -> lila.game.PerfPicker.perfType(speed, v, none).map(_.iconChar.toString),
"name" -> v.name
)
private def playerJson(player: SimulPlayer): Fu[JsObject] =
getLightUser(player.user) map { light =>
Json.obj(
"id" -> player.user,
"variant" -> player.variant.key,
"rating" -> player.rating
).add("username" -> light.map(_.name))
.add("title" -> light.map(_.title))
.add("provisional" -> player.provisional.filter(identity))
.add("patron" -> light.??(_.isPatron))
}
private def applicantJson(app: SimulApplicant): Fu[JsObject] =
playerJson(app.player) map { player =>
Json.obj(
"player" -> player,
"accepted" -> app.accepted
)
}
private def gameJson(hostId: User.ID, g: Game) = Json.obj(
"id" -> g.id,
"status" -> g.status.id,
"fen" -> (chess.format.Forsyth exportBoard g.board),
"lastMove" -> ~g.lastMoveKeys,
"orient" -> g.playerByUserId(hostId).map(_.color)
)
private def pairingJson(games: List[Game], hostId: String)(p: SimulPairing): Fu[Option[JsObject]] =
games.find(_.id == p.gameId) ?? { game =>
playerJson(p.player) map { player =>
Json.obj(
"player" -> player,
"hostColor" -> p.hostColor,
"winnerColor" -> p.winnerColor,
"wins" -> p.wins, // can't be normalized because BC
"game" -> gameJson(hostId, game)
).some
}
}
private implicit val colorWriter: Writes[chess.Color] = Writes { c =>
JsString(c.name)
}
private implicit val simulTeamWriter = Json.writes[SimulTeam]
}