more tournament model and tubes
parent
31565c9d0f
commit
f062bf5b26
|
@ -503,7 +503,8 @@ private[game] object RawGame {
|
|||
"lmt" -> none[Int],
|
||||
"bm" -> none[Int],
|
||||
"r960" -> none[Boolean],
|
||||
"me" -> none[RawMetadata])
|
||||
"me" -> none[RawMetadata],
|
||||
"ua" -> none[DateTime])
|
||||
|
||||
private[game] lazy val tube = Tube(
|
||||
(__.json update (
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package lila.tournament
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import lila.common.PimpedConfig._
|
||||
import akka.actor._
|
||||
import akka.pattern.pipe
|
||||
|
||||
final class Env(
|
||||
config: Config,
|
||||
db: lila.db.Env,
|
||||
system: ActorSystem,
|
||||
hub: lila.hub.Env,
|
||||
scheduler: lila.common.Scheduler) {
|
||||
|
||||
private val settings = new {
|
||||
val OrganizerName = config getString "organizer.name"
|
||||
val CollectionTournament = config getString "collection.tournament"
|
||||
val CollectionRoom = config getString "collection.room"
|
||||
val MessageTtl = config duration "message.ttl"
|
||||
val MemoTtl = config duration "memo.ttl"
|
||||
val UidTimeout = config duration "uid.timeout"
|
||||
val HubTimeout = config duration "hub.timeout"
|
||||
}
|
||||
import settings._
|
||||
|
||||
private[tournament] lazy val tournamentColl = db(CollectionTournament)
|
||||
}
|
||||
|
||||
object Env {
|
||||
|
||||
private def app = play.api.Play.current
|
||||
|
||||
lazy val current = "[boot] tournamen" describes new Env(
|
||||
config = lila.common.PlayApp loadConfig "tournamen",
|
||||
db = lila.db.Env.current,
|
||||
system = lila.common.PlayApp.system,
|
||||
hub = lila.hub.Env.current,
|
||||
scheduler = lila.common.PlayApp.scheduler)
|
||||
}
|
|
@ -49,15 +49,6 @@ private[tournament] case class Pairing(
|
|||
)
|
||||
}
|
||||
|
||||
private[tournament] case class RawPairing(g: String, s: Int, u: List[String], w: Option[String], t: Option[Int]) {
|
||||
|
||||
def decode: Option[Pairing] = for {
|
||||
status ← chess.Status(s)
|
||||
user1 ← u.lift(0)
|
||||
user2 ← u.lift(1)
|
||||
} yield Pairing(g, status, user1, user2, w, t)
|
||||
}
|
||||
|
||||
private[tournament] object Pairing {
|
||||
|
||||
type P = (String, String)
|
||||
|
@ -135,3 +126,28 @@ private[tournament] object Pairing {
|
|||
case _ ⇒ Nil
|
||||
}
|
||||
}
|
||||
|
||||
private[tournament] case class RawPairing(g: String, s: Int, u: List[String], w: Option[String], t: Option[Int]) {
|
||||
|
||||
def decode: Option[Pairing] = for {
|
||||
status ← chess.Status(s)
|
||||
user1 ← u.lift(0)
|
||||
user2 ← u.lift(1)
|
||||
} yield Pairing(g, status, user1, user2, w, t)
|
||||
}
|
||||
|
||||
private[tournament] object RawPairing {
|
||||
|
||||
import lila.db.Tube
|
||||
import Tube.Helpers._
|
||||
import play.api.libs.json._
|
||||
|
||||
private def defaults = Json.obj(
|
||||
"w" -> none[String],
|
||||
"t" -> none[Int])
|
||||
|
||||
private[tournament] lazy val tube = Tube(
|
||||
(__.json update merge(defaults)) andThen Json.reads[RawPairing],
|
||||
Json.writes[RawPairing]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ private[tournament] case class Player(
|
|||
|
||||
private[tournament] object Player {
|
||||
|
||||
def apply(user: User): Player = new Player(
|
||||
def make(user: User): Player = new Player(
|
||||
id = user.id,
|
||||
username = user.username,
|
||||
elo = user.elo)
|
||||
|
@ -66,4 +66,20 @@ private[tournament] object Player {
|
|||
winStreak = bestWinSeq,
|
||||
score = score)
|
||||
}
|
||||
|
||||
import lila.db.Tube
|
||||
import Tube.Helpers._
|
||||
import play.api.libs.json._
|
||||
|
||||
private def defaults = Json.obj(
|
||||
"withdraw" -> false,
|
||||
"nbWin" -> 0,
|
||||
"nbLoss" -> 0,
|
||||
"winStreak" -> 0,
|
||||
"score" -> 0)
|
||||
|
||||
private[tournament] lazy val tube = Tube(
|
||||
(__.json update merge(defaults)) andThen Json.reads[Player],
|
||||
Json.writes[Player]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import chess.{ Variant, Mode }
|
|||
import lila.user.User
|
||||
import lila.game.PovRef
|
||||
|
||||
case class Data(
|
||||
private[tournament] case class Data(
|
||||
name: String,
|
||||
clock: TournamentClock,
|
||||
minutes: Int,
|
||||
|
@ -127,7 +127,7 @@ case class Created(
|
|||
|
||||
def join(user: User): Valid[Created] = contains(user).fold(
|
||||
!!("User %s is already part of the tournament" format user.id),
|
||||
withPlayers(players :+ Player(user)).success
|
||||
withPlayers(players :+ Player.make(user)).success
|
||||
)
|
||||
|
||||
def withdraw(userId: String): Valid[Created] = contains(userId).fold(
|
||||
|
@ -217,6 +217,45 @@ case class Finished(
|
|||
def encode = encode(Status.Finished)
|
||||
}
|
||||
|
||||
object Tournament {
|
||||
|
||||
import lila.db.Tube
|
||||
import play.api.libs.json._
|
||||
|
||||
private[tournament] lazy val tube = Tube(
|
||||
reader = Reads[Tournament](js ⇒
|
||||
~(for {
|
||||
obj ← js.asOpt[JsObject]
|
||||
rawTour ← RawTournament.tube.read(obj).asOpt
|
||||
tour ← rawTour.decode
|
||||
} yield JsSuccess(tour): JsResult[Tournament])
|
||||
),
|
||||
writer = Writes[Tournament](tour ⇒
|
||||
RawTournament.tube.write(tour.encode) getOrElse JsUndefined("[db] Can't write tournament " + tour.id)
|
||||
)
|
||||
)
|
||||
|
||||
def apply(
|
||||
createdBy: User,
|
||||
clock: TournamentClock,
|
||||
minutes: Int,
|
||||
minPlayers: Int,
|
||||
variant: Variant,
|
||||
mode: Mode): Created = Created(
|
||||
id = Random nextString 8,
|
||||
data = Data(
|
||||
name = RandomName(),
|
||||
clock = clock,
|
||||
createdBy = createdBy.id,
|
||||
createdAt = DateTime.now,
|
||||
variant = variant,
|
||||
mode = mode,
|
||||
minutes = minutes,
|
||||
minPlayers = minPlayers),
|
||||
players = List(Player make createdBy)
|
||||
)
|
||||
}
|
||||
|
||||
private[tournament] case class RawTournament(
|
||||
id: String,
|
||||
name: String,
|
||||
|
@ -232,6 +271,8 @@ private[tournament] case class RawTournament(
|
|||
variant: Int = Variant.Standard.id,
|
||||
mode: Int = Mode.Casual.id) {
|
||||
|
||||
def decode: Option[Tournament] = created orElse started orElse finished
|
||||
|
||||
def created: Option[Created] = (status == Status.Created.id) option Created(
|
||||
id = id,
|
||||
data = Data(name, clock, minutes, minPlayers, Variant orDefault variant, Mode orDefault mode, createdAt, createdBy),
|
||||
|
@ -266,27 +307,25 @@ private[tournament] case class RawTournament(
|
|||
}
|
||||
}
|
||||
|
||||
object Tournament {
|
||||
private[tournament] object RawTournament {
|
||||
|
||||
import lila.common.Form._
|
||||
import lila.db.Tube
|
||||
import Tube.Helpers._
|
||||
import play.api.libs.json._
|
||||
|
||||
def apply(
|
||||
createdBy: User,
|
||||
clock: TournamentClock,
|
||||
minutes: Int,
|
||||
minPlayers: Int,
|
||||
variant: Variant,
|
||||
mode: Mode): Created = Created(
|
||||
id = Random nextString 8,
|
||||
data = Data(
|
||||
name = RandomName(),
|
||||
clock = clock,
|
||||
createdBy = createdBy.id,
|
||||
createdAt = DateTime.now,
|
||||
variant = variant,
|
||||
mode = mode,
|
||||
minutes = minutes,
|
||||
minPlayers = minPlayers),
|
||||
players = List(Player(createdBy))
|
||||
private implicit def pairingTube = RawPairing.tube
|
||||
private implicit def clockTube = TournamentClock.tube
|
||||
private implicit def PlayerTube = Player.tube
|
||||
|
||||
private def defaults = Json.obj(
|
||||
"startedAt" -> none[DateTime])
|
||||
|
||||
private[tournament] lazy val tube = Tube(
|
||||
(__.json update (
|
||||
merge(defaults) andThen readDateOpt('startedAt)
|
||||
)) andThen Json.reads[RawTournament],
|
||||
Json.writes[RawTournament] andThen (__.json update (
|
||||
writeDateOpt('startedAt)
|
||||
))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,3 +9,15 @@ case class TournamentClock(limit: Int, increment: Int) {
|
|||
|
||||
def chessClock = chess.Clock(limit, increment)
|
||||
}
|
||||
|
||||
object TournamentClock {
|
||||
|
||||
import lila.db.Tube
|
||||
import Tube.Helpers._
|
||||
import play.api.libs.json._
|
||||
|
||||
private[tournament] lazy val tube = Tube(
|
||||
Json.reads[TournamentClock],
|
||||
Json.writes[TournamentClock]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package lila.tournament
|
||||
|
||||
import lila.db.api._
|
||||
import lila.db.Implicits._
|
||||
import tube.tournamentTube
|
||||
|
||||
import play.api.libs.json._
|
||||
import org.joda.time.DateTime
|
||||
import org.scala_tools.time.Imports._
|
||||
|
||||
// object TournamentRepo {
|
||||
|
||||
// def createdById(id: String): Fu[Option[Created]] = byIdAs(id, _.created)
|
||||
|
||||
// def startedById(id: String): Fu[Option[Started]] = byIdAs(id, _.started)
|
||||
|
||||
// def createdByIdAndCreator(id: String, userId: String): Fu[Option[Created]] =
|
||||
// createdById(id) map (_ filter (_ isCreator userId))
|
||||
|
||||
// private def byIdAs[A](id: String, as: Tournament ⇒ Option[A]): Fu[Option[A]] = io {
|
||||
// $find byId id map (_ flatMap as)
|
||||
// }
|
||||
|
||||
// def created: Fu[List[Created]] =
|
||||
// $find($query(
|
||||
// Json.obj("status" -> Status.Created.id)) sort $sort.createdDesc
|
||||
// )).toList map2 { (tour: Tournament) => tour.created }
|
||||
|
||||
// def started: Fu[List[Started]] = io {
|
||||
// find(DBObject("status" -> Status.Started.id))
|
||||
// .sort(DBObject("createdAt" -> -1))
|
||||
// .toList.map(_.started).flatten
|
||||
// }
|
||||
|
||||
// def finished(limit: Int): Fu[List[Finished]] = io {
|
||||
// find(DBObject("status" -> Status.Finished.id))
|
||||
// .sort(DBObject("createdAt" -> -1))
|
||||
// .limit(limit)
|
||||
// .toList.map(_.finished).flatten
|
||||
// }
|
||||
|
||||
// def setUsers(tourId: String, userIds: List[String]): Fu[Unit] = io {
|
||||
// update(idSelector(tourId), $set(Seq("data.users" -> userIds.distinct)))
|
||||
// }
|
||||
|
||||
// def userHasRunningTournament(username: String): Fu[Boolean] = io {
|
||||
// collection.findOne(
|
||||
// ("status" $ne Status.Finished.id) ++ ("data.users" -> username)
|
||||
// ).isDefined
|
||||
// }
|
||||
|
||||
// val inProgressIds: Fu[List[String]] = io {
|
||||
// primitiveProjections(DBObject("status" -> Status.Started.id), "_id")
|
||||
// }
|
||||
|
||||
// def saveFu(tournament: Tournament): Fu[Unit] = io {
|
||||
// save(tournament.encode)
|
||||
// }
|
||||
|
||||
// def removeFu(tournament: Tournament): Fu[Unit] = io {
|
||||
// remove(idSelector(tournament))
|
||||
// }
|
||||
|
||||
// def withdraw(userId: String): Fu[List[String]] = for {
|
||||
// createds ← created
|
||||
// createdIds ← (createds map (_ withdraw userId) collect {
|
||||
// case Success(tour) ⇒ saveFu(tour) map (_ ⇒ tour.id)
|
||||
// }).sequence
|
||||
// starteds ← started
|
||||
// startedIds ← (starteds map (_ withdraw userId) collect {
|
||||
// case Success(tour) ⇒ saveFu(tour) map (_ ⇒ tour.id)
|
||||
// }).sequence
|
||||
// } yield createdIds ::: startedIds
|
||||
|
||||
// private def idSelector(id: String): DBObject = DBObject("_id" -> id)
|
||||
// private def idSelector(tournament: Tournament): DBObject = idSelector(tournament.id)
|
||||
// }
|
|
@ -6,7 +6,7 @@ package object tournament extends PackageObject with WithPlay {
|
|||
|
||||
object tube {
|
||||
|
||||
// private[tournament] implicit lazy val pgnTube = Tube.json inColl Env.current.pgnColl
|
||||
private[tournament] implicit lazy val tournamentTube = Tournament.tube inColl Env.current.tournamentColl
|
||||
}
|
||||
|
||||
private[tournament]type Pairings = List[tournament.Pairing]
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
package lila.app
|
||||
package tournament
|
||||
|
||||
import com.novus.salat._
|
||||
import com.novus.salat.dao._
|
||||
import com.mongodb.casbah.MongoCollection
|
||||
import com.mongodb.casbah.query.Imports._
|
||||
import scalaz.effects._
|
||||
import scalaz.Success
|
||||
import org.joda.time.DateTime
|
||||
import org.scala_tools.time.Imports._
|
||||
|
||||
import user.User
|
||||
|
||||
class TournamentRepo(collection: MongoCollection)
|
||||
extends SalatDAO[RawTournament, String](collection) {
|
||||
|
||||
def byId(id: String): IO[Option[Tournament]] = byIdAs(id, _.any)
|
||||
def byId(id: Option[String]): IO[Option[Tournament]] =
|
||||
id.fold(io(none[Tournament])) { i ⇒ byIdAs(i, _.any) }
|
||||
|
||||
def createdById(id: String): IO[Option[Created]] = byIdAs(id, _.created)
|
||||
|
||||
def startedById(id: String): IO[Option[Started]] = byIdAs(id, _.started)
|
||||
|
||||
def createdByIdAndCreator(id: String, userId: String): IO[Option[Created]] =
|
||||
createdById(id) map { tour ⇒ tour filter (_ isCreator userId) }
|
||||
|
||||
private def byIdAs[A](id: String, as: RawTournament ⇒ Option[A]): IO[Option[A]] = io {
|
||||
findOneById(id) flatMap as
|
||||
}
|
||||
|
||||
val created: IO[List[Created]] = io {
|
||||
find(DBObject("status" -> Status.Created.id))
|
||||
.sort(DBObject("createdAt" -> -1))
|
||||
.toList.map(_.created).flatten
|
||||
}
|
||||
|
||||
val started: IO[List[Started]] = io {
|
||||
find(DBObject("status" -> Status.Started.id))
|
||||
.sort(DBObject("createdAt" -> -1))
|
||||
.toList.map(_.started).flatten
|
||||
}
|
||||
|
||||
def finished(limit: Int): IO[List[Finished]] = io {
|
||||
find(DBObject("status" -> Status.Finished.id))
|
||||
.sort(DBObject("createdAt" -> -1))
|
||||
.limit(limit)
|
||||
.toList.map(_.finished).flatten
|
||||
}
|
||||
|
||||
def setUsers(tourId: String, userIds: List[String]): IO[Unit] = io {
|
||||
update(idSelector(tourId), $set(Seq("data.users" -> userIds.distinct)))
|
||||
}
|
||||
|
||||
def userHasRunningTournament(username: String): IO[Boolean] = io {
|
||||
collection.findOne(
|
||||
("status" $ne Status.Finished.id) ++ ("data.users" -> username)
|
||||
).isDefined
|
||||
}
|
||||
|
||||
val inProgressIds: IO[List[String]] = io {
|
||||
primitiveProjections(DBObject("status" -> Status.Started.id), "_id")
|
||||
}
|
||||
|
||||
def saveIO(tournament: Tournament): IO[Unit] = io {
|
||||
save(tournament.encode)
|
||||
}
|
||||
|
||||
def removeIO(tournament: Tournament): IO[Unit] = io {
|
||||
remove(idSelector(tournament))
|
||||
}
|
||||
|
||||
def withdraw(userId: String): IO[List[String]] = for {
|
||||
createds ← created
|
||||
createdIds ← (createds map (_ withdraw userId) collect {
|
||||
case Success(tour) ⇒ saveIO(tour) map (_ ⇒ tour.id)
|
||||
}).sequence
|
||||
starteds ← started
|
||||
startedIds ← (starteds map (_ withdraw userId) collect {
|
||||
case Success(tour) ⇒ saveIO(tour) map (_ ⇒ tour.id)
|
||||
}).sequence
|
||||
} yield createdIds ::: startedIds
|
||||
|
||||
private def idSelector(id: String): DBObject = DBObject("_id" -> id)
|
||||
private def idSelector(tournament: Tournament): DBObject = idSelector(tournament.id)
|
||||
}
|
Loading…
Reference in New Issue