hide round meddler and finisher

This commit is contained in:
Thibault Duplessis 2013-05-17 23:13:51 -03:00
parent b05daadfd8
commit 3732394b41
14 changed files with 87 additions and 93 deletions

View file

@ -23,8 +23,7 @@ trait RoundEventPerformer {
Env.round.roundMap ?
Ask(takeGameId(fullId), makeMessage(takePlayerId(fullId))) mapTo
manifest[List[Event]] logFailure
"[round] fail to perform on game %s".format(fullId) addEffect
{ sendEvents(fullId) _ }
"[round] fail to perform on game %s".format(fullId)
protected def sendEvents(gameId: String)(events: List[Event]) {
Env.round.socketHub ! Forward(gameId, events)

View file

@ -22,12 +22,11 @@ final class ActorMap[A <: Actor](mkActor: String ⇒ A) extends Actor {
}
}
case Count sender ! actors.size
case Count sender ! actors.size
case Do(id, f) self ? Get(id) mapTo manifest[ActorRef] foreach f
case Ask(id, msg) get(id) flatMap { _ ? msg } pipeTo sender
case Ask(id, msg)
self ? Get(id) mapTo manifest[ActorRef] flatMap { _ ? msg } pipeTo sender
case Tell(id, msg) get(id) foreach { _ forward msg }
case Stop(id) "stop actor " + id describes {
actors get id foreach context.stop
@ -40,5 +39,7 @@ final class ActorMap[A <: Actor](mkActor: String ⇒ A) extends Actor {
}
}
private def get(id: String): Fu[ActorRef] = self ? Get(id) mapTo manifest[ActorRef]
private var actors = Map[String, ActorRef]()
}

View file

@ -24,8 +24,8 @@ case class NbMembers(nb: Int)
package map {
case class Get(id: String)
case class Do(id: String, f: akka.actor.ActorRef Unit)
case class Ask(id: String, msg: Any)
case class Tell(id: String, msg: Any)
case object Count
case class Stop(id: String)
}

View file

@ -7,14 +7,13 @@ import com.typesafe.config.Config
final class Env(
config: Config,
roundMap: akka.actor.ActorRef,
finisher: lila.round.Finisher,
bookmark: lila.hub.ActorLazyRef) {
private val Delay = config duration "delay"
lazy val forms = new DataForm
lazy val importer = new Importer(roundMap, finisher, bookmark, Delay)
lazy val importer = new Importer(roundMap, bookmark, Delay)
}
object Env {
@ -22,6 +21,5 @@ object Env {
lazy val current = "[boot] importer" describes new Env(
config = lila.common.PlayApp loadConfig "importer",
roundMap = lila.round.Env.current.roundMap,
finisher = lila.round.Env.current.finisher,
bookmark = lila.hub.Env.current.actor.bookmark)
}

View file

@ -2,7 +2,6 @@ package lila.importer
import chess.{ Color, Move, Status }
import lila.game.{ Game, GameRepo, Pov }
import lila.round.Finisher
import lila.round.actorApi.round._
import lila.hub.actorApi.map._
import lila.game.tube.gameTube
@ -15,22 +14,16 @@ import scala.concurrent.duration.Duration
private[importer] final class Importer(
roundMap: ActorRef,
finisher: Finisher,
bookmark: lila.hub.ActorLazyRef,
delay: Duration) {
def apply(data: ImportData, user: Option[String]): Fu[Game] = gameExists(data.pgn) {
(data preprocess user).fold[Fu[Game]](fufail(_), {
case Preprocessed(game, moves, result) for {
_ (GameRepo insertDenormalized game) >> applyMoves(Pov(game, Color.white), moves)
dbGame $find.byId[Game](game.id)
_ ~((dbGame |@| result) apply {
case (dbg, res) finish(dbg, res)
}) >>- ~((dbGame |@| user) apply {
case (dbg, u) bookmark ! (dbg.id -> u)
})
} yield game
})
(data preprocess user).future flatMap {
case Preprocessed(game, moves, result)
(GameRepo insertDenormalized game) >>-
applyMoves(Pov(game, Color.white), moves) >>-
(result foreach { r applyResult(game, r) }) inject game
}
}
private def gameExists(pgn: String)(processing: Fu[Game]): Fu[Game] =
@ -38,26 +31,31 @@ private[importer] final class Importer(
_.fold(processing)(game fuccess(game))
}
private def finish(game: Game, result: Result): Funit = (result match {
case Result(Status.Draw, _) finisher drawForce game
case Result(Status.Resign, Some(color)) roundMap ? Ask(
game.id,
Resign(game.player(!color).id)
)
case _ funit
}).void
private def applyMoves(pov: Pov, moves: List[Move]): Funit = moves match {
case Nil funit
case move :: rest applyMove(pov, move) >>-
(Thread sleep delay.toMillis) >>
applyMoves(!pov, rest)
private def applyResult(game: Game, result: Result) {
result match {
case Result(Status.Draw, _) roundMap ! Tell(game.id, DrawForce)
case Result(Status.Resign, Some(color)) roundMap ! Tell(game.id, Resign(game.player(!color).id))
case _
}
}
private def applyMove(pov: Pov, move: Move) = roundMap ? Ask(pov.gameId, Play(
playerId = pov.playerId,
orig = move.orig.toString,
dest = move.dest.toString,
prom = move.promotion map (_.forsyth.toString)
)) logFailure ("[importer] apply move")
private def applyMoves(pov: Pov, moves: List[Move]) {
moves match {
case move :: rest {
applyMove(pov, move)
Thread sleep delay.toMillis
applyMoves(!pov, rest)
}
case Nil
}
}
private def applyMove(pov: Pov, move: Move) {
roundMap ! Tell(pov.gameId, Play(
playerId = pov.playerId,
orig = move.orig.toString,
dest = move.dest.toString,
prom = move.promotion map (_.forsyth.toString)
))
}
}

View file

@ -66,8 +66,7 @@ final class Env(
flood = flood,
hijack = hijack)
// TODO make private
lazy val finisher = new Finisher(
private lazy val finisher = new Finisher(
messenger = messenger,
eloUpdater = eloUpdater,
eloCalculator = eloCalculator,
@ -75,7 +74,7 @@ final class Env(
tournamentOrganizer = hub.actor.tournamentOrganizer)
lazy val meddler = new Meddler(
finisher = finisher,
roundMap = roundMap,
socketHub = socketHub)
lazy val messenger = new Messenger(NetDomain, i18nKeys, getUsername)
@ -100,7 +99,7 @@ final class Env(
}
}
private lazy val titivate = new Titivate(finisher, meddler)
private lazy val titivate = new Titivate(roundMap, meddler)
private lazy val hijack = new Hijack(HijackTimeout)

View file

@ -1,45 +1,27 @@
package lila.round
import actorApi._
import actorApi._, round._
import lila.game.{ Game, GameRepo, PovRef, Pov }
import lila.game.tube.gameTube
import lila.socket.actorApi.Forward
import lila.hub.actorApi.map.Tell
import lila.db.api._
import akka.actor.ActorRef
import akka.pattern.{ ask, pipe }
private[round] final class Meddler(finisher: Finisher, socketHub: ActorRef) {
private[round] final class Meddler(roundMap: ActorRef, socketHub: ActorRef) {
def forceAbort(id: String) {
$find.byId(id) foreach {
_.fold(logwarn("Cannot abort missing game " + id)) { game
finisher forceAbort game effectFold (
e logwarn(e.getMessage),
events socketHub ! Forward(game.id, events)
)
}
}
def forceAbort(gameId: String) {
roundMap ! Tell(gameId, AbortForce)
}
def resign(pov: Pov) {
finisher resign pov effectFold (
e logwarn(e.getMessage),
events socketHub ! Forward(pov.game.id, events)
)
}
def resign(povRef: PovRef) {
GameRepo pov povRef foreach {
_.fold(logwarn("Cannot resign missing game " + povRef))(resign)
}
roundMap ! Tell(pov.gameId, Resign(pov.playerId))
}
def finishAbandoned(game: Game) {
game.abandoned.fold(
finisher.resign(Pov(game, game.player)) onFailure {
case e logwarn("Finish abandoned game %s : ".format(game.id, e.getMessage))
},
logwarn("Game is not abandoned")
)
game.abandoned ?? {
roundMap ! Tell(game.id, Resign(game.player.id))
}
}
}

View file

@ -83,6 +83,10 @@ private[round] final class Round(
pov.game.resignable ?? finisher(pov.game, _.Resign, Some(!pov.color))
}
case ResignColor(color) sender ! blocking(color) { pov
pov.game.resignable ?? finisher(pov.game, _.Resign, Some(!pov.color))
}
case ResignForce(playerId) sender ! blocking(playerId) { pov
(pov.game.resignable && !pov.game.hasAi) ?? {
socketHub ? IsGone(pov.game.id, !pov.color) flatMap {

View file

@ -2,9 +2,12 @@ package lila.round
import lila.game.{ Query, Game, GameRepo }
import lila.game.tube.gameTube
import lila.hub.actorApi.map.Tell
import lila.round.actorApi.round.Outoftime
import lila.db.api._
import lila.common.PimpedJson._
import akka.actor.ActorRef
import org.joda.time.DateTime
import org.scala_tools.time.Imports._
import play.api.libs.json._
@ -12,18 +15,18 @@ import play.api.libs.iteratee._
import play.modules.reactivemongo.json.ImplicitBSONHandlers._
private[round] final class Titivate(
finisher: Finisher,
meddler: Meddler) {
roundMap: ActorRef,
meddler: Meddler) {
def finishByClock: Funit =
$enumerate.bulk[Option[Game]]($query(Query.candidatesToAutofinish), 50) { games
fuloginfo("[titivate] Finish %d games by clock" format games.flatten.size) >>
(finisher outoftimes games.flatten)
fuloginfo("[titivate] Finish %d games by clock" format games.flatten.size) >>-
(games.flatten foreach { game roundMap ! Tell(game.id, Outoftime) })
}
def finishAbandoned: Funit =
$enumerate.bulk[Option[Game]]($query(Query.abandoned), 50) { games
fuloginfo("[titivate] Finish %d abandoned games" format games.flatten.size) >>
fuccess(games.flatten foreach meddler.finishAbandoned)
fuloginfo("[titivate] Finish %d abandoned games" format games.flatten.size) >>-
(games.flatten foreach meddler.finishAbandoned)
}
}

View file

@ -79,6 +79,7 @@ package round {
case class Abort(playerId: String)
case object AbortForce
case class Resign(playerId: String)
case class ResignColor(color: Color)
case class ResignForce(playerId: String)
case class DrawClaim(playerId: String)
case class DrawAccept(playerId: String)

View file

@ -16,7 +16,7 @@ final class Env(
timelinePush: lila.hub.ActorLazyRef,
flood: lila.security.Flood,
hub: lila.hub.Env,
roundMeddler: lila.round.Meddler,
roundMap: ActorRef,
getUsername: String Fu[Option[String]],
isDev: Boolean,
scheduler: lila.common.Scheduler) {
@ -43,7 +43,7 @@ final class Env(
socketHub = socketHub,
site = hub.socket.site,
lobby = hub.socket.lobby,
roundMeddler = roundMeddler)
roundMap = roundMap)
lazy val socketHandler = new SocketHandler(
socketHub = socketHub,
@ -81,7 +81,7 @@ final class Env(
}
private lazy val joiner = new GameJoiner(
roundMeddler = roundMeddler,
roundMap = roundMap,
timelinePush = timelinePush,
system = system)
@ -114,7 +114,7 @@ object Env {
timelinePush = hub.actor.timeline,
flood = lila.security.Env.current.flood,
hub = lila.hub.Env.current,
roundMeddler = lila.round.Env.current.meddler,
roundMap = lila.round.Env.current.roundMap,
getUsername = lila.user.Env.current.usernameOption,
isDev = lila.common.PlayApp.isDev,
scheduler = lila.common.PlayApp.scheduler)

View file

@ -3,13 +3,14 @@ package lila.tournament
import chess.Color
import lila.game.{ Game, Player GamePlayer, GameRepo, Pov, PovRef, Source }
import lila.user.{ User, UserRepo }
import lila.round.Meddler
import lila.hub.actorApi.map.Tell
import lila.round.actorApi.round.ResignColor
import scala.concurrent.duration._
import akka.actor.{ ActorRef, ActorSystem }
final class GameJoiner(
roundMeddler: Meddler,
roundMap: ActorRef,
timelinePush: lila.hub.ActorLazyRef,
system: ActorSystem) {
@ -58,7 +59,8 @@ final class GameJoiner(
lmt - nowSeconds + secondsToMove
})
},
roundMeddler resign pov)
roundMap ! Tell(pov.gameId, ResignColor(pov.color))
)
}
}
}

View file

@ -9,6 +9,8 @@ import lila.game.{ Game, GameRepo }
import lila.user.{ User, UserRepo }
import lila.hub.actorApi.lobby.{ SysTalk, UnTalk, ReloadTournaments }
import lila.hub.actorApi.router.Tourney
import lila.hub.actorApi.map.{ Ask, Tell }
import lila.round.actorApi.round.{ AbortForce, ResignColor }
import lila.socket.actorApi.{ SendToFlag, Forward }
import makeTimeout.short
@ -26,7 +28,7 @@ private[tournament] final class TournamentApi(
socketHub: ActorRef,
site: lila.hub.ActorLazyRef,
lobby: lila.hub.ActorLazyRef,
roundMeddler: lila.round.Meddler) extends scalaz.OptionTs {
roundMap: ActorRef) extends scalaz.OptionTs {
def makePairings(tour: Started, pairings: NonEmptyList[Pairing]): Funit =
(tour addPairings pairings) |> { tour2
@ -80,8 +82,10 @@ private[tournament] final class TournamentApi(
val finished = started.finish
$update(finished) >>-
sendTo(started.id, ReloadPage) >>-
reloadSiteSocket >>-
(pairingsToAbort map (_.gameId) foreach roundMeddler.forceAbort) >>
reloadSiteSocket >>
(pairingsToAbort map (_.gameId) map { gameId
roundMap ? Ask(gameId, AbortForce) void
}).sequence >>
finished.players.filter(_.score > 0).map(p UserRepo.incToints(p.id)(p.score)).sequence inject finished
}, fuccess(started))
@ -103,8 +107,10 @@ private[tournament] final class TournamentApi(
)
case started: Started (started withdraw userId).fold(
err fufail(err.shows),
tour2 $update(tour2) >>-
(tour2 userCurrentPov userId foreach roundMeddler.resign) >>-
tour2 $update(tour2) >>
(tour2.userCurrentPov(userId) ?? { povRef
roundMap ? Ask(povRef.gameId, ResignColor(povRef.color)) void
}) >>-
socketReload(tour2.id) >>-
reloadSiteSocket
)

1
todo
View file

@ -83,6 +83,7 @@ from MoralIntentions email:
- Several options of how points should be given to players (for example: Score * Sonneborn-Berger * Tournament Performance Rating * Percentage Score [for example: 0.64] / 1000) and therefore also several Leaderboards.
- The possibility of team matches (with solutions for players who are in several teams), where the team leader has to choose the board order, where the team results are shown and where the team player (who has played all of the games of the match) with the highest Percentage Score gets crowned Player of the Match of team "A".
safari has high bounce rate
tell, instead of asking, the round actor. it may send the events to the socket
DEPLOY p21
----------