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,
|
2016-08-24 14:43:55 -06:00
|
|
|
vote: AggregateVote,
|
2014-02-05 01:57:50 -07:00
|
|
|
attempts: Int,
|
2016-08-11 06:56:24 -06:00
|
|
|
mate: Boolean) {
|
2014-02-03 14:04:43 -07:00
|
|
|
|
2016-11-28 08:17:23 -07:00
|
|
|
def initialPly: Int = history.size
|
2014-02-25 13:44:02 -07:00
|
|
|
|
2016-08-24 14:43:55 -06:00
|
|
|
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
|
2015-03-17 16:32:45 -06:00
|
|
|
|
|
|
|
def fenAfterInitialMove: Option[String] = {
|
2016-01-15 06:21:16 -07:00
|
|
|
import chess.format.{ Uci, Forsyth }
|
2015-03-17 16:32:45 -06:00
|
|
|
for {
|
|
|
|
sit1 <- Forsyth << fen
|
2016-11-29 06:15:46 -07:00
|
|
|
sit2 <- sit1.move(initialMove).toOption.map(_.situationAfter)
|
2015-03-17 16:32:45 -06:00
|
|
|
} 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,
|
2016-08-11 06:56:24 -06:00
|
|
|
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,
|
2016-08-24 14:43:55 -06:00
|
|
|
vote = AggregateVote(0, 0, 0),
|
2014-02-05 01:57:50 -07:00
|
|
|
attempts = 0,
|
2016-08-11 06:56:24 -06:00
|
|
|
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 {
|
2016-10-29 02:57:55 -06:00
|
|
|
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"
|
2016-08-11 06:56:24 -06:00
|
|
|
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
|
2016-08-24 14:43:55 -06:00
|
|
|
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),
|
2016-08-24 14:43:55 -06:00
|
|
|
vote = r.get[AggregateVote](vote),
|
2014-02-06 11:22:28 -07:00
|
|
|
attempts = r int attempts,
|
2016-08-11 06:56:24 -06:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|