import PGN variations and comments in study - WIP
parent
f17ebc390b
commit
003ffad1f8
|
@ -1 +1 @@
|
|||
Subproject commit b32f8c8941602f4ff0ab0088ad29939934a9bf46
|
||||
Subproject commit 286395e16efc955fbbd10fcbaccb26f081f3337a
|
|
@ -21,11 +21,12 @@ private[importer] final class DataForm {
|
|||
}
|
||||
|
||||
private[importer] case class Result(status: Status, winner: Option[Color])
|
||||
private[importer] case class Preprocessed(
|
||||
case class Preprocessed(
|
||||
game: Game,
|
||||
replay: Replay,
|
||||
result: Option[Result],
|
||||
initialFen: Option[FEN])
|
||||
initialFen: Option[FEN],
|
||||
parsed: ParsedPgn)
|
||||
|
||||
case class ImportData(pgn: String, analyse: Option[String]) {
|
||||
|
||||
|
@ -35,7 +36,7 @@ case class ImportData(pgn: String, analyse: Option[String]) {
|
|||
|
||||
def preprocess(user: Option[String]): Valid[Preprocessed] = Parser.full(pgn) flatMap {
|
||||
case ParsedPgn(_, sans) if sans.size > maxPlies => !!("Replay is too long")
|
||||
case ParsedPgn(tags, sans) => Reader.full(pgn) map {
|
||||
case parsed@ParsedPgn(tags, sans) => Reader.full(pgn) map {
|
||||
case replay@Replay(setup, _, game) =>
|
||||
def tag(which: Tag.type => TagType): Option[String] =
|
||||
tags find (_.name == which(Tag)) map (_.value)
|
||||
|
@ -79,7 +80,7 @@ case class ImportData(pgn: String, analyse: Option[String]) {
|
|||
binaryPgn = BinaryFormat.pgn write replay.state.pgnMoves
|
||||
).start
|
||||
|
||||
Preprocessed(dbGame, replay, result, initialFen)
|
||||
Preprocessed(dbGame, replay, result, initialFen, parsed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ final class Importer(
|
|||
|
||||
gameExists {
|
||||
(data preprocess user).future flatMap {
|
||||
case Preprocessed(g, replay, result, initialFen) =>
|
||||
case Preprocessed(g, replay, result, initialFen, _) =>
|
||||
val started = forceId.fold(g)(g.withId).start
|
||||
val game = applyResult(started, result, replay.state.situation)
|
||||
(GameRepo.insertDenormalized(game, initialFen = initialFen)) >> {
|
||||
|
@ -55,6 +55,6 @@ final class Importer(
|
|||
}
|
||||
|
||||
def inMemory(data: ImportData): Valid[(Game, Option[FEN])] = data.preprocess(user = none).map {
|
||||
case Preprocessed(game, replay, _, fen) => (game withId "synthetic", fen)
|
||||
case Preprocessed(game, replay, _, fen, _) => (game withId "synthetic", fen)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ object Node {
|
|||
case class Comment(text: String, by: String)
|
||||
object Comment {
|
||||
def byLichess(text: String) = Comment(text, "lichess")
|
||||
def byUnknown(text: String) = Comment(text, "")
|
||||
def sanitize(text: String) = text.trim().take(2000)
|
||||
.replaceAll("""\r\n""", "\n") // these 3 lines dedup white spaces and new lines
|
||||
.replaceAll("""(?m)(^ *| +(?= |$))""", "")
|
||||
|
|
|
@ -23,9 +23,17 @@ private final class ChapterMaker(domain: String, importer: Importer) {
|
|||
}
|
||||
|
||||
private def fromPgn(study: Study, pgn: String, data: Data, orientation: Color, order: Int): Fu[Option[Chapter]] =
|
||||
importer.inMemory(ImportData(pgn, analyse = none)).fold(err => fufail(err.shows), {
|
||||
case (game, fen) => fromPov(study, Pov(game, orientation), data, order, fen)
|
||||
})
|
||||
PgnImport(pgn).future map { res =>
|
||||
Chapter.make(
|
||||
studyId = study.id,
|
||||
name = data.name,
|
||||
setup = Chapter.Setup(
|
||||
none,
|
||||
res.variant,
|
||||
orientation),
|
||||
root = res.root,
|
||||
order = order).some
|
||||
}
|
||||
|
||||
private def fromFenOrBlank(study: Study, data: Data, orientation: Color, order: Int): Option[Chapter] = {
|
||||
val variant = data.variant.flatMap(Variant.apply) | Variant.default
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package lila.study
|
||||
|
||||
import scalaz.Validation.FlatMap._
|
||||
|
||||
import chess.format.pgn.{ Pgn, Tag, TagType, Parser, ParsedPgn, Glyphs, San, Dumper }
|
||||
import chess.format.{ Forsyth, FEN, Uci, UciCharPair }
|
||||
import lila.importer.{ ImportData, Preprocessed }
|
||||
import lila.socket.tree.Node.{ Comment, Comments }
|
||||
|
||||
private object PgnImport {
|
||||
|
||||
private type TagPicker = Tag.type => TagType
|
||||
|
||||
case class Result(
|
||||
root: Node.Root,
|
||||
variant: chess.variant.Variant)
|
||||
|
||||
def apply(pgn: String): Valid[Result] =
|
||||
ImportData(pgn, analyse = none).preprocess(user = none).map {
|
||||
case Preprocessed(game, replay, result, initialFen, ParsedPgn(tags, sans)) => Result(
|
||||
root = Node.Root(
|
||||
ply = replay.setup.turns,
|
||||
fen = initialFen | FEN(game.variant.initialFen),
|
||||
check = replay.setup.situation.check,
|
||||
shapes = Nil,
|
||||
comments = Comments(Nil),
|
||||
glyphs = Glyphs.empty,
|
||||
crazyData = replay.setup.situation.board.crazyData,
|
||||
children = makeNode(replay.setup, sans).fold(
|
||||
err => {
|
||||
logger.warn(s"PgnImport $err")
|
||||
Node.emptyChildren
|
||||
},
|
||||
node => Node.Children(node.toVector)
|
||||
)),
|
||||
variant = game.variant)
|
||||
}
|
||||
|
||||
private def makeNode(prev: chess.Game, sans: List[San]): Valid[Option[Node]] =
|
||||
sans match {
|
||||
case Nil => success(none)
|
||||
case san :: rest => san(prev.situation) flatMap { moveOrDrop =>
|
||||
val game = moveOrDrop.fold(prev.apply, prev.applyDrop)
|
||||
val uci = moveOrDrop.fold(_.toUci, _.toUci)
|
||||
val sanStr = moveOrDrop.fold(Dumper.apply, Dumper.apply)
|
||||
makeNode(game, rest) map { mainline =>
|
||||
val variations = rest.headOption.?? {
|
||||
_.metas.variations.flatMap { variation =>
|
||||
makeNode(game, variation).fold({ err =>
|
||||
logger.warn(s"$variation $err")
|
||||
none
|
||||
}, identity)
|
||||
}
|
||||
}
|
||||
Node(
|
||||
id = UciCharPair(uci),
|
||||
ply = game.turns,
|
||||
move = Uci.WithSan(uci, sanStr),
|
||||
fen = FEN(Forsyth >> game),
|
||||
check = game.situation.check,
|
||||
shapes = Nil,
|
||||
comments = Comments(san.metas.comments map Comment.byUnknown),
|
||||
glyphs = san.metas.glyphs,
|
||||
crazyData = game.situation.board.crazyData,
|
||||
children = Node.Children {
|
||||
mainline.fold(variations)(_ :: variations).toVector
|
||||
}
|
||||
).some
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue