<commit_before>package lila.study

import chess.{ Pos, Color }
import lila.socket.tree.Node.{ Shape, Shapes }

private object ShapeParser {

  private val circlesRegex = """.*\[\%csl ((?:\w{3},?)+)\].*""".r
  private val circlesRemoveRegex = """\[\%csl ((?:\w{3},?)+)\]""".r
  private val arrowsRegex = """.*\[\%cal ((?:\w{5},?)+)\].*""".r
  private val arrowsRemoveRegex = """\[\%cal ((?:\w{5},?)+)\]""".r

  private type ShapesAndComment = (Shapes, String)

  def apply(comment: String): ShapesAndComment =
    parseCircles(comment) match {
      case (circles, c2) => parseArrows(c2) match {
        case (arrows, c3) => (circles ++ arrows) -> c3
      }
    }

  private def parseCircles(comment: String): ShapesAndComment = comment match {
    case circlesRegex(str) =>
      val circles = str.split(',').toList.flatMap { c =>
        for {
          color <- c.headOption
          pos <- Pos posAt c.drop(1)
        } yield Shape.Circle(toBrush(color), pos)
      }
      Shapes(circles) -> circlesRemoveRegex.replaceAllIn(comment, "")
    case _ => Shapes(Nil) -> comment
  }

  private def parseArrows(comment: String): ShapesAndComment = comment match {
    case arrowsRegex(str) =><commit_msg>fix study shapes parser (handle extra whitespace)<commit_after>package lila.study

import chess.{ Pos, Color }
import lila.socket.tree.Node.{ Shape, Shapes }

private object ShapeParser {

  private val circlesRegex = """.*\[\%csl ((?:\w{3}[,\s]*)+)\].*""".r
  private val circlesRemoveRegex = """\[\%csl ((?:\w{3}[,\s]*)+)\]""".r
  private val arrowsRegex = """.*\[\%cal ((?:\w{5}[,\s]*)+)\].*""".r
  private val arrowsRemoveRegex = """\[\%cal ((?:\w{5}[,\s]*)+)\]""".r

  private type ShapesAndComment = (Shapes, String)

  def apply(comment: String): ShapesAndComment =
    parseCircles(comment) match {
      case (circles, c2) => parseArrows(c2) match {
        case (arrows, c3) => (circles ++ arrows) -> c3
      }
    }

  private def parseCircles(comment: String): ShapesAndComment = comment match {
    case circlesRegex(str) =>
      val circles = str.split(',').toList.map(_.trim).flatMap { c =>
        for {
          color <- c.headOption
          pos <- Pos posAt c.drop(1)
        } yield Shape.Circle(toBrush(color), pos)
      }
      Shapes(circles) -> circlesRemoveRegex.replaceAllIn(comment, "")
    case _ => Shapes(Nil) -> comment
  }

  private def parseArrows(comment: String): ShapesAndComment = comment match {
    case arrowsRegex(str) =>
{'fraction_non_alphanumeric': 0.19093851132686085, 'fraction_numerical': 0.007281553398058253, 'mean_word_length': 3.1844331641285955, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5988257', 'n_tokens_mistral': 861, 'n_tokens_neox': 811, 'n_words': 190}