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

144 lines
3.8 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
2016-11-29 06:15:46 -07:00
import chess.format.Uci
2014-02-03 11:53:10 -07:00
import org.joda.time.DateTime
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,
2016-11-26 07:49:25 -07:00
gameId: String,
2014-02-03 14:04:43 -07:00
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,
vote: AggregateVote,
2014-02-05 01:57:50 -07:00
attempts: Int,
mate: Boolean) {
2014-02-03 14:04:43 -07:00
2016-11-28 08:17:23 -07:00
def initialPly: Int = history.size
def withVote(f: AggregateVote => AggregateVote) = copy(vote = f(vote))
2014-02-06 13:36:31 -07:00
2016-11-29 06:15:46 -07:00
def initialMove: Uci.Move = history.lastOption flatMap Uci.Move.apply err s"Bad initial move $this"
2014-02-09 16:17:33 -07:00
def enabled = vote.sum > -9000
def fenAfterInitialMove: Option[String] = {
import chess.format.{ Uci, Forsyth }
for {
sit1 <- Forsyth << fen
2016-11-29 06:15:46 -07:00
sit2 <- sit1.move(initialMove).toOption.map(_.situationAfter)
} yield Forsyth >> sit2
}
2014-02-03 14:04:43 -07:00
}
2014-02-03 11:53:10 -07:00
object Puzzle {
def make(
2016-11-26 07:49:25 -07:00
gameId: String,
2014-02-03 11:53:10 -07:00
history: List[String],
fen: String,
2016-07-29 06:11:56 -06:00
color: Color,
lines: Lines,
mate: Boolean)(id: PuzzleId) = new Puzzle(
2014-02-05 13:54:19 -07:00
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,
2016-07-29 06:11:56 -06:00
color = color,
2014-02-03 11:53:10 -07:00
date = DateTime.now,
2014-02-06 11:22:28 -07:00
perf = Perf.default,
vote = AggregateVote(0, 0, 0),
2014-02-05 01:57:50 -07:00
attempts = 0,
mate = mate)
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 {
case BSONElement(move, BSONBoolean(true)) => Win(readMove(move))
case BSONElement(move, BSONBoolean(false)) => Retry(readMove(move))
case BSONElement(move, more: BSONDocument) =>
Node(readMove(move), read(more))
case BSONElement(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"
val mate = "mate"
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
import AggregateVote.aggregatevoteBSONHandler
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,
2016-11-26 07:49:25 -07:00
gameId = r str gameId,
2014-02-03 11:53:10 -07:00
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),
vote = r.get[AggregateVote](vote),
2014-02-06 11:22:28 -07:00
attempts = r int attempts,
mate = r bool mate)
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,
2016-08-13 05:06:03 -06:00
mate -> o.mate)
2014-02-03 11:53:10 -07:00
}
}