<commit_before>package lila.puzzle

import org.joda.time.DateTime

import lila.user.User

case class Round(
    id: Round.Id,
    date: DateTime,
    result: Result,
    rating: Int,
    ratingDiff: Int
) {

  def userPostRating = rating + ratingDiff
}

object Round {

  case class Id(userId: User.ID, puzzleId: PuzzleId)

  object BSONFields {
    val id = "_id"
    val date = "a"
    val magic = "m"
  }

  import reactivemongo.bson._
  import lila.db.BSON
  import lila.db.dsl._
  import BSON.BSONJodaDateTimeHandler

  private implicit val ResultBSONHandler = booleanAnyValHandler[Result](_.win, Result.apply)

  implicit val roundIdHandler: BSONHandler[BSONString, Id] = new BSONHandler[BSONString, Id] {
    private val sep = ':'
    /* We shift the puzzle ID by -60000
     * Because the initial puzzle is 60000 and something.
     * This way the lowest puzzle ID is 00000
     * and it allows us to sort rounds by ID: userId:puzzleId
     * because all puzzle IDs have the same length */
    private val shift = 60000
    def read(bs: BSONString) = bs.value split sep match {
      case Array(userId, puzzleId) => Id(userId, Integer.parseInt(puzzleId) + shift)
      case _ => sys error s"Invalid puzzle round id ${bs.value}"
    }
    def write(id: Id) = {
      val puzzleId = "%05d".format(id.puzzleId - shift)
      BSONString(s"${id.userId}$sep$puzzleId")
    }
  }

  implicit val RoundBSONHandler = new BSON[Round] {

    import BSONFields._

    /* `magic` field stores;
     * - win: boolean     | 1 bit
     * - ratingDiff: int  | 15 bits
     * - rating: int      | 16 bits
     */

    def reads(r: BSON.Reader): Round = {
      val m = r int magic
      val win = m >>> 31 != 0
      val ratingDiff = (m << 1) >>> 17
      Round(
        id = r.get[Id](id),
        date = r.get[DateTime](date),
        result = Result(win),
        rating = m & (-1 >>> 16),
        ratingDiff = if (win) ratingDiff else -ratingDiff
      )
    }

    def writes(w: BSON.Writer, o: Round) = BSONDocument(
      id -> o.id,
      date -> o.date,
      magic -> {
        (o.result.win ?? 1 << 31) |
          (Math.abs(o.ratingDiff) << 16) |
          o.rating
      }
    )
  }
}<commit_msg>Update Round.scala<commit_after>package lila.puzzle

import org.joda.time.DateTime

import lila.user.User

case class Round(
    id: Round.Id,
    date: DateTime,
    result: Result,
    rating: Int,
    ratingDiff: Int
) {

  def userPostRating = rating + ratingDiff
}

object Round {

  case class Id(userId: User.ID, puzzleId: PuzzleId)

  object BSONFields {
    val id = "_id"
    val date = "a"
    val magic = "m"
  }

  import reactivemongo.bson._
  import lila.db.BSON
  import lila.db.dsl._
  import BSON.BSONJodaDateTimeHandler

  private implicit val ResultBSONHandler = booleanAnyValHandler[Result](_.win, Result.apply)

  implicit val roundIdHandler: BSONHandler[BSONString, Id] = new BSONHandler[BSONString, Id] {
    private val sep = ':'
    /* We shift the puzzle ID by -60000
     * Because the initial puzzle is 60000 and something.
     * This way the lowest puzzle ID is 00000
     * and it allows us to sort rounds by ID: userId:puzzleId
     * because all puzzle IDs have the same length */
    private val shift = 60000
    def read(bs: BSONString) = bs.value split sep match {
      case Array(userId, puzzleId) => Id(userId, Integer.parseInt(puzzleId) + shift)
      case _ => sys error s"Invalid puzzle round id ${bs.value}"
    }
    def write(id: Id) = {
      val puzzleId = "%05d".format(id.puzzleId - shift)
      BSONString(s"${id.userId}$sep$puzzleId")
    }
  }

  implicit val RoundBSONHandler = new BSON[Round] {

    import BSONFields._

    /* `magic` field stores;
     * - win: boolean     | 1 bit
     * - ratingDiff: int  | 15 bits
     * - rating: int      | 16 bits
     */

    def reads(r: BSON.Reader): Round = {
      val m = r int magic
      val win = m >>> 31 != 0
      val ratingDiff = (m << 1) >>> 17
      Round(
        id = r.get[Id](id),
        date = r.get[DateTime](date),
        result = Result(win),
        rating = m & (-1 >>> 16),
        ratingDiff = if (win) ratingDiff else -ratingDiff
      )
    }

    def writes(w: BSON.Writer, o: Round) = BSONDocument(
      id -> o.id,
      date -> o.date,
      magic -> {
        (o.result.win ?? (1 << 31)) |
          (Math.abs(o.ratingDiff) << 16) |
          o.rating
      }
    )
  }
}
{'fraction_non_alphanumeric': 0.11872871736662884, 'fraction_numerical': 0.018615209988649264, 'mean_word_length': 2.2905153099327857, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 31, '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': '5610855', 'n_tokens_mistral': 1557, 'n_tokens_neox': 1459, 'n_words': 433}