package controllers import scala.util.{ Try, Success, Failure } import play.api.data._, Forms._ import play.api.mvc._ import play.twirl.api.Html import play.api.Play.current import play.api.i18n.Messages.Implicits._ import lila.api.Context import lila.app._ import lila.common.HTTPRequest import lila.opening.{ Generated, Opening => OpeningModel, UserInfos, Attempt } import lila.user.{ User => UserModel, UserRepo } import views._ import views.html.opening.JsData object Opening extends LilaController { private def env = Env.opening private def identify(opening: OpeningModel) = env.api.identify(opening.fen, 5) private def renderShow(opening: OpeningModel)(implicit ctx: Context) = env userInfos ctx.me zip identify(opening) map { case (infos, identified) => views.html.opening.show(opening, identified, infos, env.AnimationDuration) } private def makeData( opening: OpeningModel, infos: Option[UserInfos], play: Boolean, attempt: Option[Attempt], win: Option[Boolean])(implicit ctx: Context): Fu[Result] = identify(opening) map { identified => Ok(JsData( opening, identified, infos, play = play, attempt = attempt, win = win, animationDuration = env.AnimationDuration)) as JSON } def home = Open { implicit ctx => if (HTTPRequest isXhr ctx.req) env.selector(ctx.me) zip (env userInfos ctx.me) flatMap { case (opening, infos) => makeData(opening, infos, true, none, none) } else env.selector(ctx.me) flatMap { opening => renderShow(opening) map { Ok(_) } } } def show(id: OpeningModel.ID) = Open { implicit ctx => OptionFuOk(env.api.opening find id)(renderShow) } def history = Auth { implicit ctx => me => XhrOnly { env userInfos me map { ui => Ok(views.html.opening.history(ui)) } } } private val attemptForm = Form(mapping( "found" -> number, "failed" -> number )(Tuple2.apply)(Tuple2.unapply)) def attempt(id: OpeningModel.ID) = OpenBody { implicit ctx => implicit val req = ctx.body OptionFuResult(env.api.opening find id) { opening => attemptForm.bindFromRequest.fold( err => fuccess(BadRequest(err.errorsAsJson) as JSON), data => { val (found, failed) = data val win = found == opening.goal && failed == 0 ctx.me match { case Some(me) => env.finisher(opening, me, win) flatMap { case (newAttempt, None) => UserRepo byId me.id map (_ | me) flatMap { me2 => (env.api.opening find id) zip (env userInfos me2.some) flatMap { case (o2, infos) => makeData(o2 | opening, infos, false, newAttempt.some, none) } } case (oldAttempt, Some(win)) => env userInfos me.some flatMap { infos => makeData(opening, infos, false, oldAttempt.some, win.some) } } case None => makeData(opening, none, false, none, win.some) } } ) } } def importOne = Action.async(parse.json) { implicit req => env.api.opening.importOne(req.body, ~get("token", req)) map { id => Ok("kthxbye " + { val url = s"http://lichess.org/training/opening/$id" play.api.Logger("opening import").info(s"${req.remoteAddress} $url") url }) } recover { case e => play.api.Logger("opening import").warn(e.getMessage) BadRequest(e.getMessage) } } }