Skip to content

Commit

Permalink
Merge pull request #5455 from ornicar/arena-stallers
Browse files Browse the repository at this point in the history
Automatically pause stallers in arenas
  • Loading branch information
ornicar committed Aug 24, 2019
2 parents 0535133 + 8dabb22 commit 579448c
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 8 deletions.
15 changes: 13 additions & 2 deletions modules/playban/src/main/PlaybanApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ final class PlaybanApi(
seconds = nowSeconds - game.movedAt.getSeconds
limit <- unreasonableTime
if seconds >= limit
} yield save(Outcome.Sitting, userId, roughWinEstimate(game, flaggerColor)) >>- feedback.sitting(Pov(game, flaggerColor))
} yield save(Outcome.Sitting, userId, roughWinEstimate(game, flaggerColor)) >>-
feedback.sitting(Pov(game, flaggerColor)) >>-
propagateSitting(game, userId)

// flagged after waiting a short time;
// but the previous move used a long time.
Expand All @@ -98,7 +100,9 @@ final class PlaybanApi(
lastMovetime <- movetimes.lastOption
limit <- unreasonableTime
if lastMovetime.toSeconds >= limit
} yield save(Outcome.SitMoving, userId, roughWinEstimate(game, flaggerColor)) >>- feedback.sitting(Pov(game, flaggerColor))
} yield save(Outcome.SitMoving, userId, roughWinEstimate(game, flaggerColor)) >>-
feedback.sitting(Pov(game, flaggerColor)) >>-
propagateSitting(game, userId)

sandbag(game, flaggerColor) flatMap { isSandbag =>
IfBlameable(game) {
Expand All @@ -109,6 +113,13 @@ final class PlaybanApi(
}
}

def propagateSitting(game: Game, userId: String) =
sitAndDcCounter(userId) map { counter =>
if (counter <= -5) {
bus.publish(SittingDetected(game, userId), 'playban)
}
}

def other(game: Game, status: Status.type => Status, winner: Option[Color]): Funit =
winner.?? { w => sandbag(game, !w) } flatMap { isSandbag =>
IfBlameable(game) {
Expand Down
4 changes: 4 additions & 0 deletions modules/playban/src/main/model.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package lila.playban
import org.joda.time.DateTime
import play.api.libs.json._

import lila.game.Game

case class UserRecord(
_id: String,
o: Option[List[Outcome]],
Expand Down Expand Up @@ -117,3 +119,5 @@ object Outcome {

def apply(id: Int): Option[Outcome] = byId get id
}

case class SittingDetected(game: Game, userId: String)
2 changes: 2 additions & 0 deletions modules/tournament/src/main/ApiActor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ private[tournament] final class ApiActor(

case FinishGame(game, _, _) => api finishGame game

case lila.playban.SittingDetected(game, player) => api.sittingDetected(game, player)

case lila.hub.actorApi.mod.MarkCheater(userId, true) =>
leaderboard.getAndDeleteRecent(userId, DateTime.now minusDays 3) foreach {
api.ejectLame(userId, _)
Expand Down
20 changes: 14 additions & 6 deletions modules/tournament/src/main/TournamentApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -247,21 +247,24 @@ final class TournamentApi(
TournamentRepo tourIdsToWithdrawWhenEntering tourId foreach {
PlayerRepo.filterExists(_, userId) foreach {
_ foreach {
withdraw(_, userId, isPause = false)
withdraw(_, userId, isPause = false, isStalling = false)
}
}
}

def selfPause(tourId: Tournament.ID, userId: User.ID): Unit =
withdraw(tourId, userId, isPause = true)
withdraw(tourId, userId, isPause = true, isStalling = false)

private def withdraw(tourId: Tournament.ID, userId: User.ID, isPause: Boolean): Unit = {
private def stallPause(tourId: Tournament.ID, userId: User.ID): Unit =
withdraw(tourId, userId, isPause = false, isStalling = true)

private def withdraw(tourId: Tournament.ID, userId: User.ID, isPause: Boolean, isStalling: Boolean): Unit = {
Sequencing(tourId)(TournamentRepo.enterableById) {
case tour if tour.isCreated =>
PlayerRepo.remove(tour.id, userId) >> updateNbPlayers(tour.id) >>- socketReload(tour.id) >>- publish()
case tour if tour.isStarted => for {
_ <- PlayerRepo.withdraw(tour.id, userId)
pausable <- isPause ?? cached.ranking(tour).map { _ get userId exists (7>) }
pausable <- if (isPause) cached.ranking(tour).map { _ get userId exists (7>) } else fuccess(isStalling)
} yield {
if (pausable) pause.add(userId, tour)
socketReload(tour.id)
Expand All @@ -275,7 +278,7 @@ final class TournamentApi(
TournamentRepo.nonEmptyEnterableIds foreach {
PlayerRepo.filterExists(_, user.id) foreach {
_ foreach {
withdraw(_, user.id, isPause = false)
withdraw(_, user.id, isPause = false, isStalling = false)
}
}
}
Expand Down Expand Up @@ -311,6 +314,11 @@ final class TournamentApi(
}
}

def sittingDetected(game: Game, player: User.ID): Unit =
game.tournamentId foreach { tourId =>
stallPause(tourId, player)
}

private def updatePlayer(
tour: Tournament,
finishing: Option[Game] // if set, update the player performance. Leave to none to just recompute the sheet.
Expand Down Expand Up @@ -349,7 +357,7 @@ final class TournamentApi(
if game.status == chess.Status.NoStart
player <- game.playerWhoDidNotMove
userId <- player.userId
} withdraw(tourId, userId, isPause = false)
} withdraw(tourId, userId, isPause = false, isStalling = false)

def pausePlaybanned(userId: User.ID) =
TournamentRepo.startedIds flatMap {
Expand Down

0 comments on commit 579448c

Please sign in to comment.