Skip to content

Commit

Permalink
parse all sort of exotic ways to express chess results - closes liche…
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Dec 23, 2023
1 parent 278b3c0 commit 8217b3d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 39 deletions.
39 changes: 34 additions & 5 deletions src/main/scala/Outcome.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,37 @@ object Outcome:
outcome.fold("*")(_.toString)

def fromResult(result: String): Option[Outcome] =
result match
case "1-0" => Some(Outcome(Some(White)))
case "0-1" => Some(Outcome(Some(Black)))
case "1/2-1/2" => Some(Outcome(None))
case _ => None
normalizationMap.get(result)

lazy val knownResultStrings = "*" :: normalizationMap.keys.toList

private val normalizationMap: Map[String, Outcome] =
val hyphen = "-"
val enDash = ""
val emDash = ""
val dashes = List(hyphen, enDash, emDash)
val separators = dashes ::: List("_", ":")
val draws = List("½", "1/2")
val wins = List("1", "+")
val losses = "0" :: dashes

val allDraws = for
separator <- separators
draw <- draws
yield s"$draw$separator$draw"
val allWins = for
separator <- separators
win <- wins
loss <- losses
yield s"$win$separator$loss"
val allLosses = for
separator <- separators
win <- wins
loss <- losses
yield s"$loss$separator$win"

val pairs = allDraws.map(_ -> Outcome(None)) :::
allWins.map(_ -> Outcome(Some(White))) :::
allLosses.map(_ -> Outcome(Some(Black)))

pairs.toMap
36 changes: 3 additions & 33 deletions src/main/scala/format/pgn/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,39 +36,9 @@ object Parser:
val inlineComment = P.char(';') *> P.until(R.lf).map(Comment(_))
val comment = (blockComment | inlineComment).withContext("Invalid comment") <* escape

val resultList = List(
"*",
"1/2-1/2",
"½-½",
"0-1",
"1-0",
"1/2‑1/2",
"½‑½",
"0‑1",
"1‑0",
"1/2–1/2",
"½–½",
"0–1",
"1–0"
)

def mapResult(result: String): String = result match
case "½-½" => "1/2-1/2"
case "1/2‑1/2" => "1/2-1/2"
case "½‑½" => "1/2-1/2"
case "1/2–1/2" => "1/2-1/2"
case "½–½" => "1/2-1/2"
case "0‑1" => "0-1"
case "0–1" => "0-1"
case "1‑0" => "1-0"
case "1–0" => "1-0"
case "+--" => "1-0"
case "+:-" => "1-0"
case "--+" => "0-1"
case "-:+" => "0-1"
case x => x

val result: P[String] = P.stringIn(resultList).map(mapResult)
def mapResult(result: String): String = Outcome.fromResult(result).fold(result)(_.toString)

val result: P[String] = P.stringIn(Outcome.knownResultStrings).map(mapResult)

val nagGlyphsRE = P.stringIn(Glyph.PositionAssessment.all.map(_.symbol))

Expand Down
12 changes: 12 additions & 0 deletions test-kit/src/test/scala/format/pgn/Fixtures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ object Fixtures:
+--"""

val unicodeResultDraw = """[Result "½-½"]
½-½"""

val unicodeResultWeirdDashDraw = """[Result "1/2–1/2"]
1/2–1/2"""

val unicodeResultWeirdDashWin = """[Result "1–0"]
1–0"""

val recentChessCom = """[Event "Live Chess"]
[Site "Chess.com"]
[Date "2016.05.10"]
Expand Down
17 changes: 16 additions & 1 deletion test-kit/src/test/scala/format/pgn/ParserTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,22 @@ class ParserTest extends ChessTest:
parse(nbsp).assertRight: a =>
assertEquals(a.mainline.size, 2)

test("unicode result"):
parse(unicodeResultDraw)
.assertRight: a =>
assertEquals(a.tags(_.Result), Some("½-½"))
assertEquals(a.tags.outcome, Some(Outcome(None)))
parse(unicodeResultWeirdDashDraw)
.assertRight: a =>
assertEquals(a.tags(_.Result), Some("1/2–1/2"))
assertEquals(a.tags.outcome, Some(Outcome(None)))
parse(unicodeResultWeirdDashWin)
.assertRight: a =>
assertEquals(a.tags(_.Result), Some("1–0"))
assertEquals(a.tags.outcome, Some(Outcome(Some(White))))

test("absent result"):
parse(blackAbsentResult)
.assertRight: a =>
assertEquals(a.tags.outcome, Some(Outcome(Some(Black))))
assertEquals(a.tags(_.Result), Some("+--"))
assertEquals(a.tags.outcome, Some(Outcome(Some(White))))

0 comments on commit 8217b3d

Please sign in to comment.