diff --git a/app/views/user/show.scala.html b/app/views/user/show.scala.html
index 5b29371c8a..eb2c902a3a 100644
--- a/app/views/user/show.scala.html
+++ b/app/views/user/show.scala.html
@@ -47,6 +47,15 @@
}
}
+ @u.variantElos.toMap.map {
+ case (variant, x) => {
+
+
@variant.toString
+ @x.elo ELO
+ @x.nb @trans.games()
+
+ }
+ }
}
diff --git a/modules/db/src/main/api/enumerate.scala b/modules/db/src/main/api/enumerate.scala
index 898b6d06e1..7d4ac698b9 100644
--- a/modules/db/src/main/api/enumerate.scala
+++ b/modules/db/src/main/api/enumerate.scala
@@ -23,6 +23,9 @@ object $enumerate {
)
}
- def fold[A: BSONDocumentReader, B: Zero](query: QueryBuilder)(f: (B, A) ⇒ B): Fu[B] =
- query.cursor[A].enumerate |>>> Iteratee.fold(∅[B])(f)
+ def fold[A: BSONDocumentReader, B](query: QueryBuilder)(zero: B)(f: (B, A) ⇒ B): Fu[B] =
+ query.cursor[A].enumerate |>>> Iteratee.fold(zero)(f)
+
+ def foldZero[A: BSONDocumentReader, B: Zero](query: QueryBuilder)(f: (B, A) ⇒ B): Fu[B] =
+ fold(query)(∅[B])(f)
}
diff --git a/modules/game/src/main/ComputeElos.scala b/modules/game/src/main/ComputeElos.scala
index c37f7abe57..676be9b8a0 100644
--- a/modules/game/src/main/ComputeElos.scala
+++ b/modules/game/src/main/ComputeElos.scala
@@ -30,23 +30,39 @@ private[game] final class ComputeElos(system: ActorSystem) {
funit
}
- def apply(user: User): Funit = $enumerate.fold[Option[Game], SpeedElos](gamesQuery(user)) {
- case (elos, gameOption) ⇒ (for {
+ def apply(user: User): Funit = $enumerate.fold[Option[Game], User](gamesQuery(user))(user) {
+ case (user, gameOption) ⇒ (for {
game ← gameOption
player ← game player user
opponentElo ← game.opponent(player).elo
- } yield {
- val speed = Speed(game.clock)
- val speedElo = elos(speed)
- val opponentSpeedElo = SubElo(0, opponentElo)
- val (white, black) = player.color.fold[(eloCalculator.User, eloCalculator.User)](
- speedElo -> opponentSpeedElo,
- opponentSpeedElo -> speedElo)
- val newElos = eloCalculator.calculate(white, black, game.winnerColor)
- val newElo = player.color.fold(newElos._1, newElos._2)
- elos.addGame(speed, newElo)
- }) | elos
- } flatMap UserRepo.setSpeedElos(user.id)
+ } yield user.copy(
+ speedElos = {
+ val speed = Speed(game.clock)
+ val speedElo = user.speedElos(speed)
+ val opponentSpeedElo = SubElo(0, opponentElo)
+ val (white, black) = player.color.fold[(eloCalculator.User, eloCalculator.User)](
+ speedElo -> opponentSpeedElo,
+ opponentSpeedElo -> speedElo)
+ val newElos = eloCalculator.calculate(white, black, game.winnerColor)
+ val newElo = player.color.fold(newElos._1, newElos._2)
+ user.speedElos.addGame(speed, newElo)
+ },
+ variantElos = {
+ val variantElo = user.variantElos(game.variant)
+ val opponentVariantElo = SubElo(0, opponentElo)
+ val (white, black) = player.color.fold[(eloCalculator.User, eloCalculator.User)](
+ variantElo -> opponentVariantElo,
+ opponentVariantElo -> variantElo)
+ val newElos = eloCalculator.calculate(white, black, game.winnerColor)
+ val newElo = player.color.fold(newElos._1, newElos._2)
+ user.variantElos.addGame(game.variant, newElo)
+ }
+ )
+ ) | user
+ } flatMap { user ⇒
+ UserRepo.setSpeedElos(user.id, user.speedElos) >>
+ UserRepo.setVariantElos(user.id, user.variantElos)
+ }
private def usersQuery = $query.apply[User](
Json.obj(
diff --git a/modules/user/src/main/User.scala b/modules/user/src/main/User.scala
index e6d7958210..b6c5a6a4f9 100644
--- a/modules/user/src/main/User.scala
+++ b/modules/user/src/main/User.scala
@@ -9,6 +9,7 @@ case class User(
username: String,
elo: Int,
speedElos: SpeedElos,
+ variantElos: VariantElos,
count: Count,
troll: Boolean = false,
ipBan: Boolean = false,
@@ -57,6 +58,7 @@ object User {
private implicit def countTube = Count.tube
private implicit def speedElosTube = SpeedElos.tube
+ private implicit def variantElosTube = VariantElos.tube
private[user] lazy val tube = Tube[User](
(__.json update (
@@ -69,6 +71,7 @@ object User {
private def defaults = Json.obj(
"speedElos" -> SpeedElos.default,
+ "variantElos" -> VariantElos.default,
"troll" -> false,
"ipBan" -> false,
"settings" -> Json.obj(),
diff --git a/modules/user/src/main/UserRepo.scala b/modules/user/src/main/UserRepo.scala
index 8a713b3a23..623b6f7f8e 100644
--- a/modules/user/src/main/UserRepo.scala
+++ b/modules/user/src/main/UserRepo.scala
@@ -146,11 +146,16 @@ object UserRepo {
def setBio(id: ID, bio: String) = $update.field(id, "bio", bio)
- def setSpeedElos(id: ID)(ses: SpeedElos) = {
+ def setSpeedElos(id: ID, ses: SpeedElos) = {
import tube.speedElosTube
$update.field(id, "speedElos", ses)
}
+ def setVariantElos(id: ID, ses: VariantElos) = {
+ import tube.variantElosTube
+ $update.field(id, "variantElos", ses)
+ }
+
def enable(id: ID) = $update.field(id, "enabled", true)
def disable(id: ID) = $update.field(id, "enabled", false)
diff --git a/modules/user/src/main/VariantElos.scala b/modules/user/src/main/VariantElos.scala
new file mode 100644
index 0000000000..25ab2685be
--- /dev/null
+++ b/modules/user/src/main/VariantElos.scala
@@ -0,0 +1,55 @@
+package lila.user
+
+import chess.Variant
+import lila.db.Tube
+import play.api.libs.json._
+import Tube.Helpers._
+
+case class VariantElos(
+ standard: SubElo,
+ chess960: SubElo) {
+
+ def apply(variant: Variant) = variant match {
+ case Variant.Chess960 ⇒ chess960
+ case _ ⇒ standard
+ }
+
+ def toMap = Map(
+ Variant.Standard -> standard,
+ Variant.Chess960 -> chess960)
+
+ def addGame(variant: Variant, newElo: Int) = variant match {
+ case Variant.Chess960 ⇒ copy(chess960 = chess960 addGame newElo)
+ case Variant.Standard ⇒ copy(standard = standard addGame newElo)
+ case _ ⇒ this
+ }
+
+ def adjustTo(to: Int) = {
+ val nb = toMap.values.map(_.nb).sum
+ if (nb == 0) this else {
+ val median = (toMap.values map {
+ case SubElo(nb, elo) ⇒ nb * elo
+ }).sum / nb
+ val diff = to - median
+ def amortize(se: SubElo) = se withElo (se.elo + (diff * se.nb / nb))
+ VariantElos(
+ standard = amortize(standard),
+ chess960 = amortize(chess960))
+ }
+ }
+}
+
+object VariantElos {
+
+ val default = VariantElos(SubElo.default, SubElo.default)
+
+ private implicit def subEloTube = SubElo.tube
+
+ private[user] lazy val tube = Tube[VariantElos](
+ __.json update merge(defaults) andThen Json.reads[VariantElos],
+ Json.writes[VariantElos])
+
+ private def defaults = Json.obj(
+ "standard" -> SubElo.default,
+ "chess960" -> SubElo.default)
+}
diff --git a/modules/user/src/main/package.scala b/modules/user/src/main/package.scala
index 501df67762..a9895b3281 100644
--- a/modules/user/src/main/package.scala
+++ b/modules/user/src/main/package.scala
@@ -10,6 +10,7 @@ package object user extends PackageObject with WithPlay {
implicit lazy val userTube = User.tube inColl Env.current.userColl
private[user] implicit lazy val speedElosTube = SpeedElos.tube
+ private[user] implicit lazy val variantElosTube = VariantElos.tube
private[user] implicit lazy val historyTube =
Tube.json inColl Env.current.historyColl
diff --git a/todo b/todo
index d888017aa6..eb5f4ae825 100644
--- a/todo
+++ b/todo
@@ -70,8 +70,7 @@ customize piece images
opera bug http://postimg.org/image/zcv8hse8n/full/
customize sound notifications http://imgur.com/70WVyb5
show friend game results on timeline
-profile tweaks proposed by clarkey http://i.imgur.com/C57qoRC.jpg
-bullet < 3 min
+opera issue http://en.lichess.org/forum/lichess-feedback/new-game-wont-show-on-games-list-opera#1
---