lila/modules/pool/src/main/PoolActor.scala

117 lines
3.0 KiB
Scala

package lila.pool
import scala.concurrent.duration._
import scala.util.Random
import akka.actor._
import akka.pattern.pipe
import org.joda.time.DateTime
import lila.user.User
private final class PoolActor(
config: PoolConfig,
hookThieve: HookThieve,
gameStarter: GameStarter) extends Actor {
import PoolActor._
var members = Vector[PoolMember]()
var nextWave: Cancellable = _
def scheduleWave =
nextWave = context.system.scheduler.scheduleOnce(
config.wave.every + Random.nextInt(1000).millis,
self, ScheduledWave)
scheduleWave
def receive = {
case Join(joiner) =>
members.find(joiner.is) match {
case None =>
members = members :+ PoolMember(joiner, config)
if (members.size >= config.wave.players.value) self ! FullWave
monitor.join.count(monId)()
case Some(member) if member.ratingRange != joiner.ratingRange =>
members = members.map {
case m if m == member => m withRange joiner.ratingRange
case m => m
}
case _ => // no change
}
case Leave(userId) => members.find(_.userId == userId) foreach { member =>
members = members.filter(member !=)
monitor.leave.count(monId)()
monitor.leave.wait(monId)(member.waitMillis)
}
case ScheduledWave =>
monitor.wave.scheduled(monId)()
self ! RunWave
case FullWave =>
monitor.wave.full(monId)()
self ! RunWave
case RunWave =>
nextWave.cancel()
hookThieve.candidates(config.clock, monId) pipeTo self
case HookThieve.PoolHooks(hooks) => {
monitor.wave.withRange(monId)(members.count(_.hasRange))
val pairings = lila.mon.measure(_.lobby.pool.matchMaking.duration(monId)) {
MatchMaking(members ++ hooks.map(_.member))
}
val pairedMembers = pairings.flatMap(_.members)
hookThieve.stolen(hooks.filter { h =>
pairedMembers.exists(h.is)
}, monId)
members = members.diff(pairedMembers).map(_.incMisses)
if (pairings.nonEmpty)
gameStarter(config, pairings).mon(_.lobby.pool.gameStart.duration(monId))
logger.debug(s"${config.id.value} wave: ${pairings.size} pairings, ${members.size} missed")
monitor.wave.paired(monId)(pairedMembers.size)
monitor.wave.missed(monId)(members.size)
pairedMembers.foreach { m =>
monitor.wave.wait(monId)(m.waitMillis)
}
pairings.foreach { p =>
monitor.wave.ratingDiff(monId)(p.ratingDiff)
}
scheduleWave
}
case SocketIds(ids) =>
members = members.filter { m =>
ids contains m.socketId.value
}
}
val monitor = lila.mon.lobby.pool
val monId = config.id.value.replace("+", "_")
}
private object PoolActor {
case class Join(joiner: PoolApi.Joiner) extends AnyVal
case class Leave(userId: User.ID) extends AnyVal
case class SocketIds(ids: Set[String])
case object ScheduledWave
case object FullWave
case object RunWave
}