forked from lichess-org/lila
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PairingRepo.scala
121 lines (98 loc) · 4.68 KB
/
PairingRepo.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package lila.tournament
import org.joda.time.DateTime
import reactivemongo.bson._
import reactivemongo.core.commands._
import BSONHandlers._
import lila.db.BSON._
import lila.db.Implicits._
object PairingRepo {
private lazy val coll = Env.current.pairingColl
private def selectId(id: String) = BSONDocument("_id" -> id)
private def selectTour(tourId: String) = BSONDocument("tid" -> tourId)
private def selectUser(userId: String) = BSONDocument("u" -> userId)
private def selectTourUser(tourId: String, userId: String) = BSONDocument(
"tid" -> tourId,
"u" -> userId)
private val selectPlaying = BSONDocument("s" -> BSONDocument("$lt" -> chess.Status.Mate.id))
private val selectFinished = BSONDocument("s" -> BSONDocument("$gte" -> chess.Status.Mate.id))
private val recentSort = BSONDocument("d" -> -1)
private val chronoSort = BSONDocument("d" -> 1)
def byId(id: String): Fu[Option[Pairing]] = coll.find(selectId(id)).one[Pairing]
def recentByTour(tourId: String, nb: Int): Fu[List[Pairing]] =
coll.find(selectTour(tourId)).sort(recentSort).cursor[Pairing]().collect[List](nb)
def recentUidsByTourAndUserIds(tourId: String, userIds: Iterable[String], nb: Int): Fu[List[Pairing.Uids]] =
coll.find(
selectTour(tourId) ++ BSONDocument("u" -> BSONDocument("$in" -> userIds)),
BSONDocument("_id" -> false, "u" -> true)
).sort(recentSort).cursor[Pairing.Uids]().collect[List](nb)
def recentIdsByTourAndUserId(tourId: String, userId: String, nb: Int): Fu[List[String]] =
coll.find(
selectTour(tourId) ++ BSONDocument("u" -> userId),
BSONDocument("_id" -> true)
).sort(recentSort).cursor[BSONDocument]().collect[List](nb).map {
_.flatMap(_.getAs[String]("_id"))
}
def byTourUserNb(tourId: String, userId: String, nb: Int): Fu[Option[Pairing]] =
(nb > 0) ?? coll.find(
selectTour(tourId) ++ BSONDocument("u" -> userId)
).sort(chronoSort).skip(nb - 1).one[Pairing]
def removeByTour(tourId: String) = coll.remove(selectTour(tourId)).void
def count(tourId: String): Fu[Int] =
coll.count(selectTour(tourId).some)
def countByTourIdAndUserIds(tourId: String): Fu[Map[String, Int]] = {
import reactivemongo.api.collections.bson.BSONBatchCommands.AggregationFramework._
coll.aggregate(
Match(selectTour(tourId)),
List(
Project(BSONDocument("u" -> true, "_id" -> false)),
Unwind("u"),
GroupField("u")("nb" -> SumValue(1))
)).map {
_.documents.flatMap { doc =>
doc.getAs[String]("_id") flatMap { uid =>
doc.getAs[Int]("nb") map { uid -> _ }
}
}.toMap
}
}
def removePlaying(tourId: String) = coll.remove(selectTour(tourId) ++ selectPlaying).void
def findPlaying(tourId: String): Fu[List[Pairing]] =
coll.find(selectTour(tourId) ++ selectPlaying).cursor[Pairing]().collect[List]()
def findPlaying(tourId: String, userId: String): Fu[Option[Pairing]] =
coll.find(selectTourUser(tourId, userId) ++ selectPlaying).one[Pairing]
def finishedByPlayerChronological(tourId: String, userId: String): Fu[List[Pairing]] =
coll.find(
selectTourUser(tourId, userId) ++ selectFinished
).sort(chronoSort).cursor[Pairing]().collect[List]()
def insert(pairing: Pairing) = coll.insert {
pairingHandler.write(pairing) ++ BSONDocument("d" -> DateTime.now)
}.void
def finish(g: lila.game.Game) = coll.update(
selectId(g.id),
BSONDocument("$set" -> BSONDocument(
"s" -> g.status.id,
"w" -> g.winnerColor.map(_.white),
"t" -> g.turns))).void
def setBerserk(pairing: Pairing, userId: String, value: Int) = (userId match {
case uid if pairing.user1 == uid => "b1".some
case uid if pairing.user2 == uid => "b2".some
case _ => none
}) ?? { field =>
coll.update(
selectId(pairing.id),
BSONDocument("$set" -> BSONDocument(field -> value))).void
}
import coll.BatchCommands.AggregationFramework, AggregationFramework.{ AddToSet, Group, Match, Project, Push, Unwind }
def playingUserIds(tour: Tournament): Fu[Set[String]] =
coll.aggregate(Match(selectTour(tour.id) ++ selectPlaying), List(
Project(BSONDocument(
"u" -> BSONBoolean(true), "_id" -> BSONBoolean(false))),
Unwind("u"), Group(BSONBoolean(true))("ids" -> AddToSet("u")))).map(
_.documents.headOption.flatMap(_.getAs[Set[String]]("ids")).
getOrElse(Set.empty[String]))
def playingGameIds(tourId: String): Fu[List[String]] =
coll.aggregate(Match(selectTour(tourId) ++ selectPlaying), List(
Group(BSONBoolean(true))("ids" -> Push("_id")))).map(
_.documents.headOption.flatMap(_.getAs[List[String]]("ids")).
getOrElse(List.empty[String]))
}