forked from lichess-org/lila
-
Notifications
You must be signed in to change notification settings - Fork 0
/
HistoryApi.scala
71 lines (61 loc) · 2.65 KB
/
HistoryApi.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package lila.history
import org.joda.time.{ DateTime, Days }
import reactivemongo.bson._
import chess.Speed
import lila.db.dsl._
import lila.game.Game
import lila.rating.PerfType
import lila.user.{ User, Perfs }
final class HistoryApi(coll: Coll) {
import History._
def add(user: User, game: Game, perfs: Perfs): Funit = {
val isStd = game.ratingVariant.standard
val changes = List(
isStd.option("standard" -> perfs.standard),
game.ratingVariant.chess960.option("chess960" -> perfs.chess960),
game.ratingVariant.kingOfTheHill.option("kingOfTheHill" -> perfs.kingOfTheHill),
game.ratingVariant.threeCheck.option("threeCheck" -> perfs.threeCheck),
game.ratingVariant.antichess.option("antichess" -> perfs.antichess),
game.ratingVariant.atomic.option("atomic" -> perfs.atomic),
game.ratingVariant.horde.option("horde" -> perfs.horde),
game.ratingVariant.racingKings.option("racingKings" -> perfs.racingKings),
game.ratingVariant.crazyhouse.option("crazyhouse" -> perfs.crazyhouse),
(isStd && game.speed == Speed.Bullet).option("bullet" -> perfs.bullet),
(isStd && game.speed == Speed.Blitz).option("blitz" -> perfs.blitz),
(isStd && game.speed == Speed.Classical).option("classical" -> perfs.classical),
(isStd && game.speed == Speed.Correspondence).option("correspondence" -> perfs.correspondence)
).flatten.map {
case (k, p) => k -> p.intRating
}
val days = daysBetween(user.createdAt, game.updatedAt | game.createdAt)
coll.update(
$id(user.id),
$doc("$set" -> $doc(changes.map {
case (perf, rating) => s"$perf.$days" -> $int(rating)
})),
upsert = true
).void
}
// used for rating refunds
def setPerfRating(user: User, perf: PerfType, rating: Int): Funit = {
val days = daysBetween(user.createdAt, DateTime.now)
coll.update(
$id(user.id),
$set(s"${perf.key}.$days" -> $int(rating))
).void
}
def daysBetween(from: DateTime, to: DateTime): Int =
Days.daysBetween(from.withTimeAtStartOfDay, to.withTimeAtStartOfDay).getDays
def get(userId: String): Fu[Option[History]] = coll.uno[History]($id(userId))
def ratingsMap(user: User, perf: PerfType): Fu[RatingsMap] =
coll.primitiveOne[RatingsMap]($id(user.id), perf.key) map (~_)
def lastWeekTopRating(user: User, perf: PerfType): Fu[Int] = {
val days = daysBetween(user.createdAt, DateTime.now minusWeeks 1)
ratingsMap(user, perf) map { ratings =>
ratings.foldLeft(user.perfs(perf).intRating) {
case (rating, (d, r)) if d >= days && r > rating => r
case (rating, _) => rating
}
}
}
}