diff --git a/app/round/Hub.scala b/app/round/Hub.scala index 867be34038..0808fab6ed 100644 --- a/app/round/Hub.scala +++ b/app/round/Hub.scala @@ -40,6 +40,9 @@ final class Hub( } } + case Ack(uid) => withMember(uid) { _.channel push ackEvent } + + case Broom ⇒ { broom() if (lastPingTime < (nowMillis - hubTimeout)) { @@ -126,6 +129,8 @@ final class Hub( def makeEvent(t: String, data: JsValue): JsObject = JsObject(Seq("t" -> JsString(t), "d" -> data)) + lazy val ackEvent = makeEvent("ack", JsNull) + def ownerOf(color: Color): Option[Member] = members.values find { m ⇒ m.owner && m.color == color } diff --git a/app/round/Socket.scala b/app/round/Socket.scala index b04c2a9403..996f48f3d3 100644 --- a/app/round/Socket.scala +++ b/app/round/Socket.scala @@ -64,6 +64,7 @@ final class Socket( } case Some("move") ⇒ parseMove(e) foreach { case (orig, dest, prom, blur, lag) ⇒ { + hub ! Ack(uid) hand.play(povRef, orig, dest, prom, blur, lag) onSuccess { case Failure(fs) ⇒ { hub ! Resync(uid) @@ -72,7 +73,7 @@ final class Socket( case Success((events, fen)) ⇒ { send(povRef.gameId, events) moveNotifier(povRef.gameId, fen) - } + } } } } diff --git a/app/round/actorApi.scala b/app/round/actorApi.scala index fb4fa2ed7c..bf768c3d83 100644 --- a/app/round/actorApi.scala +++ b/app/round/actorApi.scala @@ -75,3 +75,4 @@ case class GetHub(gameId: String) case object HubTimeout case object GetNbHubs case class AnalysisAvailable(gameId: String) +case class Ack(uid: String) diff --git a/app/socket/HubActor.scala b/app/socket/HubActor.scala index b904fcea53..747c013d88 100644 --- a/app/socket/HubActor.scala +++ b/app/socket/HubActor.scala @@ -112,7 +112,7 @@ abstract class HubActor[M <: SocketMember](uidTimeout: Int) extends Actor { withMember(uid)(_ addLiveGames ids) } - def withMember(uid: String)(f: M => Unit) { + def withMember(uid: String)(f: M ⇒ Unit) { members get uid foreach f } } diff --git a/app/templating/AssetHelper.scala b/app/templating/AssetHelper.scala index 1faeda7d21..9c98c449fe 100644 --- a/app/templating/AssetHelper.scala +++ b/app/templating/AssetHelper.scala @@ -7,7 +7,7 @@ import play.api.templates.Html trait AssetHelper { - val assetVersion = 66 + val assetVersion = 67 def cssTag(name: String) = css("stylesheets/" + name) diff --git a/public/javascripts/game.js b/public/javascripts/game.js index 1672c606da..58a16758ae 100644 --- a/public/javascripts/game.js +++ b/public/javascripts/game.js @@ -13,6 +13,7 @@ $.widget("lichess.game", { self.options.tableUrl = self.element.data('table-url'); self.options.playersUrl = self.element.data('players-url'); self.options.socketUrl = self.element.data('socket-url'); + self.socketAckTimeout; if (self.options.game.started) { self.indicateTurn(); @@ -64,6 +65,9 @@ $.widget("lichess.game", { name: "game" }, events: { + ack: function() { + clearTimeout(self.socketAckTimeout); + }, message: function(event) { self.element.queue(function() { if (self.$chat) self.$chat.chat("append", event); @@ -350,6 +354,9 @@ $.widget("lichess.game", { moveData.lag = parseInt(lichess.socket.averageLag); } lichess.socket.send("move", moveData); + self.socketAckTimeout = setTimeout(function() { + location.reload(); + }, lichess.socket.options.pingMaxLag); } var color = self.options.player.color; diff --git a/todo b/todo index 56d7dc2b83..54e37b8e56 100644 --- a/todo +++ b/todo @@ -32,7 +32,5 @@ admin ip search interface analyse: show main line for every move http://en.lichess.org/forum/lichess-feedback/about-the-analysis-feature#5 try to show last analysis cp on graph (move 26) http://en.lichess.org/analyse/bwxnx0al elo range must contain player elo -auto-restart when http timeout complete analysis movetimes with tsinnema - requires ms movetimes and db migration complete search engine using https://github.com/bsadeh/scalastic -don't count AI games in win/loss ratios