lila/modules/swiss/src/main/BsonHandlers.scala

139 lines
4.8 KiB
Scala

package lila.swiss
import chess.Color
import chess.format.FEN
import reactivemongo.api.bson._
import scala.concurrent.duration._
import lila.db.BSON
import lila.db.dsl._
import lila.user.User
object BsonHandlers {
implicit val variantHandler = variantByKeyHandler
implicit val clockHandler = clockConfigHandler
implicit val swissPointsHandler = intAnyValHandler[Swiss.Points](_.double, Swiss.Points.apply)
implicit val swissTieBreakHandler = doubleAnyValHandler[Swiss.TieBreak](_.value, Swiss.TieBreak.apply)
implicit val swissPerformanceHandler =
floatAnyValHandler[Swiss.Performance](_.value, Swiss.Performance.apply)
implicit val swissScoreHandler = intAnyValHandler[Swiss.Score](_.value, Swiss.Score.apply)
implicit val roundNumberHandler = intAnyValHandler[SwissRound.Number](_.value, SwissRound.Number.apply)
implicit val swissIdHandler = stringAnyValHandler[Swiss.Id](_.value, Swiss.Id.apply)
implicit val playerIdHandler = stringAnyValHandler[SwissPlayer.Id](_.value, SwissPlayer.Id.apply)
implicit val playerHandler = new BSON[SwissPlayer] {
import SwissPlayer.Fields._
def reads(r: BSON.Reader) =
SwissPlayer(
id = r.get[SwissPlayer.Id](id),
swissId = r.get[Swiss.Id](swissId),
userId = r str userId,
rating = r int rating,
provisional = r boolD provisional,
points = r.get[Swiss.Points](points),
tieBreak = r.get[Swiss.TieBreak](tieBreak),
performance = r.getO[Swiss.Performance](performance),
score = r.get[Swiss.Score](score),
absent = r.boolD(absent),
byes = ~r.getO[Set[SwissRound.Number]](byes)
)
def writes(w: BSON.Writer, o: SwissPlayer) =
$doc(
id -> o.id,
swissId -> o.swissId,
userId -> o.userId,
rating -> o.rating,
provisional -> w.boolO(o.provisional),
points -> o.points,
tieBreak -> o.tieBreak,
performance -> o.performance,
score -> o.score,
absent -> w.boolO(o.absent),
byes -> o.byes.some.filter(_.nonEmpty)
)
}
implicit val pairingStatusHandler = lila.db.dsl.quickHandler[SwissPairing.Status](
{
case BSONBoolean(true) => Left(SwissPairing.Ongoing)
case BSONInteger(index) => Right(Color.fromWhite(index == 0).some)
case _ => Right(none)
},
{
case Left(_) => BSONBoolean(true)
case Right(Some(c)) => BSONInteger(c.fold(0, 1))
case _ => BSONNull
}
)
implicit val pairingHandler = new BSON[SwissPairing] {
import SwissPairing.Fields._
def reads(r: BSON.Reader) =
r.get[List[User.ID]](players) match {
case List(w, b) =>
SwissPairing(
id = r str id,
swissId = r.get[Swiss.Id](swissId),
round = r.get[SwissRound.Number](round),
white = w,
black = b,
status = r.getO[SwissPairing.Status](status) | Right(none),
isForfeit = r.boolD(isForfeit)
)
case _ => sys error "Invalid swiss pairing users"
}
def writes(w: BSON.Writer, o: SwissPairing) =
$doc(
id -> o.id,
swissId -> o.swissId,
round -> o.round,
players -> o.players,
status -> o.status,
isForfeit -> w.boolO(o.isForfeit)
)
}
import SwissCondition.BSONHandlers.AllBSONHandler
implicit val settingsHandler = new BSON[Swiss.Settings] {
def reads(r: BSON.Reader) =
Swiss.Settings(
nbRounds = r.get[Int]("n"),
rated = r.boolO("r") | true,
description = r.strO("d"),
position = r.getO[FEN]("f"),
chatFor = r.intO("c") | Swiss.ChatFor.default,
roundInterval = (r.intO("i") | 60).seconds,
password = r.strO("p"),
conditions = r.getO[SwissCondition.All]("o") getOrElse SwissCondition.All.empty,
forbiddenPairings = r.getD[String]("fp")
)
def writes(w: BSON.Writer, s: Swiss.Settings) =
$doc(
"n" -> s.nbRounds,
"r" -> (!s.rated).option(false),
"d" -> s.description,
"f" -> s.position,
"c" -> (s.chatFor != Swiss.ChatFor.default).option(s.chatFor),
"i" -> s.roundInterval.toSeconds.toInt,
"p" -> s.password,
"o" -> s.conditions.ifNonEmpty,
"fp" -> s.forbiddenPairings.some.filter(_.nonEmpty)
)
}
implicit val swissHandler = Macros.handler[Swiss]
// "featurable" mostly means that the tournament isn't over yet
def addFeaturable(s: Swiss) =
swissHandler.writeTry(s).get ++ {
s.isNotFinished ?? $doc(
"featurable" -> true,
"garbage" -> s.unrealisticSettings.option(true)
)
}
import Swiss.IdName
implicit val SwissIdNameBSONHandler = Macros.handler[IdName]
}