<commit_before>package lila.challenge

import org.joda.time.DateTime
import scala.concurrent.duration._

import lila.common.Bus
import lila.common.config.Max
import lila.game.{ Game, Pov }
import lila.hub.actorApi.socket.SendTo
import lila.memo.CacheApi._
import lila.user.{ User, UserRepo }
import lila.i18n.I18nLangPicker

final class ChallengeApi(
    repo: ChallengeRepo,
    challengeMaker: ChallengeMaker,
    userRepo: UserRepo,
    joiner: ChallengeJoiner,
    jsonView: JsonView,
    gameCache: lila.game.Cached,
    maxPlaying: Max,
    cacheApi: lila.memo.CacheApi
)(implicit
    ec: scala.concurrent.ExecutionContext,
    system: akka.actor.ActorSystem
) {

  import Challenge._

  def allFor(userId: User.ID): Fu[AllChallenges] =
    createdByDestId(userId) zip createdByChallengerId(userId) dmap (AllChallenges.apply _).tupled

  // returns boolean success
  def create(c: Challenge): Fu[Boolean] =
    isLimitedByMaxPlaying(c) flatMap {
      case true => fuFalse
      case false =>
        {
          repo like c flatMap { _ ?? repo.cancel }
        } >> (repo insert c) >>- {
          uncacheAndNotify(c)
          Bus.publish(Event.Create(c), "challenge")
        } inject true
    }

  def byId = repo byId _

  def activeByIdFor(id: Challenge.ID, dest: User) = repo.byIdFor(id, dest).dmap(_.filter(_.active))
  def activeByIdBy(id: Challenge.ID, orig: User)  = repo.byIdBy(id, orig).dmap(_.filter(_.active))

  def onlineByIdFor(id: Challenge.ID, dest: User) = repo.byIdFor(id, dest).dmap(_.filter(_.online))

  val countInFor = cacheApi[User.ID, Int](65536, "challenge.countInFor") {
    _.expireAfterAccess(20 minutes)
      .buildAsyncFuture(repo.countCreatedByDestId)
  }

  def createdByChallengerId = repo createdByChallengerId _

  def createdByDestId = repo createdByDestId _

  def cancel(c: Challenge) =
    repo.cancel(c) >>- {
      uncacheAndNotify(c)
      Bus.publish(Event.Cancel(c), "challenge")
    }

  private def offline(c: Challenge) = (repo offline c) >>- uncacheAndNotify(c)

  private[challenge] def ping(id: Challenge.ID): Funit =
    repo statusById id flatMap {
      case Some(Status.Created) => repo setSeen id
      case Some(Status.Offline) => (repo setSeenAgain id) >> byId(id).map { _ foreach uncacheAndNotify }
      case _                    => fuccess(socketReload(id))
    }

  def decline(c: Challenge, reason: Challenge.DeclineReason) =
    repo.decline(c, reason) >>- {
      uncacheAndNotify(c)
      Bus.publish(Event.Decline(c declineWith reason), "challenge")
    }

  private val acceptQueue = new lila.hub.DuctSequencer(maxSize = 64, timeout = 5 seconds, "challengeAccept")

  def accept(
      c: Challenge,
      user: Option[User],
      sid: Option[String],
      color: Option[chess.Color] = None
  ): Fu[Option[Pov]] =
    acceptQueue {
      if (c.challengerIsOpen)
        repo.setChallenger(c.setChallenger(user, sid), color) inject none
      else<commit_msg>bots can't accept ultrabullet challenges<commit_after>package lila.challenge

import org.joda.time.DateTime
import scala.concurrent.duration._

import lila.common.Bus
import lila.common.config.Max
import lila.game.{ Game, Pov }
import lila.hub.actorApi.socket.SendTo
import lila.memo.CacheApi._
import lila.user.{ User, UserRepo }
import lila.i18n.I18nLangPicker

final class ChallengeApi(
    repo: ChallengeRepo,
    challengeMaker: ChallengeMaker,
    userRepo: UserRepo,
    joiner: ChallengeJoiner,
    jsonView: JsonView,
    gameCache: lila.game.Cached,
    maxPlaying: Max,
    cacheApi: lila.memo.CacheApi
)(implicit
    ec: scala.concurrent.ExecutionContext,
    system: akka.actor.ActorSystem
) {

  import Challenge._

  def allFor(userId: User.ID): Fu[AllChallenges] =
    createdByDestId(userId) zip createdByChallengerId(userId) dmap (AllChallenges.apply _).tupled

  // returns boolean success
  def create(c: Challenge): Fu[Boolean] =
    isLimitedByMaxPlaying(c) flatMap {
      case true => fuFalse
      case false =>
        {
          repo like c flatMap { _ ?? repo.cancel }
        } >> (repo insert c) >>- {
          uncacheAndNotify(c)
          Bus.publish(Event.Create(c), "challenge")
        } inject true
    }

  def byId = repo byId _

  def activeByIdFor(id: Challenge.ID, dest: User) = repo.byIdFor(id, dest).dmap(_.filter(_.active))
  def activeByIdBy(id: Challenge.ID, orig: User)  = repo.byIdBy(id, orig).dmap(_.filter(_.active))

  def onlineByIdFor(id: Challenge.ID, dest: User) = repo.byIdFor(id, dest).dmap(_.filter(_.online))

  val countInFor = cacheApi[User.ID, Int](65536, "challenge.countInFor") {
    _.expireAfterAccess(20 minutes)
      .buildAsyncFuture(repo.countCreatedByDestId)
  }

  def createdByChallengerId = repo createdByChallengerId _

  def createdByDestId = repo createdByDestId _

  def cancel(c: Challenge) =
    repo.cancel(c) >>- {
      uncacheAndNotify(c)
      Bus.publish(Event.Cancel(c), "challenge")
    }

  private def offline(c: Challenge) = (repo offline c) >>- uncacheAndNotify(c)

  private[challenge] def ping(id: Challenge.ID): Funit =
    repo statusById id flatMap {
      case Some(Status.Created) => repo setSeen id
      case Some(Status.Offline) => (repo setSeenAgain id) >> byId(id).map { _ foreach uncacheAndNotify }
      case _                    => fuccess(socketReload(id))
    }

  def decline(c: Challenge, reason: Challenge.DeclineReason) =
    repo.decline(c, reason) >>- {
      uncacheAndNotify(c)
      Bus.publish(Event.Decline(c declineWith reason), "challenge")
    }

  private val acceptQueue = new lila.hub.DuctSequencer(maxSize = 64, timeout = 5 seconds, "challengeAccept")

  def accept(
      c: Challenge,
      user: Option[User],
      sid: Option[String],
      color: Option[chess.Color] = None
  ): Fu[Option[Pov]] =
    acceptQueue {
      if (user.exists(_.isBot) && !Game.isBotCompatible(chess.Speed(c.clock.map(_.config))))
        fuccess(none)
      else if (c.challengerIsOpen)
        repo.setChallenger(c.setChallenger(user, sid), color) inject none
      else
{'fraction_non_alphanumeric': 0.1183402489626556, 'fraction_numerical': 0.004647302904564316, 'mean_word_length': 3.385735080058224, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1681794', 'n_tokens_mistral': 2066, 'n_tokens_neox': 1985, 'n_words': 428}