archive seeks and restore seeks of aborted correspondence games

pull/437/head
Thibault Duplessis 2015-04-21 18:32:11 +02:00
parent e26a8381c0
commit 610737d2a2
10 changed files with 65 additions and 7 deletions

View File

@ -10,10 +10,11 @@ case class StartGame(game: Game)
case class UserStartGame(userId: String, game: Game)
case class FinishGame(game: Game, white: Option[User], black: Option[User]) {
def isVsSelf = white.isDefined && white == black
}
case class InsertGame(game: Game)
case class AbortedBy(pov: Pov)
private[game] case object NewCaptcha

View File

@ -169,6 +169,7 @@ case class MoveEvent(
opponentUserId: Option[String],
simulId: Option[String])
case class NbRounds(nb: Int)
case class Abort(gameId: String, byColor: String)
}
package evaluation {

View File

@ -0,0 +1,16 @@
package lila.lobby
import org.joda.time.DateTime
import lila.game.Pov
private[lobby] final class AbortListener(seekApi: SeekApi) {
def recreateSeek(pov: Pov): Funit = pov.player.userId ?? { aborterId =>
seekApi.findArchived(pov.game.id) flatMap {
_ ?? { seek =>
(seek.user.id != aborterId) ?? seekApi.insert(Seek renew seek)
}
}
}
}

View File

@ -25,6 +25,7 @@ final class Env(
val BroomPeriod = config duration "broom_period"
val ResyncIdsPeriod = config duration "resync_ids_period"
val CollectionSeek = config getString "collection.seek"
val CollectionSeekArchive = config getString "collection.seek_archive"
val SeekMaxPerPage = config getInt "seek.max_per_page"
val SeekMaxPerUser = config getInt "seek.max_per_user"
}
@ -38,6 +39,7 @@ final class Env(
lazy val seekApi = new SeekApi(
coll = db(CollectionSeek),
archiveColl = db(CollectionSeekArchive),
blocking = blocking,
maxPerPage = SeekMaxPerPage,
maxPerUser = SeekMaxPerUser)
@ -57,6 +59,16 @@ final class Env(
lazy val history = new History[actorApi.Messadata](ttl = MessageTtl)
private val abortListener = new AbortListener(seekApi = seekApi)
system.actorOf(Props(new Actor {
system.lilaBus.subscribe(self, 'abortGame)
def receive = {
case lila.game.actorApi.AbortedBy(pov) if pov.game.isCorrespondence =>
abortListener recreateSeek pov
}
}))
{
import scala.concurrent.duration._

View File

@ -80,7 +80,7 @@ private[lobby] final class Lobby(
case msg@JoinSeek(_, seek, game, _) =>
onStart(game.id)
socket ! msg
(seekApi remove seek) >>- {
seekApi.archive(seek, game.id) >>- {
socket ! RemoveSeek(seek.id)
}

View File

@ -31,7 +31,7 @@ case class Seek(
def compatibleWith(h: Seek) =
user.id != h.user.id &&
compatibilityProperties == h.compatibilityProperties &&
compatibilityProperties == h.compatibilityProperties &&
(realColor compatibleWith h.realColor) &&
ratingRangeCompatibleWith(h) && h.ratingRangeCompatibleWith(this)
@ -85,6 +85,16 @@ object Seek {
ratingRange = ratingRange.toString,
createdAt = DateTime.now)
def renew(seek: Seek) = new Seek(
_id = Random nextStringUppercase idSize,
variant = seek.variant,
daysPerTurn = seek.daysPerTurn,
mode = seek.mode,
color = seek.color,
user = seek.user,
ratingRange = seek.ratingRange,
createdAt = DateTime.now)
import reactivemongo.bson.Macros
import lila.db.BSON.MapValue.MapHandler
import lila.db.BSON.BSONJodaDateTimeHandler

View File

@ -6,12 +6,14 @@ import reactivemongo.core.commands._
import scala.concurrent.duration._
import actorApi.LobbyUser
import lila.db.BSON.BSONJodaDateTimeHandler
import lila.db.Types.Coll
import lila.memo.AsyncCache
import lila.user.{ User, UserRepo }
final class SeekApi(
coll: Coll,
archiveColl: Coll,
blocking: String => Fu[Set[String]],
maxPerPage: Int,
maxPerUser: Int) {
@ -30,7 +32,7 @@ final class SeekApi(
case ForAnon => allCursor.collect[List](maxPerPage)
case ForUser => allCursor.collect[List]()
},
timeToLive = 5.seconds)
timeToLive = 3.seconds)
def forAnon = cache(ForAnon)
@ -62,6 +64,18 @@ final class SeekApi(
def remove(seek: Seek) =
coll.remove(BSONDocument("_id" -> seek.id)).void >> cache.clear
def archive(seek: Seek, gameId: String) = {
val archiveDoc = Seek.seekBSONHandler.write(seek) ++ BSONDocument(
"gameId" -> gameId,
"archivedAt" -> DateTime.now)
coll.remove(BSONDocument("_id" -> seek.id)).void >>
cache.clear >>
archiveColl.insert(archiveDoc)
}
def findArchived(gameId: String): Fu[Option[Seek]] =
archiveColl.find(BSONDocument("gameId" -> gameId)).one[Seek]
def removeBy(seekId: String, userId: String) =
coll.remove(BSONDocument(
"_id" -> seekId,

View File

@ -5,7 +5,7 @@ import chess.Status._
import chess.{ Status, Color, Speed }
import lila.db.api._
import lila.game.actorApi.FinishGame
import lila.game.actorApi.{ FinishGame, AbortedBy }
import lila.game.tube.gameTube
import lila.game.{ GameRepo, Game, Pov, Event }
import lila.i18n.I18nKey.{ Select => SelectI18nKey }
@ -21,6 +21,10 @@ private[round] final class Finisher(
timeline: akka.actor.ActorSelection,
casualOnly: Boolean) {
def abort(pov: Pov): Fu[Events] = apply(pov.game, _.Aborted) addEffect { _ =>
bus.publish(AbortedBy(pov), 'abortGame)
}
def apply(
game: Game,
status: Status.type => Status,

View File

@ -52,7 +52,7 @@ private[round] final class Round(
}
case Abort(playerId) => handle(playerId) { pov =>
pov.game.abortable ?? finisher(pov.game, _.Aborted)
pov.game.abortable ?? finisher.abort(pov)
}
case Resign(playerId) => handle(playerId) { pov =>

View File

@ -4,7 +4,7 @@ import akka.actor._
import com.typesafe.config.{ Config => AppConfig }
import lila.common.PimpedConfig._
import lila.game.{ Game, Progress }
import lila.game.{ Game, Pov, Progress }
import lila.user.UserContext
final class Env(