From 764d9a5d2ded1792ef5c02e26f14ecf71033631d Mon Sep 17 00:00:00 2001 From: Thanh Le Date: Wed, 10 Apr 2024 20:24:26 +0700 Subject: [PATCH] Add emt field to Study & parse it --- modules/study/src/main/BSONHandlers.scala | 6 ++-- modules/study/src/main/CommentParser.scala | 16 +++++++++-- modules/study/src/main/NewPgnImport.scala | 8 ++++-- modules/study/src/main/Node.scala | 1 + modules/study/src/main/PgnImport.scala | 32 ++++++++++++---------- modules/tree/src/main/newTree.scala | 3 ++ modules/tree/src/main/tree.scala | 3 ++ 7 files changed, 46 insertions(+), 23 deletions(-) diff --git a/modules/study/src/main/BSONHandlers.scala b/modules/study/src/main/BSONHandlers.scala index 05584b9a9d8fe..7231de2f08291 100644 --- a/modules/study/src/main/BSONHandlers.scala +++ b/modules/study/src/main/BSONHandlers.scala @@ -21,9 +21,7 @@ object BSONHandlers: def reads(r: Reader) = val brush = r.str("b") r.getO[Square]("p") - .map { pos => - Shape.Circle(brush, pos) - } + .map(pos => Shape.Circle(brush, pos)) .getOrElse(Shape.Arrow(brush, r.get[Square]("o"), r.get[Square]("d"))) def writes(w: Writer, t: Shape) = t match @@ -140,6 +138,7 @@ object BSONHandlers: glyphs = doc.getAsOpt[Glyphs](F.glyphs).getOrElse(Glyphs.empty) eval = doc.getAsOpt[Score](F.score).map(_.eval) clock = doc.getAsOpt[Centis](F.clock) + emt = doc.getAsOpt[Centis](F.emt) crazyData = doc.getAsOpt[Crazyhouse.Data](F.crazy) forceVariation = ~doc.getAsOpt[Boolean](F.forceVariation) yield Branch( @@ -175,6 +174,7 @@ object BSONHandlers: glyphs = doc.getAsOpt[Glyphs](F.glyphs).getOrElse(Glyphs.empty) eval = doc.getAsOpt[Score](F.score).map(_.eval) clock = doc.getAsOpt[Centis](F.clock) + emt = doc.getAsOpt[Centis](F.emt) crazyData = doc.getAsOpt[Crazyhouse.Data](F.crazy) forceVariation = ~doc.getAsOpt[Boolean](F.forceVariation) yield NewBranch( diff --git a/modules/study/src/main/CommentParser.scala b/modules/study/src/main/CommentParser.scala index b5477eb6eaabe..0d087a4a07085 100644 --- a/modules/study/src/main/CommentParser.scala +++ b/modules/study/src/main/CommentParser.scala @@ -14,12 +14,15 @@ private[study] object CommentParser: private val arrowsRemoveRegex = """\[\%cal[\s\r\n]++((?:\w{5}[,\s]*+)++)\]""".r private val clockRegex = """(?s)\[\%clk[\s\r\n]++([\d:\.]++)\]""".r.unanchored private val clockRemoveRegex = """\[\%clk[\s\r\n]++[\d:\.]++\]""".r + private val emtRegex = """(?s)\[\%emt[\s\r\n]++([\d:\.]++)\]""".r.unanchored + private val emtRemoveRegex = """\[\%emt[\s\r\n]++[\d:\.]++\]""".r private val tcecClockRegex = """(?s)tl=([\d:\.]++)""".r.unanchored private val tcecClockRemoveRegex = """tl=[\d:\.]++""".r case class ParsedComment( shapes: Shapes, clock: Option[Centis], + emt: Option[Centis], comment: String ) @@ -27,9 +30,11 @@ private[study] object CommentParser: parseShapes(comment.value) match case (shapes, c2) => parseClock(c2) match - case (clock, c3) => ParsedComment(shapes, clock, c3) + case (clock, c3) => + parseEmt(c3) match + case (emt, c4) => ParsedComment(shapes, clock, emt, c4) - private type ClockAndComment = (Option[Centis], String) + private type CentisAndComment = (Option[Centis], String) private def readCentis(hours: String, minutes: String, seconds: String): Option[Centis] = for @@ -52,12 +57,17 @@ private[study] object CommentParser: readCentis(hours, minutes, seconds) case _ => none - private def parseClock(comment: String): ClockAndComment = + private def parseClock(comment: String): CentisAndComment = comment match case clockRegex(str) => readCentis(str) -> clockRemoveRegex.replaceAllIn(comment, "").trim case tcecClockRegex(str) => readCentis(str) -> tcecClockRemoveRegex.replaceAllIn(comment, "").trim case _ => None -> comment + private def parseEmt(comment: String): CentisAndComment = + comment match + case emtRegex(str) => readCentis(str) -> emtRemoveRegex.replaceAllIn(comment, "").trim + case _ => None -> comment + private type ShapesAndComment = (Shapes, String) private def parseShapes(comment: String): ShapesAndComment = diff --git a/modules/study/src/main/NewPgnImport.scala b/modules/study/src/main/NewPgnImport.scala index daa34dfcf3242..2ce76282dfb83 100644 --- a/modules/study/src/main/NewPgnImport.scala +++ b/modules/study/src/main/NewPgnImport.scala @@ -33,7 +33,7 @@ object NewPgnImport: case Preprocessed(game, replay, initialFen, parsedPgn) => val annotator = PgnImport.findAnnotator(parsedPgn, contributors) PgnImport.parseComments(parsedPgn.initialPosition.comments, annotator) match - case (shapes, _, comments) => + case (shapes, _, _, comments) => val root: NewRoot = NewRoot( Metas( @@ -49,7 +49,8 @@ object NewPgnImport: glyphs = Glyphs.empty, opening = None, crazyData = replay.setup.situation.board.crazyData, - clock = parsedPgn.tags.clockConfig.map(_.limit) + clock = parsedPgn.tags.clockConfig.map(_.limit), + emt = None ), parsedPgn.tree.flatMap(makeTree(replay.setup, _, annotator)) ) @@ -100,7 +101,7 @@ object NewPgnImport: ( game, PgnImport.parseComments(data.metas.comments, annotator) match - case (shapes, clock, comments) => + case (shapes, clock, emt, comments) => NewBranch( id = id, move = Uci.WithSan(uci, sanStr), @@ -119,6 +120,7 @@ object NewPgnImport: glyphs = data.metas.glyphs, opening = None, clock = clock, + emt = emt, crazyData = game.situation.board.crazyData ) ).some diff --git a/modules/study/src/main/Node.scala b/modules/study/src/main/Node.scala index 72b07322dc34c..314b858ada4db 100644 --- a/modules/study/src/main/Node.scala +++ b/modules/study/src/main/Node.scala @@ -18,3 +18,4 @@ object Node: val clock = "l" val crazy = "z" val forceVariation = "fv" + val emt = "em" diff --git a/modules/study/src/main/PgnImport.scala b/modules/study/src/main/PgnImport.scala index a54c612534d87..f86e909851f2f 100644 --- a/modules/study/src/main/PgnImport.scala +++ b/modules/study/src/main/PgnImport.scala @@ -31,7 +31,7 @@ object PgnImport: case Preprocessed(game, replay, initialFen, parsedPgn) => val annotator = findAnnotator(parsedPgn, contributors) parseComments(parsedPgn.initialPosition.comments, annotator) match - case (shapes, _, comments) => + case (shapes, _, _, comments) => val root = Root( ply = replay.setup.ply, fen = initialFen | game.variant.initialFen, @@ -40,6 +40,7 @@ object PgnImport: comments = comments, glyphs = Glyphs.empty, clock = parsedPgn.tags.clockConfig.map(_.limit), + emt = none, crazyData = replay.setup.situation.board.crazyData, children = parsedPgn.tree.fold(Branches.empty)(makeBranches(replay.setup, _, annotator)) ) @@ -88,19 +89,21 @@ object PgnImport: def parseComments( comments: List[ChessComment], annotator: Option[Comment.Author] - ): (Shapes, Option[Centis], Comments) = - comments.foldLeft((Shapes(Nil), none[Centis], Comments(Nil))) { case ((shapes, clock, comments), txt) => - CommentParser(txt) match - case CommentParser.ParsedComment(s, c, str) => - ( - (shapes ++ s), - c.orElse(clock), - (str.trim match - case "" => comments - case com => - comments + Comment(Comment.Id.make, Comment.Text(com), annotator | Comment.Author.Lichess) + ): (Shapes, Option[Centis], Option[Centis], Comments) = + comments.foldLeft((Shapes(Nil), none[Centis], none[Centis], Comments(Nil))) { + case ((shapes, clock, emt, comments), txt) => + CommentParser(txt) match + case CommentParser.ParsedComment(s, c, e, str) => + ( + (shapes ++ s), + c.orElse(clock), + e.orElse(emt), + (str.trim match + case "" => comments + case com => + comments + Comment(Comment.Id.make, Comment.Text(com), annotator | Comment.Author.Lichess) + ) ) - ) } private def makeBranches( @@ -128,7 +131,7 @@ object PgnImport: val uci = moveOrDrop.toUci val sanStr = moveOrDrop.toSanStr parseComments(node.value.metas.comments, annotator) match - case (shapes, clock, comments) => + case (shapes, clock, emt, comments) => Branch( id = UciCharPair(uci), ply = game.ply, @@ -139,6 +142,7 @@ object PgnImport: comments = comments, glyphs = node.value.metas.glyphs, clock = clock, + emt = emt, crazyData = game.situation.board.crazyData, children = node.child.fold(Branches.empty)(makeBranches(game, _, annotator)) ).some diff --git a/modules/tree/src/main/newTree.scala b/modules/tree/src/main/newTree.scala index 6f8cc60ee6e13..f5cd884f2dcc2 100644 --- a/modules/tree/src/main/newTree.scala +++ b/modules/tree/src/main/newTree.scala @@ -29,6 +29,7 @@ case class Metas( glyphs: Glyphs = Glyphs.empty, opening: Option[Opening] = None, clock: Option[Centis] = None, + emt: Option[Centis] = None, crazyData: Option[Crazyhouse.Data] = None // TODO, add support for variationComments ): @@ -79,6 +80,7 @@ case class NewBranch( glyphs, opening, clock, + emt, crazyData } override def toString = s"$ply, $id, ${move.uci}" @@ -167,6 +169,7 @@ object NewTree: node.glyphs, node.opening, node.clock, + node.emt, node.crazyData ) diff --git a/modules/tree/src/main/tree.scala b/modules/tree/src/main/tree.scala index f86abe0768250..64764e71bb225 100644 --- a/modules/tree/src/main/tree.scala +++ b/modules/tree/src/main/tree.scala @@ -164,6 +164,7 @@ sealed trait Node: def addChild(branch: Branch): Node def dropFirstChild: Node def clock: Option[Centis] + def emt: Option[Centis] def forceVariation: Boolean // implementation dependent @@ -191,6 +192,7 @@ case class Root( children: Branches = Branches.empty, opening: Option[Opening] = None, clock: Option[Centis] = None, // clock state at game start, assumed same for both players + emt: Option[Centis] = None, crazyData: Option[Crazyhouse.Data] ) extends Node: @@ -321,6 +323,7 @@ case class Branch( opening: Option[Opening] = None, comp: Boolean = false, clock: Option[Centis] = None, // clock state after the move is played, and the increment applied + emt: Option[Centis] = None, // estimated move time crazyData: Option[Crazyhouse.Data], forceVariation: Boolean = false // cannot be mainline ) extends Node: