<commit_before>package lila.round

import scala.concurrent.duration._
import scala.math

import play.api.libs.json._

import lila.common.PimpedJson._
import lila.game.{ Pov, Game, PerfPicker, Source, GameRepo, CorrespondenceClock }
import lila.pref.Pref
import lila.user.{ User, UserRepo }

import chess.format.Forsyth
import chess.{ Color, Clock }

import actorApi.SocketStatus

final class JsonView(
    chatApi: lila.chat.ChatApi,
    noteApi: NoteApi,
    userJsonView: lila.user.JsonView,
    getSocketStatus: String => Fu[SocketStatus],
    canTakeback: Game => Fu[Boolean],
    baseAnimationDuration: Duration,
    moretimeSeconds: Int) {

  import JsonView._

  private def checkCount(game: Game, color: Color) =
    (game.variant == chess.variant.ThreeCheck) option game.checkCount(color)

  def playerJson(
    pov: Pov,
    pref: Pref,
    apiVersion: Int,
    playerUser: Option[User],
    initialFen: Option[String],
    withBlurs: Boolean): Fu[JsObject] =
    getSocketStatus(pov.game.id) zip
      (pov.opponent.userId ?? UserRepo.byId) zip
      canTakeback(pov.game) zip
      getPlayerChat(pov.game, playerUser) map {
        case (((socket, opponentUser), takebackable), chat) =>
          import pov._
          Json.obj(
            "game" -> gameJson(game, initialFen),
            "clock" -> game.clock.map(clockJson),
            "correspondence" -> game.correspondenceClock,
            "player" -> Json.obj(
              "id" -> playerId,
              "color" -> player.color.name,
              "version" -> socket.version,
              "spectator" -> false,
              "user" -> playerUser.map { userJsonView(_, true) },
              "rating" -> player.rating,
              "ratingDiff" -> player.ratingDiff,
              "provisional" -> player.provisional.option(true),
              "offeringRematch" -> player.isOfferingRematch.option(true),
              "offeringDraw" -> player.isOfferingDraw.option(true),
              "proposingTakeback" -> player.isProposingTakeback.option(true),
              "onGame" -> (player.isAi || socket.onGame(player.color)),
              "checks" -> checkCount(game, player.color),
              "hold" -> (withBlurs option hold(player)),
              "blurs" -> (withBlurs option blurs(game, player))
            ).noNull,
            "opponent" -> Json.obj(
              "color" -> opponent.color.name,
              "ai" -> opponent.aiLevel,
              "user" -> opponentUser.map { userJsonView(_, true) },
              "rating" -> opponent.rating,
              "ratingDiff" -> opponent.ratingDiff,
              "provisional" -> opponent.provisional.option(true),
              "offeringRematch" -> opponent.isOfferingRematch.option(true),
              "offeringDraw" -> opponent.isOfferingDraw.option(true),
              "proposingTakeback" -> opponent.isProposingTakeback.option(true),
              "onGame" -> (opponent.isAi || socket.onGame(opponent.color)),
              "isGone" -> (!opponent.isAi && socket.isGone(opponent.color)),
              "checks" -> checkCount(game, opponent.color),
              "hold" -> (withBlurs option hold(opponent)),
              "blurs" -> (withBlurs option blurs(game, opponent))
            ).noNull,
            "url" -> Json.obj(
              "socket" -> s"/$fullId/socket/v$apiVersion",
              "round" -> s"/$fullId"
            ),
            "pref" -> Json.obj(
              "blindfold" -> pref.isBlindfold,
              "animationDuration" -> animationDuration(pov, pref),
              "highlight" -> (pref.highlight || pref.isBlindfold),
              "destination" -> (pref.destination && !pref.isBlindfold),
              "coords" -> pref.coords,
              "replay" -> pref.replay,
              "autoQueen" -> (pov.game.variant == chess.variant.Antichess).fold(Pref.AutoQueen.NEVER, pref.autoQueen),
              "clockTenths" -> pref.clockTenths,
              "clockBar" -> pref.clockBar,
              "clockSound" -> pref.clockSound,
              "enablePremove" -> pref.premove,
              "showCaptured" -> pref.captured,
              "submitMove" -> (
                pref.submitMove == Pref.SubmitMove.ALWAYS || {
                  pref.submitMove == Pref.SubmitMove.CORRESPONDENCE &&
                    game.isCorrespondence && game.nonAi
                })
            ),
            "chat" -> chat.map { c =>
              JsArray(c.lines map {
                case lila.chat.UserLine(username, text, _) => Json.obj(
                  "u" -> username,
                  "t" -> text)
                case lila.chat.PlayerLine(color, text) => Json.obj(
                  "c" -> color.name,
                  "t" -> text)
              })
            },
            "possibleMoves" -> possibleMoves(pov),
            "takebackable" -> takebackable).noNull
      }

  def watcherJson(
    pov: Pov,
    pref: Pref,
    apiVersion: Int,
    user: Option[User],
    tv: Option[OnTv],
    withBlurs: Boolean,
    initialFen: Option[String] = None,
    withMoveTimes: Boolean) =
    getSocketStatus(pov.game.id) zip
      getWatcherChat(pov.game, user) zip
      UserRepo.pair(pov.player.userId, pov.opponent.userId) map {
        case ((socket, chat), (playerUser, opponentUser)) =>
          import pov._
          Json.obj(
            "game" -> {
              gameJson(game, initialFen) ++ Json.obj(
                "moveTimes" -> withMoveTimes.option(game.moveTimes),
                "opening" -> game.opening,
                "joinable" -> game.joinable,
                "importedBy" -> game.pgnImport.flatMap(_.user)).noNull
            },
            "clock" -> game.clock.map(clockJson),
            "correspondence" -> game.correspondenceClock,
            "player" -> Json.obj(
              "color" -> color.name,
              "version" -> socket.version,
              "spectator" -> true,
              "ai" -> player.aiLevel,
              "user" -> playerUser.map { userJsonView(_, true) },
              "name" -> player.name,
              "rating" -> player.rating,
              "ratingDiff" -> player.ratingDiff,
              "provisional" -> player.provisional.option(true),
              "onGame" -> (player.isAi || socket.onGame(player.color)),
              "checks" -> checkCount(game, player.color),
              "berserk" -> player.bersek.option(true),
              "hold" -> (withBlurs option hold(player)),
              "blurs" -> (withBlurs option blurs(game, player))
            ).noNull,
            "opponent" -> Json.obj(
              "color" -> opponent.color.name,
              "ai" -> opponent.aiLevel,
              "user" -> opponentUser.map { userJsonView(_, true) },
              "name" -> opponent.name,
              "rating" -> opponent.rating,
              "ratingDiff" -> opponent.ratingDiff,
              "provisional" -> opponent.provisional.option(true),
              "onGame" -> (opponent.isAi || socket.onGame(opponent.color)),
              "checks" -> checkCount(game, opponent.color),
              "berserk" -> player.bersek.option(true),
              "hold" -> (withBlurs option hold(opponent)),
              "blurs" -> (withBlurs option blurs(game, opponent))
            ).noNull,
            "orientation" -> pov.color.name,
            "url" -> Json.obj(
              "socket" -> s"/$gameId/${color.name}/socket",<commit_msg>what was I thinking<commit_after>package lila.round

import scala.concurrent.duration._
import scala.math

import play.api.libs.json._

import lila.common.PimpedJson._
import lila.game.{ Pov, Game, PerfPicker, Source, GameRepo, CorrespondenceClock }
import lila.pref.Pref
import lila.user.{ User, UserRepo }

import chess.format.Forsyth
import chess.{ Color, Clock }

import actorApi.SocketStatus

final class JsonView(
    chatApi: lila.chat.ChatApi,
    noteApi: NoteApi,
    userJsonView: lila.user.JsonView,
    getSocketStatus: String => Fu[SocketStatus],
    canTakeback: Game => Fu[Boolean],
    baseAnimationDuration: Duration,
    moretimeSeconds: Int) {

  import JsonView._

  private def checkCount(game: Game, color: Color) =
    (game.variant == chess.variant.ThreeCheck) option game.checkCount(color)

  def playerJson(
    pov: Pov,
    pref: Pref,
    apiVersion: Int,
    playerUser: Option[User],
    initialFen: Option[String],
    withBlurs: Boolean): Fu[JsObject] =
    getSocketStatus(pov.game.id) zip
      (pov.opponent.userId ?? UserRepo.byId) zip
      canTakeback(pov.game) zip
      getPlayerChat(pov.game, playerUser) map {
        case (((socket, opponentUser), takebackable), chat) =>
          import pov._
          Json.obj(
            "game" -> gameJson(game, initialFen),
            "clock" -> game.clock.map(clockJson),
            "correspondence" -> game.correspondenceClock,
            "player" -> Json.obj(
              "id" -> playerId,
              "color" -> player.color.name,
              "version" -> socket.version,
              "spectator" -> false,
              "user" -> playerUser.map { userJsonView(_, true) },
              "rating" -> player.rating,
              "ratingDiff" -> player.ratingDiff,
              "provisional" -> player.provisional.option(true),
              "offeringRematch" -> player.isOfferingRematch.option(true),
              "offeringDraw" -> player.isOfferingDraw.option(true),
              "proposingTakeback" -> player.isProposingTakeback.option(true),
              "onGame" -> (player.isAi || socket.onGame(player.color)),
              "checks" -> checkCount(game, player.color),
              "hold" -> (withBlurs option hold(player)),
              "blurs" -> (withBlurs option blurs(game, player))
            ).noNull,
            "opponent" -> Json.obj(
              "color" -> opponent.color.name,
              "ai" -> opponent.aiLevel,
              "user" -> opponentUser.map { userJsonView(_, true) },
              "rating" -> opponent.rating,
              "ratingDiff" -> opponent.ratingDiff,
              "provisional" -> opponent.provisional.option(true),
              "offeringRematch" -> opponent.isOfferingRematch.option(true),
              "offeringDraw" -> opponent.isOfferingDraw.option(true),
              "proposingTakeback" -> opponent.isProposingTakeback.option(true),
              "onGame" -> (opponent.isAi || socket.onGame(opponent.color)),
              "isGone" -> (!opponent.isAi && socket.isGone(opponent.color)),
              "checks" -> checkCount(game, opponent.color),
              "hold" -> (withBlurs option hold(opponent)),
              "blurs" -> (withBlurs option blurs(game, opponent))
            ).noNull,
            "url" -> Json.obj(
              "socket" -> s"/$fullId/socket/v$apiVersion",
              "round" -> s"/$fullId"
            ),
            "pref" -> Json.obj(
              "blindfold" -> pref.isBlindfold,
              "animationDuration" -> animationDuration(pov, pref),
              "highlight" -> (pref.highlight || pref.isBlindfold),
              "destination" -> (pref.destination && !pref.isBlindfold),
              "coords" -> pref.coords,
              "replay" -> pref.replay,
              "autoQueen" -> (pov.game.variant == chess.variant.Antichess).fold(Pref.AutoQueen.NEVER, pref.autoQueen),
              "clockTenths" -> pref.clockTenths,
              "clockBar" -> pref.clockBar,
              "clockSound" -> pref.clockSound,
              "enablePremove" -> pref.premove,
              "showCaptured" -> pref.captured,
              "submitMove" -> (
                pref.submitMove == Pref.SubmitMove.ALWAYS || {
                  pref.submitMove == Pref.SubmitMove.CORRESPONDENCE &&
                    game.isCorrespondence && game.nonAi
                })
            ),
            "chat" -> chat.map { c =>
              JsArray(c.lines map {
                case lila.chat.UserLine(username, text, _) => Json.obj(
                  "u" -> username,
                  "t" -> text)
                case lila.chat.PlayerLine(color, text) => Json.obj(
                  "c" -> color.name,
                  "t" -> text)
              })
            },
            "possibleMoves" -> possibleMoves(pov),
            "takebackable" -> takebackable).noNull
      }

  def watcherJson(
    pov: Pov,
    pref: Pref,
    apiVersion: Int,
    user: Option[User],
    tv: Option[OnTv],
    withBlurs: Boolean,
    initialFen: Option[String] = None,
    withMoveTimes: Boolean) =
    getSocketStatus(pov.game.id) zip
      getWatcherChat(pov.game, user) zip
      UserRepo.pair(pov.player.userId, pov.opponent.userId) map {
        case ((socket, chat), (playerUser, opponentUser)) =>
          import pov._
          Json.obj(
            "game" -> {
              gameJson(game, initialFen) ++ Json.obj(
                "moveTimes" -> withMoveTimes.option(game.moveTimes),
                "opening" -> game.opening,
                "joinable" -> game.joinable,
                "importedBy" -> game.pgnImport.flatMap(_.user)).noNull
            },
            "clock" -> game.clock.map(clockJson),
            "correspondence" -> game.correspondenceClock,
            "player" -> Json.obj(
              "color" -> color.name,
              "version" -> socket.version,
              "spectator" -> true,
              "ai" -> player.aiLevel,
              "user" -> playerUser.map { userJsonView(_, true) },
              "name" -> player.name,
              "rating" -> player.rating,
              "ratingDiff" -> player.ratingDiff,
              "provisional" -> player.provisional.option(true),
              "onGame" -> (player.isAi || socket.onGame(player.color)),
              "checks" -> checkCount(game, player.color),
              "berserk" -> player.berserk.option(true),
              "hold" -> (withBlurs option hold(player)),
              "blurs" -> (withBlurs option blurs(game, player))
            ).noNull,
            "opponent" -> Json.obj(
              "color" -> opponent.color.name,
              "ai" -> opponent.aiLevel,
              "user" -> opponentUser.map { userJsonView(_, true) },
              "name" -> opponent.name,
              "rating" -> opponent.rating,
              "ratingDiff" -> opponent.ratingDiff,
              "provisional" -> opponent.provisional.option(true),
              "onGame" -> (opponent.isAi || socket.onGame(opponent.color)),
              "checks" -> checkCount(game, opponent.color),
              "berserk" -> opponent.berserk.option(true),
              "hold" -> (withBlurs option hold(opponent)),
              "blurs" -> (withBlurs option blurs(game, opponent))
            ).noNull,
            "orientation" -> pov.color.name,
            "url" -> Json.obj(
              "socket" -> s"/$gameId/${color.name}/socket",
{'fraction_non_alphanumeric': 0.14012738853503184, 'fraction_numerical': 0.0, 'mean_word_length': 1.8295628834355828, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 209, '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': '3731227', 'n_tokens_mistral': 4356, 'n_tokens_neox': 4309, 'n_words': 778}