158 lines
5.3 KiB
Scala
158 lines
5.3 KiB
Scala
package lila.swiss
|
|
|
|
import chess.Clock.{ Config => ClockConfig }
|
|
import chess.format.FEN
|
|
import chess.variant.Variant
|
|
import chess.{ Color, StartingPosition }
|
|
import reactivemongo.api.bson._
|
|
import scala.concurrent.duration._
|
|
|
|
import lila.db.BSON
|
|
import lila.db.dsl._
|
|
import lila.user.User
|
|
|
|
private object BsonHandlers {
|
|
|
|
implicit val clockHandler = tryHandler[ClockConfig](
|
|
{ case doc: BSONDocument =>
|
|
for {
|
|
limit <- doc.getAsTry[Int]("limit")
|
|
inc <- doc.getAsTry[Int]("increment")
|
|
} yield ClockConfig(limit, inc)
|
|
},
|
|
c =>
|
|
BSONDocument(
|
|
"limit" -> c.limitSeconds,
|
|
"increment" -> c.incrementSeconds
|
|
)
|
|
)
|
|
implicit val variantHandler = lila.db.dsl.quickHandler[Variant](
|
|
{
|
|
case BSONString(v) => Variant orDefault v
|
|
case _ => Variant.default
|
|
},
|
|
v => BSONString(v.key)
|
|
)
|
|
private lazy val fenIndex: Map[String, StartingPosition] = StartingPosition.all.view.map { p =>
|
|
p.fen -> p
|
|
}.toMap
|
|
implicit val startingPositionHandler = lila.db.dsl.quickHandler[StartingPosition](
|
|
{
|
|
case BSONString(v) => fenIndex.getOrElse(v, StartingPosition.initial)
|
|
case _ => StartingPosition.initial
|
|
},
|
|
v => BSONString(v.fen)
|
|
)
|
|
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)
|
|
)
|
|
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
|
|
)
|
|
}
|
|
|
|
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
|
|
)
|
|
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
|
|
)
|
|
}
|
|
|
|
implicit val swissHandler = Macros.handler[Swiss]
|
|
|
|
def addFeaturable(s: Swiss) =
|
|
swissHandler.writeTry(s).get ++ {
|
|
s.isNotFinished ?? $doc("featurable" -> true)
|
|
}
|
|
}
|