typesafe puzzle round result
This commit is contained in:
parent
d79dc12d03
commit
9804b5987e
|
@ -11,8 +11,7 @@ import play.twirl.api.Html
|
|||
import lila.api.Context
|
||||
import lila.app._
|
||||
import lila.game.GameRepo
|
||||
import lila.puzzle.PuzzleId
|
||||
import lila.puzzle.{ Generated, Puzzle => PuzzleModel, UserInfos }
|
||||
import lila.puzzle.{ PuzzleId, Result, Generated, Puzzle => PuzzleModel, UserInfos }
|
||||
import lila.user.{ User => UserModel, UserRepo }
|
||||
import views._
|
||||
|
||||
|
@ -26,7 +25,7 @@ object Puzzle extends LilaController {
|
|||
mode: String,
|
||||
voted: Option[Boolean],
|
||||
round: Option[lila.puzzle.Round] = None,
|
||||
win: Option[Boolean] = None)(implicit ctx: Context): Fu[JsObject] =
|
||||
result: Option[Result] = None)(implicit ctx: Context): Fu[JsObject] =
|
||||
lila.puzzle.JsonView(
|
||||
puzzle = puzzle,
|
||||
userInfos = userInfos,
|
||||
|
@ -34,7 +33,7 @@ object Puzzle extends LilaController {
|
|||
animationDuration = env.AnimationDuration,
|
||||
pref = ctx.pref,
|
||||
isMobileApi = ctx.isMobileApi,
|
||||
win = win,
|
||||
result = result,
|
||||
voted = voted)
|
||||
|
||||
private def renderShow(puzzle: PuzzleModel, mode: String)(implicit ctx: Context) =
|
||||
|
@ -97,36 +96,76 @@ object Puzzle extends LilaController {
|
|||
else lila.mon.puzzle.round.material()
|
||||
env.forms.round.bindFromRequest.fold(
|
||||
err => fuccess(BadRequest(errorsAsJson(err))),
|
||||
data => ctx.me match {
|
||||
case Some(me) =>
|
||||
lila.mon.puzzle.round.user()
|
||||
env.finisher(puzzle, me, data) flatMap {
|
||||
case (newAttempt, None) => UserRepo byId me.id map (_ | me) flatMap { me2 =>
|
||||
env.api.puzzle find id zip
|
||||
(env userInfos me2.some) zip
|
||||
env.api.vote.value(id, me2) flatMap {
|
||||
case ((p2, infos), voted) => renderJson(
|
||||
p2 | puzzle, infos, "view", voted = voted, round = newAttempt.some
|
||||
) map { Ok(_) }
|
||||
resultInt => {
|
||||
val result = Result(resultInt == 1)
|
||||
ctx.me match {
|
||||
case Some(me) =>
|
||||
lila.mon.puzzle.round.user()
|
||||
env.finisher(puzzle, me, result) flatMap {
|
||||
case (newAttempt, None) => UserRepo byId me.id map (_ | me) flatMap { me2 =>
|
||||
env.api.puzzle find id zip
|
||||
(env userInfos me2.some) zip
|
||||
env.api.vote.value(id, me2) flatMap {
|
||||
case ((p2, infos), voted) => renderJson(
|
||||
p2 | puzzle, infos, "view", voted = voted, round = newAttempt.some
|
||||
) map { Ok(_) }
|
||||
}
|
||||
}
|
||||
case (oldAttempt, Some(win)) => env.userInfos(me.some) zip
|
||||
ctx.me.?? { env.api.vote.value(puzzle.id, _) } flatMap {
|
||||
case (infos, voted) => renderJson(puzzle, infos, "view",
|
||||
round = oldAttempt.some,
|
||||
result = result.some,
|
||||
voted = voted) map { Ok(_) }
|
||||
}
|
||||
}
|
||||
case (oldAttempt, Some(win)) => env.userInfos(me.some) zip
|
||||
ctx.me.?? { env.api.vote.value(puzzle.id, _) } flatMap {
|
||||
case (infos, voted) => renderJson(puzzle, infos, "view",
|
||||
round = oldAttempt.some,
|
||||
win = win.some,
|
||||
voted = voted) map { Ok(_) }
|
||||
}
|
||||
}
|
||||
case None =>
|
||||
lila.mon.puzzle.round.anon()
|
||||
env.finisher.incPuzzleAttempts(puzzle)
|
||||
renderJson(puzzle, none, "view", win = data.isWin.some, voted = none) map { Ok(_) }
|
||||
case None =>
|
||||
lila.mon.puzzle.round.anon()
|
||||
env.finisher.incPuzzleAttempts(puzzle)
|
||||
renderJson(puzzle, none, "view", result = result.some, voted = none) map { Ok(_) }
|
||||
}
|
||||
}
|
||||
) map (_ as JSON)
|
||||
}
|
||||
}
|
||||
|
||||
// def round2(id: PuzzleId) = OpenBody { implicit ctx =>
|
||||
// implicit val req = ctx.body
|
||||
// OptionFuResult(env.api.puzzle find id) { puzzle =>
|
||||
// if (puzzle.mate) lila.mon.puzzle.round.mate()
|
||||
// else lila.mon.puzzle.round.material()
|
||||
// env.forms.round.bindFromRequest.fold(
|
||||
// err => fuccess(BadRequest(errorsAsJson(err))),
|
||||
// data => ctx.me match {
|
||||
// case Some(me) =>
|
||||
// lila.mon.puzzle.round.user()
|
||||
// env.finisher(puzzle, me, data) flatMap {
|
||||
// case (newAttempt, None) => UserRepo byId me.id map (_ | me) flatMap { me2 =>
|
||||
// env.api.puzzle find id zip
|
||||
// (env userInfos me2.some) zip
|
||||
// env.api.vote.value(id, me2) flatMap {
|
||||
// case ((p2, infos), voted) => renderJson(
|
||||
// p2 | puzzle, infos, "view", voted = voted, round = newAttempt.some
|
||||
// ) map { Ok(_) }
|
||||
// }
|
||||
// }
|
||||
// case (oldAttempt, Some(win)) => env.userInfos(me.some) zip
|
||||
// ctx.me.?? { env.api.vote.value(puzzle.id, _) } flatMap {
|
||||
// case (infos, voted) => renderJson(puzzle, infos, "view",
|
||||
// round = oldAttempt.some,
|
||||
// win = win.some,
|
||||
// voted = voted) map { Ok(_) }
|
||||
// }
|
||||
// }
|
||||
// case None =>
|
||||
// lila.mon.puzzle.round.anon()
|
||||
// env.finisher.incPuzzleAttempts(puzzle)
|
||||
// renderJson(puzzle, none, "view", win = data.isWin.some, voted = none) map { Ok(_) }
|
||||
// }
|
||||
// ) map (_ as JSON)
|
||||
// }
|
||||
// }
|
||||
|
||||
def vote(id: PuzzleId) = AuthBody { implicit ctx => me =>
|
||||
implicit val req = ctx.body
|
||||
env.forms.vote.bindFromRequest.fold(
|
||||
|
|
|
@ -5,18 +5,9 @@ import play.api.data.Forms._
|
|||
|
||||
object DataForm {
|
||||
|
||||
val difficulty = Form(single(
|
||||
"difficulty" -> number(min = 1, max = 3)
|
||||
))
|
||||
|
||||
val round = Form(mapping(
|
||||
val round = Form(single(
|
||||
"win" -> number
|
||||
)(RoundData.apply)(RoundData.unapply))
|
||||
|
||||
case class RoundData(win: Int) extends AnyVal {
|
||||
|
||||
def isWin = win == 1
|
||||
}
|
||||
))
|
||||
|
||||
val vote = Form(single(
|
||||
"vote" -> number
|
||||
|
|
|
@ -13,15 +13,15 @@ private[puzzle] final class Finisher(
|
|||
|
||||
private val maxTime = 5 * 60 * 1000
|
||||
|
||||
def apply(puzzle: Puzzle, user: User, data: DataForm.RoundData): Fu[(Round, Option[Boolean])] =
|
||||
def apply(puzzle: Puzzle, user: User, result: Result): Fu[(Round, Option[Result])] =
|
||||
api.head.find(user) flatMap {
|
||||
case Some(PuzzleHead(_, Some(c), _)) if c == puzzle.id =>
|
||||
api.head.solved(user, puzzle.id) >>
|
||||
api.learning.update(user, puzzle, data).flatMap { isLearning =>
|
||||
api.learning.update(user, puzzle, result).flatMap { isLearning =>
|
||||
val userRating = user.perfs.puzzle.toRating
|
||||
val puzzleRating = puzzle.perf.toRating
|
||||
updateRatings(userRating, puzzleRating,
|
||||
result = data.isWin.fold(Glicko.Result.Win, Glicko.Result.Loss),
|
||||
result = result.win.fold(Glicko.Result.Win, Glicko.Result.Loss),
|
||||
isLearning = isLearning)
|
||||
val date = DateTime.now
|
||||
val puzzlePerf = puzzle.perf.addOrReset(_.puzzle.crazyGlicko, s"puzzle ${puzzle.id} user")(puzzleRating, date)
|
||||
|
@ -30,7 +30,7 @@ private[puzzle] final class Finisher(
|
|||
puzzleId = puzzle.id,
|
||||
userId = user.id,
|
||||
date = DateTime.now,
|
||||
win = data.isWin,
|
||||
result = result,
|
||||
rating = user.perfs.puzzle.intRating,
|
||||
ratingDiff = userPerf.intRating - user.perfs.puzzle.intRating)
|
||||
(api.round add a) >> {
|
||||
|
@ -47,10 +47,10 @@ private[puzzle] final class Finisher(
|
|||
puzzleId = puzzle.id,
|
||||
userId = user.id,
|
||||
date = DateTime.now,
|
||||
win = data.isWin,
|
||||
result = result,
|
||||
rating = user.perfs.puzzle.intRating,
|
||||
ratingDiff = 0)
|
||||
fuccess(a -> data.isWin.some)
|
||||
fuccess(a -> result.some)
|
||||
}
|
||||
|
||||
private val VOLATILITY = Glicko.default.volatility
|
||||
|
|
|
@ -17,7 +17,7 @@ object JsonView {
|
|||
pref: lila.pref.Pref,
|
||||
isMobileApi: Boolean,
|
||||
round: Option[Round] = None,
|
||||
win: Option[Boolean] = None,
|
||||
result: Option[Result] = None,
|
||||
voted: Option[Boolean]): Fu[JsObject] =
|
||||
(!isMobileApi ?? GameJson(puzzle.gameId, puzzle.initialPly).map(_.some)) map { gameJson =>
|
||||
Json.obj(
|
||||
|
@ -62,17 +62,17 @@ object JsonView {
|
|||
"round" -> round.map { a =>
|
||||
Json.obj(
|
||||
"ratingDiff" -> a.ratingDiff,
|
||||
"win" -> a.win
|
||||
"win" -> a.result.win
|
||||
)
|
||||
},
|
||||
"attempt" -> round.ifTrue(isMobileApi).map { r =>
|
||||
Json.obj(
|
||||
"userRatingDiff" -> r.ratingDiff,
|
||||
"win" -> r.win,
|
||||
"win" -> r.result.win,
|
||||
"seconds" -> "a few" // lol we don't have the value anymore
|
||||
)
|
||||
},
|
||||
"win" -> win,
|
||||
"win" -> result.ifTrue(isMobileApi).map(_.win),
|
||||
"voted" -> voted,
|
||||
"user" -> userInfos.map { i =>
|
||||
Json.obj(
|
||||
|
|
|
@ -83,8 +83,8 @@ private[puzzle] final class PuzzleApi(
|
|||
|
||||
def add(l: Learning) = learningColl insert l void
|
||||
|
||||
def update(user: User, puzzle: Puzzle, data: DataForm.RoundData): Fu[Boolean] =
|
||||
if (data.isWin) solved(user, puzzle.id)
|
||||
def update(user: User, puzzle: Puzzle, result: Result): Fu[Boolean] =
|
||||
if (result.win) solved(user, puzzle.id)
|
||||
else failed(user, puzzle.id)
|
||||
|
||||
def solved(user: User, puzzleId: PuzzleId): Fu[Boolean] = learning find user flatMap {
|
||||
|
|
|
@ -8,12 +8,10 @@ case class Round(
|
|||
puzzleId: PuzzleId,
|
||||
userId: User.ID,
|
||||
date: DateTime,
|
||||
win: Boolean,
|
||||
result: Result,
|
||||
rating: Int,
|
||||
ratingDiff: Int) {
|
||||
|
||||
def loss = !win
|
||||
|
||||
def userPostRating = rating + ratingDiff
|
||||
}
|
||||
|
||||
|
@ -25,7 +23,7 @@ object Round {
|
|||
val puzzleId = "p"
|
||||
val userId = "u"
|
||||
val date = "a"
|
||||
val win = "w"
|
||||
val result = "w"
|
||||
val rating = "r"
|
||||
val ratingDiff = "d"
|
||||
}
|
||||
|
@ -34,6 +32,9 @@ object Round {
|
|||
import lila.db.BSON
|
||||
import lila.db.dsl._
|
||||
import BSON.BSONJodaDateTimeHandler
|
||||
|
||||
private implicit val ResultBSONHandler = booleanAnyValHandler[Result](_.win, Result.apply)
|
||||
|
||||
implicit val RoundBSONHandler = new BSON[Round] {
|
||||
|
||||
import BSONFields._
|
||||
|
@ -42,7 +43,7 @@ object Round {
|
|||
puzzleId = r int puzzleId,
|
||||
userId = r str userId,
|
||||
date = r.get[DateTime](date),
|
||||
win = r bool win,
|
||||
result = r.get[Result](result),
|
||||
rating = r int rating,
|
||||
ratingDiff = r int ratingDiff)
|
||||
|
||||
|
@ -50,7 +51,7 @@ object Round {
|
|||
puzzleId -> o.puzzleId,
|
||||
userId -> o.userId,
|
||||
date -> o.date,
|
||||
win -> o.win,
|
||||
result -> o.result,
|
||||
rating -> w.int(o.rating),
|
||||
ratingDiff -> w.int(o.ratingDiff))
|
||||
}
|
||||
|
|
|
@ -7,4 +7,9 @@ package object puzzle extends PackageObject with WithPlay {
|
|||
type Lines = List[Line]
|
||||
|
||||
private[puzzle] def logger = lila.log("puzzle")
|
||||
|
||||
case class Result(win: Boolean) extends AnyVal {
|
||||
|
||||
def loss = !win
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue