swiss models and handlers
parent
4b0199964e
commit
c209918070
|
@ -54,7 +54,7 @@ lazy val modules = Seq(
|
|||
playban, insight, perfStat, slack, quote, challenge,
|
||||
study, studySearch, fishnet, explorer, learn, plan,
|
||||
event, coach, practice, evalCache, irwin,
|
||||
activity, relay, streamer, bot, clas
|
||||
activity, relay, streamer, bot, clas, swiss
|
||||
)
|
||||
|
||||
lazy val moduleRefs = modules map projectToRef
|
||||
|
@ -253,6 +253,11 @@ lazy val tournament = module("tournament",
|
|||
Seq(scalatags, lettuce) ++ reactivemongo.bundle
|
||||
)
|
||||
|
||||
lazy val swiss = module("swiss",
|
||||
Seq(common, hub, socket, game, round, security, chat, memo, i18n, room),
|
||||
Seq(scalatags, lettuce) ++ reactivemongo.bundle
|
||||
)
|
||||
|
||||
lazy val simul = module("simul",
|
||||
Seq(common, hub, socket, game, round, chat, memo, quote, room),
|
||||
Seq(lettuce) ++ reactivemongo.bundle
|
||||
|
|
|
@ -37,6 +37,7 @@ trait Lilaisms
|
|||
with scalaz.syntax.ToValidationOps {
|
||||
|
||||
type StringValue = lila.base.LilaTypes.StringValue
|
||||
type IntValue = lila.base.LilaTypes.IntValue
|
||||
|
||||
@inline implicit def toPimpedFuture[A](f: Fu[A]) = new PimpedFuture(f)
|
||||
@inline implicit def toPimpedFutureBoolean(f: Fu[Boolean]) = new PimpedFutureBoolean(f)
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
package lila.swiss
|
||||
|
||||
import chess.Clock.{ Config => ClockConfig }
|
||||
import chess.variant.Variant
|
||||
import chess.StartingPosition
|
||||
import lila.db.BSON
|
||||
import lila.db.dsl._
|
||||
import reactivemongo.api.bson._
|
||||
|
||||
private object BsonHandlers {
|
||||
|
||||
implicit private[swiss] val statusHandler = tryHandler[Status](
|
||||
{ case BSONInteger(v) => Status(v) toTry s"No such status: $v" },
|
||||
x => BSONInteger(x.id)
|
||||
)
|
||||
|
||||
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 playerNumberHandler = intAnyValHandler[SwissPlayer.Number](_.value, SwissPlayer.Number.apply)
|
||||
implicit val playerIdHandler = tryHandler[SwissPlayer.Id](
|
||||
{
|
||||
case BSONString(v) =>
|
||||
(v split ':' match {
|
||||
case Array(swissId, number) =>
|
||||
number.toIntOption map { n =>
|
||||
SwissPlayer.Id(Swiss.Id(swissId), SwissPlayer.Number(n))
|
||||
}
|
||||
case _ => None
|
||||
}) toTry s"Invalid player ID $v"
|
||||
},
|
||||
id => BSONString(s"${id.swissId}:${id.number}")
|
||||
)
|
||||
|
||||
implicit val playerHandler = new BSON[SwissPlayer] {
|
||||
def reads(r: BSON.Reader) = SwissPlayer(
|
||||
id = r.get[SwissPlayer.Id]("_id"),
|
||||
userId = r str "uid",
|
||||
rating = r int "r",
|
||||
provisional = r boolD "pr"
|
||||
)
|
||||
def writes(w: BSON.Writer, o: SwissPlayer) = $doc(
|
||||
"_id" -> o.id,
|
||||
"uid" -> o.userId,
|
||||
"r" -> o.rating,
|
||||
"pr" -> w.boolO(o.provisional)
|
||||
)
|
||||
}
|
||||
|
||||
implicit val pairingHandler = new BSON[SwissPairing] {
|
||||
def reads(r: BSON.Reader) = {
|
||||
val white = r.get[SwissPlayer.Number]("w")
|
||||
val black = r.get[SwissPlayer.Number]("b")
|
||||
SwissPairing(
|
||||
gameId = r str "g",
|
||||
white = white,
|
||||
black = black,
|
||||
winner = r boolO "w" map {
|
||||
case true => white
|
||||
case _ => black
|
||||
}
|
||||
)
|
||||
}
|
||||
def writes(w: BSON.Writer, o: SwissPairing) = $doc(
|
||||
"g" -> o.gameId,
|
||||
"w" -> o.white,
|
||||
"b" -> o.black,
|
||||
"w" -> o.winner.map(o.white ==)
|
||||
)
|
||||
}
|
||||
|
||||
implicit val roundNumberHandler = intAnyValHandler[SwissRound.Number](_.value, SwissRound.Number.apply)
|
||||
implicit val roundIdHandler = tryHandler[SwissRound.Id](
|
||||
{
|
||||
case BSONString(v) =>
|
||||
(v split ':' match {
|
||||
case Array(swissId, number) =>
|
||||
number.toIntOption map { n =>
|
||||
SwissRound.Id(Swiss.Id(swissId), SwissRound.Number(n))
|
||||
}
|
||||
case _ => None
|
||||
}) toTry s"Invalid round ID $v"
|
||||
},
|
||||
id => BSONString(id.toString)
|
||||
)
|
||||
|
||||
implicit val roundHandler = new BSON[SwissRound] {
|
||||
def reads(r: BSON.Reader) =
|
||||
SwissRound(
|
||||
id = r.get[SwissRound.Id]("_id"),
|
||||
pairings = r.get[List[SwissPairing]]("p"),
|
||||
byes = r.get[List[SwissPlayer.Number]]("b")
|
||||
)
|
||||
def writes(w: BSON.Writer, o: SwissRound) = $doc(
|
||||
"id" -> o.id,
|
||||
"p" -> o.pairings,
|
||||
"b" -> o.byes
|
||||
)
|
||||
}
|
||||
|
||||
implicit val swissIdHandler = stringAnyValHandler[Swiss.Id](_.value, Swiss.Id.apply)
|
||||
implicit val swissHandler = Macros.handler[Swiss]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package lila.clas
|
||||
|
||||
import com.softwaremill.macwire._
|
||||
|
||||
import lila.common.config._
|
||||
|
||||
@Module
|
||||
final class Env(
|
||||
db: lila.db.Db,
|
||||
userRepo: lila.user.UserRepo
|
||||
)(implicit ec: scala.concurrent.ExecutionContext) {
|
||||
|
||||
private val colls = wire[SwissColls]
|
||||
|
||||
}
|
||||
|
||||
private class SwissColls(db: lila.db.Db) {
|
||||
val swiss = db(CollName("swiss"))
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package lila.swiss
|
||||
|
||||
sealed abstract private[swiss] class Status(val id: Int) extends Ordered[Status] {
|
||||
def compare(other: Status) = Integer.compare(id, other.id)
|
||||
def name = toString
|
||||
def is(s: Status): Boolean = this == s
|
||||
}
|
||||
|
||||
private[swiss] object Status {
|
||||
|
||||
case object Created extends Status(10)
|
||||
case object Started extends Status(20)
|
||||
case object Finished extends Status(30)
|
||||
|
||||
val all = List(Created, Started, Finished)
|
||||
|
||||
val byId = all map { v =>
|
||||
(v.id, v)
|
||||
} toMap
|
||||
|
||||
def apply(id: Int): Option[Status] = byId get id
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package lila.swiss
|
||||
|
||||
import org.joda.time.{ DateTime, Duration, Interval }
|
||||
import ornicar.scalalib.Random
|
||||
import chess.Clock.{ Config => ClockConfig }
|
||||
import chess.StartingPosition
|
||||
|
||||
import lila.user.User
|
||||
import lila.game.Game
|
||||
|
||||
case class Swiss(
|
||||
_id: Swiss.Id,
|
||||
name: String,
|
||||
status: Status,
|
||||
clock: ClockConfig,
|
||||
variant: chess.variant.Variant,
|
||||
position: StartingPosition,
|
||||
rated: Boolean,
|
||||
nbRounds: Int,
|
||||
nbPlayers: Int,
|
||||
createdAt: DateTime,
|
||||
createdBy: User.ID,
|
||||
startsAt: DateTime,
|
||||
winnerId: Option[User.ID] = None,
|
||||
description: Option[String] = None,
|
||||
hasChat: Boolean = true
|
||||
) {}
|
||||
|
||||
object Swiss {
|
||||
|
||||
case class Id(value: String) extends AnyVal with StringValue
|
||||
case class Round(value: Int) extends AnyVal with IntValue
|
||||
|
||||
def makeId = Id(scala.util.Random.alphanumeric take 8 mkString)
|
||||
}
|
||||
|
||||
case class SwissPlayer(
|
||||
id: SwissPlayer.Id,
|
||||
userId: User.ID,
|
||||
rating: Int,
|
||||
provisional: Boolean
|
||||
)
|
||||
|
||||
object SwissPlayer {
|
||||
|
||||
case class Id(swissId: Swiss.Id, number: Number)
|
||||
|
||||
case class Number(value: Int) extends AnyVal with IntValue
|
||||
}
|
||||
|
||||
case class SwissRound(
|
||||
id: SwissRound.Id,
|
||||
pairings: List[SwissPairing],
|
||||
byes: List[SwissPlayer.Number]
|
||||
) {}
|
||||
|
||||
object SwissRound {
|
||||
|
||||
case class Id(swissId: Swiss.Id, number: Number) {
|
||||
override def toString = s"$swissId:$number"
|
||||
}
|
||||
|
||||
case class Number(value: Int) extends AnyVal with IntValue
|
||||
}
|
||||
|
||||
case class SwissPairing(
|
||||
gameId: Game.ID,
|
||||
white: SwissPlayer.Number,
|
||||
black: SwissPlayer.Number,
|
||||
winner: Option[SwissPlayer.Number]
|
||||
)
|
||||
|
||||
object SwissPairing {
|
||||
|
||||
case class Id(value: String) extends AnyVal with StringValue
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package lila
|
||||
|
||||
package object swiss extends PackageObject {
|
||||
|
||||
private[swiss] val logger = lila.log("swiss")
|
||||
}
|
|
@ -5,7 +5,7 @@ import lila.game.{ Game, IdGenerator }
|
|||
import lila.user.User
|
||||
|
||||
case class Pairing(
|
||||
id: Game.ID, // game Id
|
||||
id: Game.ID,
|
||||
tourId: Tournament.ID,
|
||||
status: chess.Status,
|
||||
user1: User.ID,
|
||||
|
|
Loading…
Reference in New Issue