<commit_before>package lila.round

import chess.format.Forsyth
import chess.Pos.posAt
import chess.{ Status, Role, Color }

import actorApi.round.{ HumanPlay, AiPlay, DrawNo, TakebackNo, PlayResult, Cheat }
import lila.ai.Ai
import lila.game.{ Game, GameRepo, PgnRepo, Pov, Progress, UciMemo }
import lila.hub.actorApi.map.Tell
import lila.hub.actorApi.round.MoveEvent

private[round] final class Player(
    engine: Ai,
    notifyMove: MoveEvent ⇒ Unit,
    finisher: Finisher,
    cheatDetector: CheatDetector,
    roundMap: akka.actor.ActorSelection,
    uciMemo: UciMemo,
    aiIp: String) {

  def human(play: HumanPlay)(pov: Pov): Fu[Events] = play match {
    case HumanPlay(playerId, ip, origS, destS, promS, blur, lag, onFailure) ⇒ pov match {
      case Pov(game, color) if (game playableBy color) ⇒
        PgnRepo get game.id flatMap { pgnString ⇒
          (for {
            orig ← posAt(origS) toValid "Wrong orig " + origS
            dest ← posAt(destS) toValid "Wrong dest " + destS
            promotion = Role promotable promS
            chessGame = game.toChess withPgnMoves pgnString
            newChessGameAndMove ← chessGame(orig, dest, promotion, lag)
            (newChessGame, move) = newChessGameAndMove
          } yield game.update(newChessGame, move, blur) -> move).prefixFailuresWith(playerId + " - ").future flatMap {
            case ((progress, pgn), move) ⇒
              ((GameRepo save progress) zip PgnRepo.save(pov.gameId, pgn)) >>-
                (pov.game.hasAi ! uciMemo.add(pov.game, move)) >>-
                notifyProgress(progress, ip) >>
                progress.game.finished.fold(
                  moveFinish(progress.game, color) map { progress.events ::: _ }, {
                    cheatDetector(progress.game) addEffect {
                      case Some(color) ⇒ roundMap ! Tell(game.id, Cheat(color))
                      case None ⇒ {
                        if (progress.game.playableByAi) roundMap ! Tell(game.id, AiPlay)
                        if (game.player.isOfferingDraw) roundMap ! Tell(game.id, DrawNo(game.player.id))
                        if (game.player.isProposingTakeback) roundMap ! Tell(game.id, TakebackNo(game.player.id))
                      }
                    } inject progress.events
                  })
          }
        } addFailureEffect onFailure
      case Pov(game, _) if game.finished        ⇒ fufail(s"$pov game is finished")
      case Pov(game, _) if game.aborted         ⇒ fufail(s"$pov game is aborted")
      case Pov(_, color) if !game.turnOf(color) ⇒ fufail(s"$pov not your turn")
      case _                                    ⇒ fufail(s"$pov move refused for some reason")
    }
  }
<commit_msg>fix player error messages<commit_after>package lila.round

import chess.format.Forsyth
import chess.Pos.posAt
import chess.{ Status, Role, Color }

import actorApi.round.{ HumanPlay, AiPlay, DrawNo, TakebackNo, PlayResult, Cheat }
import lila.ai.Ai
import lila.game.{ Game, GameRepo, PgnRepo, Pov, Progress, UciMemo }
import lila.hub.actorApi.map.Tell
import lila.hub.actorApi.round.MoveEvent

private[round] final class Player(
    engine: Ai,
    notifyMove: MoveEvent ⇒ Unit,
    finisher: Finisher,
    cheatDetector: CheatDetector,
    roundMap: akka.actor.ActorSelection,
    uciMemo: UciMemo,
    aiIp: String) {

  def human(play: HumanPlay)(pov: Pov): Fu[Events] = play match {
    case HumanPlay(playerId, ip, origS, destS, promS, blur, lag, onFailure) ⇒ pov match {
      case Pov(game, color) if (game playableBy color) ⇒
        PgnRepo get game.id flatMap { pgnString ⇒
          (for {
            orig ← posAt(origS) toValid "Wrong orig " + origS
            dest ← posAt(destS) toValid "Wrong dest " + destS
            promotion = Role promotable promS
            chessGame = game.toChess withPgnMoves pgnString
            newChessGameAndMove ← chessGame(orig, dest, promotion, lag)
            (newChessGame, move) = newChessGameAndMove
          } yield game.update(newChessGame, move, blur) -> move).prefixFailuresWith(playerId + " - ").future flatMap {
            case ((progress, pgn), move) ⇒
              ((GameRepo save progress) zip PgnRepo.save(pov.gameId, pgn)) >>-
                (pov.game.hasAi ! uciMemo.add(pov.game, move)) >>-
                notifyProgress(progress, ip) >>
                progress.game.finished.fold(
                  moveFinish(progress.game, color) map { progress.events ::: _ }, {
                    cheatDetector(progress.game) addEffect {
                      case Some(color) ⇒ roundMap ! Tell(game.id, Cheat(color))
                      case None ⇒ {
                        if (progress.game.playableByAi) roundMap ! Tell(game.id, AiPlay)
                        if (game.player.isOfferingDraw) roundMap ! Tell(game.id, DrawNo(game.player.id))
                        if (game.player.isProposingTakeback) roundMap ! Tell(game.id, TakebackNo(game.player.id))
                      }
                    } inject progress.events
                  })
          }
        } addFailureEffect onFailure
      case Pov(game, _) if game.finished           ⇒ fufail(s"$pov game is finished")
      case Pov(game, _) if game.aborted            ⇒ fufail(s"$pov game is aborted")
      case Pov(game, color) if !game.turnOf(color) ⇒ fufail(s"$pov not your turn")
      case _                                       ⇒ fufail(s"$pov move refused for some reason")
    }
  }

{'fraction_non_alphanumeric': 0.10673536989326463, 'fraction_numerical': 0.0, 'mean_word_length': 2.1727962638645653, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6701208', 'n_tokens_mistral': 1739, 'n_tokens_neox': 1730, 'n_words': 427}