diff --git a/app/analyse/TimeChart.scala b/app/analyse/TimeChart.scala new file mode 100644 index 0000000000..42e6cebf30 --- /dev/null +++ b/app/analyse/TimeChart.scala @@ -0,0 +1,21 @@ +package lila +package analyse + +import game.{ DbPlayer, DbGame } + +import scala.math.round +import com.codahale.jerkson.Json + +final class TimeChart(game: DbGame) { + + def columns = Json generate { + List("string", "Move") :: game.players.map(p ⇒ + List("number", "%s - %s".format(p.color, p.userId | "anonymous"))) + } + + def rows = Json generate { + (game.creator.moveTimeList zip game.invited.moveTimeList).zipWithIndex map { + case ((black, white), move) ⇒ List(move.toString, white, black) + } + } +} diff --git a/app/controllers/Analyse.scala b/app/controllers/Analyse.scala index 9f7d448ee4..3aec2445f5 100644 --- a/app/controllers/Analyse.scala +++ b/app/controllers/Analyse.scala @@ -2,6 +2,7 @@ package controllers import lila._ import views._ +import analyse._ import play.api.mvc._ @@ -16,5 +17,11 @@ object Analyse extends LilaController { } } - def stats(id: String) = todo + def stats(id: String) = Open { implicit ctx ⇒ + IOptionOk(gameRepo game id) { game ⇒ + html.analyse.stats( + game = game, + timeChart = new TimeChart(game)) + } + } } diff --git a/app/controllers/ForumTopic.scala b/app/controllers/ForumTopic.scala index 7aecdf593d..568d953045 100644 --- a/app/controllers/ForumTopic.scala +++ b/app/controllers/ForumTopic.scala @@ -45,6 +45,4 @@ object ForumTopic extends LilaController with forum.Controller { } } } - - def delete(id: String) = TODO } diff --git a/app/game/DbGame.scala b/app/game/DbGame.scala index ce13ec5a3d..15e7ac13f0 100644 --- a/app/game/DbGame.scala +++ b/app/game/DbGame.scala @@ -51,6 +51,8 @@ case class DbGame( def player(user: User): Option[DbPlayer] = players find (_ isUser user) + def player(c: Color.type => Color): DbPlayer = player(c(Color)) + def isPlayerFullId(player: DbPlayer, fullId: String): Boolean = (fullId.size == DbGame.fullIdSize) && player.id == (fullId drop 8) @@ -295,7 +297,7 @@ case class DbGame( def invitedColor = !creatorColor - def invited = opponent(invitedColor) + def invited = player(invitedColor) def pgnList = pgn.split(' ').toList diff --git a/app/game/DbPlayer.scala b/app/game/DbPlayer.scala index 353648f3e0..543c416889 100644 --- a/app/game/DbPlayer.scala +++ b/app/game/DbPlayer.scala @@ -48,6 +48,9 @@ case class DbPlayer( def hasMoveTimes = moveTimes.size > 10 + def moveTimeList: List[Int] = + moveTimes.split(" ").toList map parseIntOption flatten + def finish(winner: Boolean) = copy( isWinner = if (winner) Some(true) else None ) diff --git a/app/user/Cached.scala b/app/user/Cached.scala index 1f006b64ea..f0c569e289 100644 --- a/app/user/Cached.scala +++ b/app/user/Cached.scala @@ -14,5 +14,9 @@ final class Cached(userRepo: UserRepo) { (userRepo username userId).unsafePerformIO ) - def usernameOrAnonymous(userId: String) = username(userId) | User.anonymous + def usernameOrAnonymous(userId: String): String = + username(userId) | User.anonymous + + def usernameOrAnonymous(userId: Option[String]): String = + userId.fold(usernameOrAnonymous, User.anonymous) } diff --git a/app/views/analyse/stats.scala.html b/app/views/analyse/stats.scala.html new file mode 100644 index 0000000000..ee7eed8dbb --- /dev/null +++ b/app/views/analyse/stats.scala.html @@ -0,0 +1,30 @@ +@(game: DbGame, timeChart: lila.analyse.TimeChart)(implicit ctx: Context) + +@moreCss = { +@cssTag("gamestats.css") +} + +@moreJs = { + +@jsTag("chart.js") +@jsTag("gamestats.js") +} + +@title = @{ "Game #%s time stats" format game.id } + +@analyse.layout( +title = title, +moreCss = moreCss, +moreJs = moreJs) { +
+

+ Game #@game.id time stats +

+

+
+
+} diff --git a/public/stylesheets/gamestats.css b/public/stylesheets/gamestats.css index bd01a1bb24..541e38294f 100644 --- a/public/stylesheets/gamestats.css +++ b/public/stylesheets/gamestats.css @@ -1,30 +1,30 @@ .title { - font-size: 1.8em; - color: #666; - font-weight: normal; - margin-bottom: 0.5em; + font-size: 1.8em; + color: #666; + font-weight: normal; + margin-bottom: 0.5em; } .section-title { - font-size: 1.6em; - color: #999; - font-weight: normal; - font-style: italic; - margin: 1.5em 0; - border-top: 1px solid #dadada; - padding: 0.5em 0; - text-align: right; + font-size: 1.6em; + color: #999; + font-weight: normal; + font-style: italic; + margin: 1.5em 0; + border-top: 1px solid #dadada; + padding: 0.5em 0; + text-align: right; } .chart-title { - font-size: 1.4em; - color: #666; - font-weight: normal; - margin-bottom: 0.5em; + font-size: 1.4em; + color: #666; + font-weight: normal; + margin-bottom: 0.5em; } .half { - float: left; - width: 49%; - margin-right: 2%; + float: left; + width: 49%; + margin-right: 2%; } .half.last { - margin-right: 0; + margin-right: 0; } diff --git a/todo b/todo index f1bea7a404..20c5a62a73 100644 --- a/todo +++ b/todo @@ -19,6 +19,7 @@ endgame sound http://en.lichess.org/forum/lichess-feedback/checkmate-sound-featu translation contributions check sf2 commands to port make the wiki static html pages managed by git? +compensate lag http://fr.lichess.org/forum/lichess-feedback/the-clock-display-should-account-for-lag?page=1#4 next deploy: bin/migrate