normalize JSON API for use in mobile client
This commit is contained in:
parent
8b14db829c
commit
c007cd23e6
|
@ -181,7 +181,9 @@ object Setup extends LilaController with TheftPrevention with play.api.http.Cont
|
|||
config => op(config)(ctx) flatMap {
|
||||
case (pov, call) => negotiate(
|
||||
html = fuccess(redirectPov(pov, call)),
|
||||
api = fuccess(Created(lila.api.JsonView.pov(pov)) as JSON)
|
||||
api = Env.round version pov.gameId map { v =>
|
||||
Created(Env.round.jsonView.playerJson(pov, v, ctx.pref)) as JSON
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -16,10 +16,7 @@ goodies = views.html.game.infoBox(pov, tour),
|
|||
chat = chat.map(c => base.chat(c, trans.chatRoom.str())),
|
||||
underchat = underchat.some,
|
||||
signedJs = hijackEnabled(pov.game) option routes.Round.signedJs(pov.gameId) map (_.toString)) {
|
||||
<div class="lichess_game clearfix lichess_player_@color not_spectator@if(!ctx.pref.captured) { hide_captured }"
|
||||
data-socket-url="@routes.Round.websocketPlayer(fullId)"
|
||||
data-table-url="@routes.Round.tablePlayer(fullId)"
|
||||
data-end-url="@routes.Round.endPlayer(fullId)">
|
||||
<div class="lichess_game clearfix lichess_player_@color not_spectator@if(!ctx.pref.captured) { hide_captured }">
|
||||
<div class="lichess_board_wrap">
|
||||
<div class="lichess_board with_marks">@Html(lila.app.ui.Board.render(pov))</div>
|
||||
<div id="premove_alert">@trans.premoveEnabledClickAnywhereToCancel()</div>
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
@import pov._
|
||||
|
||||
<div class="lichess_game clearfix lichess_player_@color"
|
||||
data-socket-url="@routes.Round.websocketWatcher(gameId, color.name)"
|
||||
data-table-url="@routes.Round.tableWatcher(gameId, color.name)"
|
||||
data-end-url="@routes.Round.endWatcher(gameId, color.name)">
|
||||
<div class="lichess_game clearfix lichess_player_@color">
|
||||
<div class="lichess_board_wrap">
|
||||
<div class="lichess_board with_marks">@Html(lila.app.ui.Board.render(pov))</div>
|
||||
<div id="dont_touch">@trans.youAreViewingThisGameAsASpectator()</div>
|
||||
|
|
|
@ -35,11 +35,11 @@ All websocket messages, sent or received, are composed of a type `t` and data `d
|
|||
## Connect to a game as a player
|
||||
|
||||
```javascript
|
||||
var playerId; // obtained from game creation API
|
||||
var baseUrl; // obtained from game creation API (`url.socket`)
|
||||
var clientId; // created by the client
|
||||
var socketVersion = 0; // last message version number seen on this socket. Starts at zero.
|
||||
|
||||
var socketUrl = 'http://socket.en.l.org:9021/' + playerId + '/socket?sri=' + clientId + '&version=' + socketVersion;
|
||||
var socketUrl = 'http://socket.en.l.org:9021' + baseUrl + '?sri=' + clientId + '&version=' + socketVersion;
|
||||
|
||||
var socket = new WebSocket(socketUrl);
|
||||
```
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package lila.api
|
||||
|
||||
import play.api.http.ContentTypes.JSON
|
||||
import play.api.libs.json.{ JsObject, Json => J }
|
||||
import play.api.mvc.Results.Ok
|
||||
|
||||
import chess.format.Forsyth
|
||||
import lila.game.{ Game, Pov }
|
||||
|
||||
object JsonView {
|
||||
|
||||
def pov(p: Pov) = J.obj(
|
||||
"game" -> game(p.game),
|
||||
"player" -> player(p))
|
||||
|
||||
private def game(g: Game) = J.obj(
|
||||
"id" -> g.id,
|
||||
"fen" -> (Forsyth >> g.toChess))
|
||||
|
||||
private def player(p: Pov) = J.obj(
|
||||
"id" -> p.fullId,
|
||||
"color" -> p.color.name)
|
||||
}
|
|
@ -139,9 +139,10 @@ final class Env(
|
|||
private lazy val reminder = new Reminder(db(CollectionReminder))
|
||||
def nowPlaying = reminder.nowPlaying
|
||||
|
||||
private[round] def animationDelay = AnimationDelay
|
||||
private[round] def moretimeSeconds = Moretime.toSeconds
|
||||
|
||||
lazy val jsonView = new JsonView(AnimationDelay)
|
||||
|
||||
{
|
||||
import scala.concurrent.duration._
|
||||
|
||||
|
|
101
modules/round/src/main/JsonView.scala
Normal file
101
modules/round/src/main/JsonView.scala
Normal file
|
@ -0,0 +1,101 @@
|
|||
package lila.round
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import scala.math.{ min, max, round }
|
||||
|
||||
import play.api.libs.json.Json
|
||||
|
||||
import lila.common.PimpedJson._
|
||||
import lila.game.{ Pov, Game }
|
||||
import lila.pref.Pref
|
||||
|
||||
final class JsonView(baseAnimationDelay: Duration) {
|
||||
|
||||
def playerJson(pov: Pov, version: Int, pref: Pref) = {
|
||||
import pov._
|
||||
Json.obj(
|
||||
"game" -> Json.obj(
|
||||
"id" -> gameId,
|
||||
"started" -> game.started,
|
||||
"finished" -> game.finishedOrAborted,
|
||||
"clock" -> game.hasClock,
|
||||
"clockRunning" -> game.isClockRunning,
|
||||
"player" -> game.turnColor.name,
|
||||
"turns" -> game.turns,
|
||||
"startedAtTurn" -> game.startedAtTurn,
|
||||
"lastMove" -> game.castleLastMoveTime.lastMoveString),
|
||||
"player" -> Json.obj(
|
||||
"id" -> playerId,
|
||||
"color" -> player.color.name,
|
||||
"version" -> version,
|
||||
"spectator" -> false
|
||||
),
|
||||
"opponent" -> Json.obj(
|
||||
"color" -> opponent.color.name,
|
||||
"ai" -> opponent.isAi
|
||||
),
|
||||
"url" -> Json.obj(
|
||||
"socket" -> s"/$fullId/socket",
|
||||
"end" -> s"/$fullId/end",
|
||||
"table" -> s"/$fullId/table"
|
||||
),
|
||||
"pref" -> Json.obj(
|
||||
"animationDelay" -> animationDelay(pov),
|
||||
"autoQueen" -> pref.autoQueen,
|
||||
"autoThreefold" -> pref.autoThreefold,
|
||||
"clockTenths" -> pref.clockTenths,
|
||||
"clockBar" -> pref.clockBar,
|
||||
"enablePremove" -> pref.premove
|
||||
),
|
||||
"possibleMoves" -> possibleMoves(pov),
|
||||
"tournamentId" -> game.tournamentId
|
||||
).noNull
|
||||
}
|
||||
|
||||
def watcherJson(pov: Pov, version: Int, tv: Boolean, pref: Pref) = {
|
||||
import pov._
|
||||
Json.obj(
|
||||
"game" -> Json.obj(
|
||||
"id" -> gameId,
|
||||
"started" -> game.started,
|
||||
"finished" -> game.finishedOrAborted,
|
||||
"clock" -> game.hasClock,
|
||||
"clockRunning" -> game.isClockRunning,
|
||||
"player" -> game.turnColor.name,
|
||||
"turns" -> game.turns,
|
||||
"startedAtTurn" -> game.startedAtTurn,
|
||||
"lastMove" -> game.castleLastMoveTime.lastMoveString),
|
||||
"player" -> Json.obj(
|
||||
"color" -> color.name,
|
||||
"version" -> version,
|
||||
"spectator" -> true),
|
||||
"opponent" -> Json.obj(
|
||||
"color" -> opponent.color.name,
|
||||
"ai" -> opponent.isAi),
|
||||
"url" -> Json.obj(
|
||||
"socket" -> s"/$gameId/${color.name}/socket",
|
||||
"end" -> s"/$gameId/${color.name}/end",
|
||||
"table" -> s"/$gameId/${color.name}/table"
|
||||
),
|
||||
"pref" -> Json.obj(
|
||||
"animationDelay" -> animationDelay(pov),
|
||||
"clockTenths" -> pref.clockTenths,
|
||||
"clockBar" -> pref.clockBar
|
||||
),
|
||||
"possibleMoves" -> possibleMoves(pov),
|
||||
"tv" -> tv
|
||||
).noNull
|
||||
}
|
||||
|
||||
private def possibleMoves(pov: Pov) = (pov.game playableBy pov.player) option {
|
||||
pov.game.toChess.situation.destinations map {
|
||||
case (from, dests) => from.key -> dests.mkString
|
||||
}
|
||||
}
|
||||
|
||||
private def animationDelay(pov: Pov) = round {
|
||||
baseAnimationDelay.toMillis * max(0, min(1.2,
|
||||
((pov.game.estimateTotalTime - 60) / 60) * 0.2
|
||||
))
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
package lila.round
|
||||
|
||||
import scala.math.{ min, max, round }
|
||||
|
||||
import play.api.libs.json.Json
|
||||
|
||||
import lila.game.Game
|
||||
import lila.game.Pov
|
||||
import lila.game.{ Pov, Game }
|
||||
import lila.pref.Pref
|
||||
import lila.round.Env.{ current => roundEnv }
|
||||
import lila.user.UserContext
|
||||
|
||||
trait RoundHelper {
|
||||
|
||||
|
@ -16,80 +12,9 @@ trait RoundHelper {
|
|||
|
||||
def moretimeSeconds = roundEnv.moretimeSeconds
|
||||
|
||||
def gameAnimationDelay = roundEnv.animationDelay
|
||||
def roundPlayerJsData(pov: Pov, version: Int, pref: Pref) =
|
||||
roundEnv.jsonView.playerJson(pov, version, pref)
|
||||
|
||||
def roundPlayerJsData(pov: Pov, version: Int, pref: Pref)(implicit ctx: UserContext) = {
|
||||
import pov._
|
||||
Json.obj(
|
||||
"game" -> Json.obj(
|
||||
"id" -> gameId,
|
||||
"started" -> game.started,
|
||||
"finished" -> game.finishedOrAborted,
|
||||
"clock" -> game.hasClock,
|
||||
"clockRunning" -> game.isClockRunning,
|
||||
"player" -> game.turnColor.name,
|
||||
"turns" -> game.turns,
|
||||
"startedAtTurn" -> game.startedAtTurn,
|
||||
"lastMove" -> game.castleLastMoveTime.lastMoveString),
|
||||
"player" -> Json.obj(
|
||||
"id" -> player.id,
|
||||
"color" -> player.color.name,
|
||||
"version" -> version,
|
||||
"spectator" -> false
|
||||
),
|
||||
"opponent" -> Json.obj(
|
||||
"color" -> opponent.color.name,
|
||||
"ai" -> opponent.isAi
|
||||
),
|
||||
"possibleMoves" -> possibleMoves(pov),
|
||||
"animationDelay" -> animationDelay(pov),
|
||||
"autoQueen" -> pref.autoQueen,
|
||||
"autoThreefold" -> pref.autoThreefold,
|
||||
"clockTenths" -> pref.clockTenths,
|
||||
"clockBar" -> pref.clockBar,
|
||||
"enablePremove" -> pref.premove,
|
||||
"tournamentId" -> game.tournamentId
|
||||
)
|
||||
}
|
||||
|
||||
def roundWatcherJsData(pov: Pov, version: Int, tv: Boolean, pref: Pref)(implicit ctx: UserContext) = {
|
||||
import pov._
|
||||
Json.obj(
|
||||
"game" -> Json.obj(
|
||||
"id" -> gameId,
|
||||
"started" -> game.started,
|
||||
"finished" -> game.finishedOrAborted,
|
||||
"clock" -> game.hasClock,
|
||||
"clockRunning" -> game.isClockRunning,
|
||||
"player" -> game.turnColor.name,
|
||||
"turns" -> game.turns,
|
||||
"startedAtTurn" -> game.startedAtTurn,
|
||||
"lastMove" -> game.castleLastMoveTime.lastMoveString),
|
||||
"player" -> Json.obj(
|
||||
"color" -> player.color.name,
|
||||
"version" -> version,
|
||||
"spectator" -> true),
|
||||
"opponent" -> Json.obj(
|
||||
"color" -> opponent.color.name,
|
||||
"ai" -> opponent.isAi),
|
||||
"possibleMoves" -> possibleMoves(pov),
|
||||
"animationDelay" -> animationDelay(pov),
|
||||
"clockTenths" -> pref.clockTenths,
|
||||
"clockBar" -> pref.clockBar,
|
||||
"tv" -> tv
|
||||
)
|
||||
}
|
||||
|
||||
def possibleMoves(pov: Pov) = (pov.game playableBy pov.player) option {
|
||||
pov.game.toChess.situation.destinations map {
|
||||
case (from, dests) => from.key -> dests.mkString
|
||||
}
|
||||
}
|
||||
|
||||
private def animationDelay(pov: Pov) = round {
|
||||
roundEnv.animationDelay.toMillis *
|
||||
max(0, min(1.2,
|
||||
((pov.game.estimateTotalTime - 60) / 60) * 0.2
|
||||
))
|
||||
}
|
||||
def roundWatcherJsData(pov: Pov, version: Int, tv: Boolean, pref: Pref) =
|
||||
roundEnv.jsonView.watcherJson(pov, version, tv, pref)
|
||||
}
|
||||
|
|
|
@ -874,9 +874,6 @@ var storage = {
|
|||
self.premove = null;
|
||||
self.holdStart = null;
|
||||
self.holds = [];
|
||||
self.options.tableUrl = self.element.data('table-url');
|
||||
self.options.endUrl = self.element.data('end-url');
|
||||
self.options.socketUrl = self.element.data('socket-url');
|
||||
|
||||
startTournamentClock();
|
||||
|
||||
|
@ -941,7 +938,7 @@ var storage = {
|
|||
});
|
||||
|
||||
lichess.socket = new strongSocket(
|
||||
self.options.socketUrl,
|
||||
self.options.url.socket,
|
||||
self.options.player.version,
|
||||
$.extend(true, lichess.socketDefaults, {
|
||||
options: {
|
||||
|
@ -1072,7 +1069,7 @@ var storage = {
|
|||
});
|
||||
},
|
||||
premove: function() {
|
||||
if (self.options.enablePremove) {
|
||||
if (self.options.pref.enablePremove) {
|
||||
self.element.queue(function() {
|
||||
self.applyPremove();
|
||||
self.element.dequeue();
|
||||
|
@ -1193,8 +1190,8 @@ var storage = {
|
|||
return $(this).clock('getSeconds');
|
||||
}).get();
|
||||
times.sort();
|
||||
return this.options.animationDelay * Math.min(1, times[0] / 120);
|
||||
} else return this.options.animationDelay;
|
||||
return this.options.pref.animationDelay * Math.min(1, times[0] / 120);
|
||||
} else return this.options.pref.animationDelay;
|
||||
},
|
||||
highlightLastMove: function(notation) {
|
||||
var self = this;
|
||||
|
@ -1243,7 +1240,7 @@ var storage = {
|
|||
},
|
||||
applyPremove: function() {
|
||||
var self = this;
|
||||
if (self.options.enablePremove && self.premove && self.isMyTurn()) {
|
||||
if (self.options.pref.enablePremove && self.premove && self.isMyTurn()) {
|
||||
var move = self.premove;
|
||||
self.unsetPremove();
|
||||
self.apiMove(move.from, move.to, true);
|
||||
|
@ -1251,7 +1248,7 @@ var storage = {
|
|||
},
|
||||
setPremove: function(move) {
|
||||
var self = this;
|
||||
if (!self.options.enablePremove || self.isMyTurn()) return;
|
||||
if (!self.options.pref.enablePremove || self.isMyTurn()) return;
|
||||
self.unsetPremove();
|
||||
if (!self.validMove(move.from, move.to, move.piece)) return;
|
||||
self.premove = move;
|
||||
|
@ -1311,7 +1308,7 @@ var storage = {
|
|||
var color = self.options.player.color;
|
||||
// promotion
|
||||
if ($piece.hasClass('pawn') && ((color == "white" && squareId[1] == 8) || (color == "black" && squareId[1] == 1))) {
|
||||
var aq = self.options.autoQueen;
|
||||
var aq = self.options.pref.autoQueen;
|
||||
if (aq == 3 || (isPremove && aq == 2)) {
|
||||
moveData.promotion = "queen";
|
||||
sendMoveRequest(moveData);
|
||||
|
@ -1466,7 +1463,7 @@ var storage = {
|
|||
},
|
||||
reloadTable: function(callback) {
|
||||
var self = this;
|
||||
self.get(self.options.tableUrl, {
|
||||
self.get(self.options.url.table, {
|
||||
success: function(html) {
|
||||
self.$tableInner.html(html);
|
||||
self.initTable();
|
||||
|
@ -1474,8 +1471,8 @@ var storage = {
|
|||
$('body').trigger('lichess.content_loaded');
|
||||
self.$tableInner.find('.lichess_claim_draw').each(function() {
|
||||
var $link = $(this);
|
||||
if (self.options.autoThreefold == 3) $link.click();
|
||||
if (self.options.autoThreefold == 2) {
|
||||
if (self.options.pref.autoThreefold == 3) $link.click();
|
||||
if (self.options.pref.autoThreefold == 2) {
|
||||
self.$table.find('.clock_bottom').each(function() {
|
||||
if ($(this).clock('getSeconds') < 30) $link.click();
|
||||
});
|
||||
|
@ -1487,7 +1484,7 @@ var storage = {
|
|||
},
|
||||
loadEnd: function(callback) {
|
||||
var self = this;
|
||||
$.getJSON(self.options.endUrl, function(data) {
|
||||
$.getJSON(self.options.url.end, function(data) {
|
||||
$(['white', 'black']).each(function() {
|
||||
if (data.players[this]) self.$table.find('div.username.' + this).html(data.players[this]);
|
||||
});
|
||||
|
@ -1534,8 +1531,8 @@ var storage = {
|
|||
self.$table.find('div.clock').each(function() {
|
||||
var $c = $(this);
|
||||
$c.clock({
|
||||
showTenths: self.options.clockTenths,
|
||||
showBar: self.options.clockBar,
|
||||
showTenths: self.options.pref.clockTenths,
|
||||
showBar: self.options.pref.clockBar,
|
||||
time: $c.data('time'),
|
||||
barTime: $c.data('bar-time'),
|
||||
emerg: $c.data('emerg'),
|
||||
|
|
Loading…
Reference in a new issue