lila/modules/puzzle/src/main/Puzzle.scala

138 lines
3.7 KiB
Scala
Raw Normal View History

2014-02-03 11:53:10 -07:00
package lila.puzzle
2014-02-05 01:57:50 -07:00
import chess.Color
2014-02-03 11:53:10 -07:00
import org.joda.time.DateTime
import scalaz.NonEmptyList
2014-02-06 11:22:28 -07:00
import lila.rating.Perf
2014-02-03 11:53:10 -07:00
case class Puzzle(
2014-02-03 14:04:43 -07:00
id: PuzzleId,
gameId: Option[String],
history: List[String],
fen: String,
lines: List[Line],
2014-02-05 01:57:50 -07:00
depth: Int,
color: Color,
2014-02-03 14:04:43 -07:00
date: DateTime,
2014-02-06 11:22:28 -07:00
perf: Perf,
2014-02-06 13:36:31 -07:00
vote: Vote,
2014-02-05 01:57:50 -07:00
attempts: Int,
wins: Int,
time: Int) {
2014-02-03 14:04:43 -07:00
def initialPly: Option[Int] = fen.split(' ').lastOption flatMap parseIntOption map { move =>
move * 2 + color.fold(0, 1)
}
2014-02-17 02:12:19 -07:00
def withVote(f: Vote => Vote) = copy(vote = f(vote))
2014-02-06 13:36:31 -07:00
2014-02-05 13:18:15 -07:00
def winPercent = if (attempts == 0) 0 else wins * 100 / attempts
2014-02-03 14:04:43 -07:00
def initialMove = history.last
2014-02-09 16:17:33 -07:00
def enabled = vote.sum > -9000
2014-02-03 14:04:43 -07:00
}
2014-02-03 11:53:10 -07:00
object Puzzle {
def make(
gameId: Option[String],
history: List[String],
fen: String,
2014-02-05 13:54:19 -07:00
lines: Lines)(id: PuzzleId) = new Puzzle(
id = id,
2014-02-03 11:53:10 -07:00
gameId = gameId,
history = history,
fen = fen,
lines = lines,
2014-02-05 16:18:11 -07:00
depth = Line minDepth lines,
2014-02-05 01:57:50 -07:00
color = Color(history.size % 2 == 0),
2014-02-03 11:53:10 -07:00
date = DateTime.now,
2014-02-06 11:22:28 -07:00
perf = Perf.default,
2014-02-06 13:36:31 -07:00
vote = Vote(0, 0, 0),
2014-02-05 01:57:50 -07:00
attempts = 0,
wins = 0,
time = 0)
2014-02-03 11:53:10 -07:00
import reactivemongo.bson._
import lila.db.BSON
import BSON.BSONJodaDateTimeHandler
private implicit val lineBSONHandler = new BSONHandler[BSONDocument, Lines] {
2014-02-05 01:57:50 -07:00
private def readMove(move: String) = chess.Pos.doublePiotrToKey(move take 2) match {
2014-02-17 02:12:19 -07:00
case Some(m) => s"$m${move drop 2}"
case _ => sys error s"Invalid piotr move notation: $move"
2014-02-05 01:57:50 -07:00
}
2014-02-03 11:53:10 -07:00
def read(doc: BSONDocument): Lines = doc.elements.toList map {
2014-02-17 02:12:19 -07:00
case (move, BSONBoolean(true)) => Win(readMove(move))
case (move, BSONBoolean(false)) => Retry(readMove(move))
case (move, more: BSONDocument) => Node(readMove(move), read(more))
case (move, value) => throw new Exception(s"Can't read value of $move: $value")
2014-02-05 01:57:50 -07:00
}
private def writeMove(move: String) = chess.Pos.doubleKeyToPiotr(move take 4) match {
2014-02-17 02:12:19 -07:00
case Some(m) => s"$m${move drop 4}"
case _ => sys error s"Invalid move notation: $move"
2014-02-03 11:53:10 -07:00
}
def write(lines: Lines): BSONDocument = BSONDocument(lines map {
2014-02-17 02:12:19 -07:00
case Win(move) => writeMove(move) -> BSONBoolean(true)
case Retry(move) => writeMove(move) -> BSONBoolean(false)
case Node(move, lines) => writeMove(move) -> write(lines)
2014-02-03 11:53:10 -07:00
})
}
object BSONFields {
val id = "_id"
val gameId = "gameId"
val history = "history"
val fen = "fen"
val lines = "lines"
2014-02-05 01:57:50 -07:00
val depth = "depth"
val white = "white"
2014-02-03 11:53:10 -07:00
val date = "date"
2014-02-06 11:22:28 -07:00
val perf = "perf"
2014-02-08 04:28:36 -07:00
val rating = s"$perf.gl.r"
2014-02-03 11:53:10 -07:00
val vote = "vote"
2014-02-08 04:28:36 -07:00
val voteSum = s"$vote.sum"
2014-02-03 11:53:10 -07:00
val attempts = "attempts"
2014-02-05 01:57:50 -07:00
val wins = "wins"
val time = "time"
2014-02-03 11:53:10 -07:00
}
implicit val puzzleBSONHandler = new BSON[Puzzle] {
import BSONFields._
2014-02-06 11:22:28 -07:00
import Perf.perfBSONHandler
2014-02-06 13:36:31 -07:00
import Vote.voteBSONHandler
2014-02-03 11:53:10 -07:00
def reads(r: BSON.Reader): Puzzle = Puzzle(
2014-02-05 13:54:19 -07:00
id = r int id,
2014-02-03 11:53:10 -07:00
gameId = r strO gameId,
history = r str history split ' ' toList,
fen = r str fen,
lines = r.get[Lines](lines),
2014-02-05 01:57:50 -07:00
depth = r int depth,
color = Color(r bool white),
2014-02-03 11:53:10 -07:00
date = r date date,
2014-02-06 11:22:28 -07:00
perf = r.get[Perf](perf),
2014-02-06 13:36:31 -07:00
vote = r.get[Vote](vote),
2014-02-06 11:22:28 -07:00
attempts = r int attempts,
wins = r int wins,
time = r int time)
2014-02-03 11:53:10 -07:00
def writes(w: BSON.Writer, o: Puzzle) = BSONDocument(
id -> o.id,
gameId -> o.gameId,
history -> o.history.mkString(" "),
fen -> o.fen,
lines -> o.lines,
2014-02-05 01:57:50 -07:00
depth -> o.depth,
white -> o.color.white,
2014-02-03 11:53:10 -07:00
date -> o.date,
2014-02-06 11:22:28 -07:00
perf -> o.perf,
2014-02-03 11:53:10 -07:00
vote -> o.vote,
2014-02-05 01:57:50 -07:00
attempts -> o.attempts,
2014-02-05 17:34:22 -07:00
wins -> o.wins,
time -> o.time)
2014-02-03 11:53:10 -07:00
}
}