diff --git a/app/ui/SiteMenu.scala b/app/ui/SiteMenu.scala index e3f485a86e..505c53c01c 100644 --- a/app/ui/SiteMenu.scala +++ b/app/ui/SiteMenu.scala @@ -19,11 +19,18 @@ final class SiteMenu(trans: I18nKeys) { val forum = new Elem("forum", routes.ForumCateg.index, trans.forum) val tv = new Elem("tv", routes.Tv.index, I18nKey.untranslated("TV")) val message = new Elem("message", routes.Message.inbox(page = 1), trans.inbox) + val puzzle = new Elem("puzzle", routes.Puzzle.home, I18nKey untranslated "Puzzles") private val authenticated = List(play, game, tournament, user, team, forum, tv) private val anonymous = List(play, game, tournament, user, team, forum, tv) - def all(me: Option[User]) = me.isDefined.fold(authenticated, anonymous) + private val betaTesters = Set("thibault", "hellball", "clarkey", "legend", "chubakka", "iron_logician") + + def all(me: Option[User]) = me match { + case Some(me) if betaTesters(me.id) ⇒ authenticated :+ puzzle + case Some(me) ⇒ authenticated + case _ ⇒ anonymous + } } object SiteMenu { diff --git a/app/views/analyse/replay.scala.html b/app/views/analyse/replay.scala.html index 8e21a36268..c1d6c2e068 100644 --- a/app/views/analyse/replay.scala.html +++ b/app/views/analyse/replay.scala.html @@ -113,20 +113,17 @@ themepicker = true) { data-max="@lila.analyse.AdvantageChart.max" data-rows="@chart"> }.getOrElse { -
- @trans.computerAnalysisInProgress() -
- } - }.getOrElse { - @if(game.analysable && analysis.isEmpty) { - - -
@trans.computerAnalysisInProgress()
} + }.getOrElse { + @if(game.analysable && analysis.isEmpty) { +
+ +
+ } }
diff --git a/app/views/puzzle/layout.scala.html b/app/views/puzzle/layout.scala.html index ee7d4eb097..5e15e474cf 100644 --- a/app/views/puzzle/layout.scala.html +++ b/app/views/puzzle/layout.scala.html @@ -1,19 +1,19 @@ -@(title: String)(body: Html)(implicit ctx: Context) +@(title: String, evenMoreCss: Option[Html] = None, evenMoreJs: Option[Html] = None)(body: Html)(implicit ctx: Context) @moreCss = { +@evenMoreCss @cssTag("problem.css") -@cssTag("chessboardjs.css") } @moreJs = { +@evenMoreJs @jsTagCompiled("chessboard.js") -@jsTag("vendor/chess.min.js") -@jsAt("compiled/problem.js") } @base.layout( title = title, moreCss = moreCss, -moreJs = moreJs) { +moreJs = moreJs, +active = siteMenu.puzzle.some) { @body } diff --git a/app/views/puzzle/show.scala.html b/app/views/puzzle/show.scala.html index 2fbaeab665..6957e9f726 100644 --- a/app/views/puzzle/show.scala.html +++ b/app/views/puzzle/show.scala.html @@ -1,6 +1,17 @@ @(puzzle: lila.puzzle.Puzzle)(implicit ctx: Context) -@layout("Puzzle " + puzzle.id) { +@moreCss = { +@cssTag("chessboardjs.css") +} + +@moreJs = { +@jsTag("vendor/chess.min.js") +@jsAt("compiled/problem.js") +} + +@layout("Puzzle " + puzzle.id, +evenMoreCss = moreCss.some, +evenMoreJs = moreJs.some) {
diff --git a/modules/puzzle/src/main/Env.scala b/modules/puzzle/src/main/Env.scala index 7e093c5ef9..8d98546db0 100644 --- a/modules/puzzle/src/main/Env.scala +++ b/modules/puzzle/src/main/Env.scala @@ -24,7 +24,7 @@ final class Env( def cli = new lila.common.Cli { def process = { - case "puzzle" :: "fix" :: "fen" :: Nil ⇒ api.fixFen inject "fixed!" + case "puzzle" :: "fix" :: "fen" :: Nil ⇒ api.fixAll inject "fixed!" } } diff --git a/modules/puzzle/src/main/PuzzleApi.scala b/modules/puzzle/src/main/PuzzleApi.scala index 0b5f894e8d..c216bacbb7 100644 --- a/modules/puzzle/src/main/PuzzleApi.scala +++ b/modules/puzzle/src/main/PuzzleApi.scala @@ -6,7 +6,7 @@ import org.joda.time.DateTime import play.api.libs.iteratee._ import play.api.libs.iteratee.Enumerator import play.api.libs.json._ -import reactivemongo.bson.BSONDocument +import reactivemongo.bson.{ BSONDocument, BSONInteger } import reactivemongo.core.commands.Count import lila.db.Types.Coll @@ -65,17 +65,27 @@ private[puzzle] final class PuzzleApi( BSONDocument(Attempt.BSONFields.vote -> v) ).void - def fixFen = puzzleColl.find(BSONDocument()).cursor[Puzzle].enumerate() |>>> - (Iteratee.foldM[Puzzle, Unit](()) { - case (_, puzzle) ⇒ Generated fenOf puzzle.history match { - case Success(fen) ⇒ puzzleColl.update( - BSONDocument("_id" -> puzzle.id), - BSONDocument("$set" -> BSONDocument( - Puzzle.BSONFields.fen -> fen, - Puzzle.BSONFields.rating -> Glicko.default - )) - ).void - case Failure(err) ⇒ fufail(err.getMessage) - } + def fixAll = puzzleColl.find( + BSONDocument(), + BSONDocument("history" -> true) + ).cursor[BSONDocument].enumerate() |>>> + (Iteratee.foldM[BSONDocument, Unit](()) { + case (_, doc) ⇒ + val reader = new lila.db.BSON.Reader(doc) + val (id, moves) = (reader str "_id", reader str "history" split ' ') + Generated fenOf moves match { + case Success(fen) ⇒ puzzleColl.update( + BSONDocument("_id" -> id), + BSONDocument("$set" -> BSONDocument( + Puzzle.BSONFields.fen -> fen, + Puzzle.BSONFields.rating -> Glicko.default, + Puzzle.BSONFields.vote -> BSONInteger(0), + Puzzle.BSONFields.attempts -> BSONInteger(0) + )) + ).void + case Failure(err) ⇒ + println(err) + fufail(err.getMessage) + } }) } diff --git a/todo b/todo index 81ab449fed..fce16f2de4 100644 --- a/todo +++ b/todo @@ -106,6 +106,14 @@ ban only latest IP give AI levels ratings connect time chart to pgn viewer and say "time spent on this move: X seconds" +deploy +------ +db.puzzle.ensureIndex({fen:1},{unique:1}) +db.puzzle.ensureIndex({date:1}) +db.puzzle.ensureIndex({vote:1}) +db.puzzle_attempt.ensureIndex({p:1}) +db.puzzle_attempt.ensureIndex({u:1}) + infra ------- lila nice + thread limit