tournament pairing countdown WIP
parent
9130dad304
commit
156d92d1ba
|
@ -44,6 +44,7 @@ object BSONHandlers {
|
|||
createdAt = r date "createdAt",
|
||||
createdBy = r str "createdBy",
|
||||
startsAt = startsAt,
|
||||
pairsAt = r dateO "pairsAt",
|
||||
winnerId = r strO "winner")
|
||||
}
|
||||
def writes(w: BSON.Writer, o: Tournament) = BSONDocument(
|
||||
|
@ -66,6 +67,7 @@ object BSONHandlers {
|
|||
"createdAt" -> w.date(o.createdAt),
|
||||
"createdBy" -> w.str(o.createdBy),
|
||||
"startsAt" -> w.date(o.startsAt),
|
||||
"pairsAt" -> o.pairsAt.map(w.date),
|
||||
"winner" -> o.winnerId)
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ final class Env(
|
|||
val SequencerTimeout = config duration "sequencer.timeout"
|
||||
val SequencerMapName = config getString "sequencer.map_name"
|
||||
val NetDomain = config getString "net.domain"
|
||||
val PairingDelay = config duration "pairing.delay"
|
||||
}
|
||||
import settings._
|
||||
|
||||
|
@ -54,6 +55,7 @@ final class Env(
|
|||
system = system,
|
||||
sequencers = sequencerMap,
|
||||
autoPairing = autoPairing,
|
||||
pairingDelay = PairingDelay,
|
||||
clearJsonViewCache = jsonView.clearCache,
|
||||
router = hub.actor.router,
|
||||
renderer = hub.actor.renderer,
|
||||
|
@ -120,7 +122,7 @@ final class Env(
|
|||
organizer -> actorApi.AllCreatedTournaments
|
||||
}
|
||||
|
||||
scheduler.message(3 seconds) {
|
||||
scheduler.message(PairingDelay) {
|
||||
organizer -> actorApi.StartedTournaments
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package lila.tournament
|
||||
|
||||
import actorApi._
|
||||
import akka.actor._
|
||||
import akka.pattern.{ ask, pipe }
|
||||
|
||||
import actorApi._
|
||||
import lila.game.actorApi.FinishGame
|
||||
import lila.hub.actorApi.map.Ask
|
||||
import lila.hub.actorApi.WithUserIds
|
||||
import makeTimeout.short
|
||||
import org.joda.time.DateTime
|
||||
|
||||
private[tournament] final class Organizer(
|
||||
api: TournamentApi,
|
||||
|
@ -36,7 +36,7 @@ private[tournament] final class Organizer(
|
|||
}
|
||||
|
||||
case StartedTournaments =>
|
||||
val startAt = nowMillis
|
||||
val startAt = DateTime.now
|
||||
TournamentRepo.started foreach {
|
||||
_ foreach { tour =>
|
||||
PlayerRepo activeUserIds tour.id foreach { activeUserIds =>
|
||||
|
@ -62,7 +62,7 @@ private[tournament] final class Organizer(
|
|||
_ filterNot isOnline foreach { api.withdraw(tour.id, _) }
|
||||
}
|
||||
|
||||
private def startPairing(tour: Tournament, activeUserIds: List[String], startAt: Long) =
|
||||
private def startPairing(tour: Tournament, activeUserIds: List[String], startAt: DateTime) =
|
||||
getWaitingUsers(tour) zip PairingRepo.playingUserIds(tour) foreach {
|
||||
case (waitingUsers, playingUserIds) =>
|
||||
val users = waitingUsers intersect activeUserIds diff playingUserIds
|
||||
|
|
|
@ -23,6 +23,7 @@ case class Tournament(
|
|||
createdAt: DateTime,
|
||||
createdBy: String,
|
||||
startsAt: DateTime,
|
||||
pairsAt: Option[DateTime] = None,
|
||||
winnerId: Option[String] = None) {
|
||||
|
||||
def isCreated = status == Status.Created
|
||||
|
|
|
@ -27,6 +27,7 @@ private[tournament] final class TournamentApi(
|
|||
system: ActorSystem,
|
||||
sequencers: ActorRef,
|
||||
autoPairing: AutoPairing,
|
||||
pairingDelay: Duration,
|
||||
clearJsonViewCache: String => Funit,
|
||||
router: ActorSelection,
|
||||
renderer: ActorSelection,
|
||||
|
@ -59,19 +60,21 @@ private[tournament] final class TournamentApi(
|
|||
TournamentRepo.insert(created).void >>- publish()
|
||||
}
|
||||
|
||||
def makePairings(oldTour: Tournament, users: WaitingUsers, startAt: Long) {
|
||||
def makePairings(oldTour: Tournament, users: WaitingUsers, startAt: DateTime) {
|
||||
Sequencing(oldTour.id)(TournamentRepo.startedById) { tour =>
|
||||
tour.system.pairingSystem.createPairings(tour, users) flatMap {
|
||||
case Nil => funit
|
||||
case pairings if nowMillis - startAt > 1000 =>
|
||||
play.api.Logger("tourpairing").warn(s"Give up making http://lichess.org/tournament/${tour.id} ${pairings.size} pairings in ${nowMillis - startAt}ms")
|
||||
case pairings if nowMillis - startAt.getMillis > 1000 =>
|
||||
play.api.Logger("tourpairing").warn(s"Give up making http://lichess.org/tournament/${tour.id} ${pairings.size} pairings in ${nowMillis - startAt.getMillis}ms")
|
||||
funit
|
||||
case pairings => pairings.map { pairing =>
|
||||
PairingRepo.insert(pairing) >> autoPairing(tour, pairing)
|
||||
}.sequenceFu.map {
|
||||
_ map StartGame.apply foreach { sendTo(tour.id, _) }
|
||||
}.sequenceFu.flatMap { games =>
|
||||
TournamentRepo.setPairsAt(tour.id, startAt plus pairingDelay.toMillis) inject {
|
||||
games map StartGame.apply foreach { sendTo(tour.id, _) }
|
||||
}
|
||||
} >>- {
|
||||
val time = nowMillis - startAt
|
||||
val time = nowMillis - startAt.getMillis
|
||||
if (time > 100)
|
||||
play.api.Logger("tourpairing").debug(s"Done making http://lichess.org/tournament/${tour.id} ${pairings.size} pairings in ${time}ms")
|
||||
}
|
||||
|
|
|
@ -89,6 +89,11 @@ object TournamentRepo {
|
|||
BSONDocument("$set" -> BSONDocument("winner" -> userId))
|
||||
).void
|
||||
|
||||
def setPairsAt(tourId: String, pairsAt: DateTime) = coll.update(
|
||||
selectId(tourId),
|
||||
BSONDocument("$set" -> BSONDocument("pairsAt" -> pairsAt))
|
||||
).void
|
||||
|
||||
private def allCreatedSelect(aheadMinutes: Int) = createdSelect ++ BSONDocument(
|
||||
"$or" -> BSONArray(
|
||||
BSONDocument("schedule" -> BSONDocument("$exists" -> false)),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package lila.tournament
|
||||
|
||||
import org.joda.time.DateTime
|
||||
import scala.concurrent.duration._
|
||||
|
||||
private[tournament] case class WaitingUsers(
|
||||
hash: Map[String, DateTime],
|
||||
|
@ -11,10 +12,12 @@ private[tournament] case class WaitingUsers(
|
|||
// 3+0 -> 16 -> 16
|
||||
// 5+0 -> 24 -> 24
|
||||
// 10+0 -> 44 -> 35
|
||||
private val waitSeconds = {
|
||||
val waitSeconds = {
|
||||
(clock.fold(60)(_.estimateTotalTime) / 15) + 4
|
||||
} min 35 max 10
|
||||
|
||||
val waitDuration = waitSeconds.seconds
|
||||
|
||||
lazy val all = hash.keys.toList
|
||||
lazy val size = hash.size
|
||||
|
||||
|
@ -26,10 +29,6 @@ private[tournament] case class WaitingUsers(
|
|||
else all
|
||||
}
|
||||
|
||||
def waitSecondsOf(userId: String) = hash get userId map { d =>
|
||||
nowSeconds - d.getSeconds
|
||||
}
|
||||
|
||||
def waiting = {
|
||||
val since = date minusSeconds waitSeconds
|
||||
hash.collect {
|
||||
|
@ -37,6 +36,16 @@ private[tournament] case class WaitingUsers(
|
|||
}.toList
|
||||
}
|
||||
|
||||
def minWaitToPairing: Option[Duration] =
|
||||
hash.foldLeft(none[Duration]) {
|
||||
case (res, (u, d)) =>
|
||||
case (u, d) if d.isBefore(since) => u
|
||||
}.toList
|
||||
|
||||
def waitSecondsOf(userId: String) = hash get userId map { d =>
|
||||
nowSeconds - d.getSeconds
|
||||
}
|
||||
|
||||
def update(us: Seq[String], clock: Option[chess.Clock]) = {
|
||||
val newDate = DateTime.now
|
||||
copy(
|
||||
|
|
|
@ -2,6 +2,7 @@ package lila.tournament
|
|||
package arena
|
||||
|
||||
import lila.tournament.{ PairingSystem => AbstractPairingSystem }
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import scala.util.Random
|
||||
|
||||
|
@ -18,16 +19,16 @@ object PairingSystem extends AbstractPairingSystem {
|
|||
// then pair all users
|
||||
def createPairings(
|
||||
tour: Tournament,
|
||||
users: WaitingUsers): Fu[Pairings] = for {
|
||||
users: WaitingUsers): Fu[(Pairings, Option[Duration])] = for {
|
||||
recentPairings <- PairingRepo.recentByTourAndUserIds(tour.id, users.all, Math.min(120, users.size * 5))
|
||||
nbActiveUsers <- PlayerRepo.countActive(tour.id)
|
||||
ranking <- PlayerRepo.ranking(tour.id)
|
||||
data = Data(tour, recentPairings, ranking, nbActiveUsers)
|
||||
pairings <- {
|
||||
if (recentPairings.isEmpty) evenOrAll(data, users)
|
||||
if (recentPairings.isEmpty) evenOrAll(data, users).map(_ -> none)
|
||||
else tryPairings(data, users.waiting) flatMap {
|
||||
case Nil => fuccess(Nil)
|
||||
case _ => evenOrAll(data, users)
|
||||
case Nil => fuccess(Nil -> none)
|
||||
case _ => evenOrAll(data, users).map(_ -> none)
|
||||
}
|
||||
}
|
||||
} yield pairings
|
||||
|
|
Loading…
Reference in New Issue