<commit_before>package lila.common

import org.joda.time.{ DateTime, DateTimeZone }
import play.api.data.format.Formats._
import play.api.data.format.{ Formatter, JodaFormats }
import play.api.data.Forms._
import play.api.data.JodaForms._
import play.api.data.validation.Constraint
import play.api.data.{ Field, FormError, Mapping }
import scala.util.Try

object Form {

  type Options[A] = Iterable[(A, String)]

  type FormLike = {
    def apply(key: String): Field
    def errors: Seq[FormError]
  }

  def options(it: Iterable[Int], pattern: String): Options[Int] = it map { d =>
    d -> (pluralize(pattern, d) format d)
  }

  def options(it: Iterable[Int], transformer: Int => Int, pattern: String): Options[Int] = it map { d =>
    d -> (pluralize(pattern, transformer(d)) format transformer(d))
  }

  def options(it: Iterable[Int], code: String, pattern: String): Options[String] = it map { d =>
    s"$d$code" -> (pluralize(pattern, d) format d)
  }

  def optionsDouble(it: Iterable[Double], format: Double => String): Options[Double] = it map { d =>
    d -> format(d)
  }

  def numberIn(choices: Options[Int]) =
    number.verifying(hasKey(choices, _))

  def numberIn(choices: Seq[Int]) =
    number.verifying(choices.contains _)

  def numberInDouble(choices: Options[Double]) =
    of[Double].verifying(hasKey(choices, _))

  def stringIn(choices: Options[String]) =
    text.verifying(hasKey(choices, _))

  def tolerantBoolean = of[Boolean](formatter.tolerantBooleanFormatter)

  def hasKey[A](choices: Options[A], key: A) =
    choices.map(_._1).toList contains key

  def trueish(v: Any) = v == 1 || v == "1" || v == "true" || v == "on" || v == "yes"

  private def pluralize(pattern: String, nb: Int) =
    pattern.replace("{s}", if (nb == 1) "" else "s")

  object formatter {
    def stringFormatter[A](from: A => String, to: String => A): Formatter[A] = new Formatter[A] {
      def bind(key: String, data: Map[String, String]) = stringFormat.bind(key, data) map to
      def unbind(key: String, value: A)                = stringFormat.unbind(key, from(value))
    }
    def intFormatter[A](from: A => Int, to: Int => A): Formatter[A] = new Formatter[A] {
      def bind(key: String, data: Map[String, String]) = intFormat.bind(key, data) map to
      def unbind(key: String, value: A)                = intFormat.unbind(key, from(value))
    }
    val tolerantBooleanFormatter: Formatter[Boolean] = new Formatter[Boolean] {
      override val format = Some(("format.boolean", Nil))
      def bind(key: String, data: Map[String, String]) =
        Right(data.getOrElse(key, "false")).flatMap { v =>
          Right(trueish(v))
        }
      def unbind(key: String, value: Boolean) = Map(key -> value.toString)
    }
  }

  object constraint {
    import play.api.data.{ validation => V }
    def minLength[A](from: A => String)(length: Int): Constraint[A] =
      Constraint[A]("constraint.minLength", length) { o =>
        if (from(o).size >= length) V.Valid else V.Invalid(V.ValidationError("error.minLength", length))
      }
    def maxLength[A](from: A => String)(length: Int): Constraint[A] =
      Constraint[A]("constraint.maxLength", length) { o =>
        if (from(o).size <= length) V.Valid else V.Invalid(V.ValidationError("error.maxLength", length))
      }
  }

  def inTheFuture(m: Mapping[DateTime]) = m.verifying(
    "The date must be set in the future",
    DateTime.now.isBefore(_)
  )

  object UTCDate {
    val dateTimePattern         = "yyyy-MM-dd HH:mm"
    val utcDate                 = jodaDate(dateTimePattern, DateTimeZone.UTC)
    implicit val dateTimeFormat = JodaFormats.jodaDateTimeFormat(dateTimePattern)
  }
  object ISODateTime {
    val dateTimePattern         = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    val formatter               = JodaFormats.jodaDateTimeFormat(dateTimePattern, DateTimeZone.UTC)
    val isoDateTime             = jodaDate(dateTimePattern, DateTimeZone.UTC)
    implicit val dateTimeFormat = JodaFormats.jodaDateTimeFormat(dateTimePattern)
  }
  object ISODate {
    val datePattern         = "yyyy-MM-dd"
    val formatter           = JodaFormats.jodaDateTimeFormat(datePattern, DateTimeZone.UTC)
    val isoDateTime         = jodaDate(datePattern, DateTimeZone.UTC)
    implicit val dateFormat = JodaFormats.jodaDateTimeFormat(datePattern)
  }
  object Timestamp {
    val formatter = new Formatter[org.joda.time.DateTime] {
      def bind(key: String, data: Map[String, String]) =
        stringFormat
          .bind(key, data)
          .flatMap { str =>
            Try(java.lang.Long.parseLong(str)).toEither.flatMap { long =>
              Try(new DateTime(long)).toEither
            }
          }
          .left
          .map(_ => Seq(FormError(key, "Invalid timestamp", Nil)))
      def unbind(key: String, value: org.joda.time.DateTime) = Map(key -> value.getMillis.toString)
    }
    val timestamp = of[org.joda.time.DateTime](formatter)
  }
  object ISODateOrTimestamp {
    val formatter = new Formatter[org.joda.time.DateTime] {
      def bind(key: String, data: Map[String, String]) =
        ISODate.formatter.bind(key, data) orElse Timestamp.formatter.bind(key, data)
      def unbind(key: String, value: org.joda.time.DateTime) = ISODate.formatter.unbind(key, value)
    }
    val isoDateOrTimestamp = of[org.joda.time.DateTime](formatter)
  }
  object ISODateTimeOrTimestamp {
    val formatter = new Formatter[org.joda.time.DateTime] {
      def bind(key: String, data: Map[String, String]) =
        ISODateTime.formatter.bind(key, data) orElse Timestamp.formatter.bind(key, data)
      def unbind(key: String, value: org.joda.time.DateTime) = ISODate.formatter.unbind(key, value)
    }
    val isoDateTimeOrTimestamp = of[org.joda.time.DateTime](formatter)
  }
}
<commit_msg>fix broadcast start date form input<commit_after>package lila.common

import org.joda.time.{ DateTime, DateTimeZone }
import play.api.data.format.Formats._
import play.api.data.format.{ Formatter, JodaFormats }
import play.api.data.Forms._
import play.api.data.JodaForms._
import play.api.data.validation.Constraint
import play.api.data.{ Field, FormError, Mapping }
import scala.util.Try

object Form {

  type Options[A] = Iterable[(A, String)]

  type FormLike = {
    def apply(key: String): Field
    def errors: Seq[FormError]
  }

  def options(it: Iterable[Int], pattern: String): Options[Int] = it map { d =>
    d -> (pluralize(pattern, d) format d)
  }

  def options(it: Iterable[Int], transformer: Int => Int, pattern: String): Options[Int] = it map { d =>
    d -> (pluralize(pattern, transformer(d)) format transformer(d))
  }

  def options(it: Iterable[Int], code: String, pattern: String): Options[String] = it map { d =>
    s"$d$code" -> (pluralize(pattern, d) format d)
  }

  def optionsDouble(it: Iterable[Double], format: Double => String): Options[Double] = it map { d =>
    d -> format(d)
  }

  def numberIn(choices: Options[Int]) =
    number.verifying(hasKey(choices, _))

  def numberIn(choices: Seq[Int]) =
    number.verifying(choices.contains _)

  def numberInDouble(choices: Options[Double]) =
    of[Double].verifying(hasKey(choices, _))

  def stringIn(choices: Options[String]) =
    text.verifying(hasKey(choices, _))

  def tolerantBoolean = of[Boolean](formatter.tolerantBooleanFormatter)

  def hasKey[A](choices: Options[A], key: A) =
    choices.map(_._1).toList contains key

  def trueish(v: Any) = v == 1 || v == "1" || v == "true" || v == "on" || v == "yes"

  private def pluralize(pattern: String, nb: Int) =
    pattern.replace("{s}", if (nb == 1) "" else "s")

  object formatter {
    def stringFormatter[A](from: A => String, to: String => A): Formatter[A] = new Formatter[A] {
      def bind(key: String, data: Map[String, String]) = stringFormat.bind(key, data) map to
      def unbind(key: String, value: A)                = stringFormat.unbind(key, from(value))
    }
    def intFormatter[A](from: A => Int, to: Int => A): Formatter[A] = new Formatter[A] {
      def bind(key: String, data: Map[String, String]) = intFormat.bind(key, data) map to
      def unbind(key: String, value: A)                = intFormat.unbind(key, from(value))
    }
    val tolerantBooleanFormatter: Formatter[Boolean] = new Formatter[Boolean] {
      override val format = Some(("format.boolean", Nil))
      def bind(key: String, data: Map[String, String]) =
        Right(data.getOrElse(key, "false")).flatMap { v =>
          Right(trueish(v))
        }
      def unbind(key: String, value: Boolean) = Map(key -> value.toString)
    }
  }

  object constraint {
    import play.api.data.{ validation => V }
    def minLength[A](from: A => String)(length: Int): Constraint[A] =
      Constraint[A]("constraint.minLength", length) { o =>
        if (from(o).size >= length) V.Valid else V.Invalid(V.ValidationError("error.minLength", length))
      }
    def maxLength[A](from: A => String)(length: Int): Constraint[A] =
      Constraint[A]("constraint.maxLength", length) { o =>
        if (from(o).size <= length) V.Valid else V.Invalid(V.ValidationError("error.maxLength", length))
      }
  }

  def inTheFuture(m: Mapping[DateTime]) = m.verifying(
    "The date must be set in the future",
    DateTime.now.isBefore(_)
  )

  object UTCDate {
    val dateTimePattern         = "yyyy-MM-dd HH:mm"
    val utcDate                 = jodaDate(dateTimePattern, DateTimeZone.UTC)
    implicit val dateTimeFormat = JodaFormats.jodaDateTimeFormat(dateTimePattern)
  }
  object ISODateTime {
    val dateTimePattern         = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
    val formatter               = JodaFormats.jodaDateTimeFormat(dateTimePattern, DateTimeZone.UTC)
    val isoDateTime             = jodaDate(dateTimePattern, DateTimeZone.UTC)
    implicit val dateTimeFormat = JodaFormats.jodaDateTimeFormat(dateTimePattern)
  }
  object ISODate {
    val datePattern         = "yyyy-MM-dd"
    val formatter           = JodaFormats.jodaDateTimeFormat(datePattern, DateTimeZone.UTC)
    val isoDateTime         = jodaDate(datePattern, DateTimeZone.UTC)
    implicit val dateFormat = JodaFormats.jodaDateTimeFormat(datePattern)
  }
  object Timestamp {
    val formatter = new Formatter[org.joda.time.DateTime] {
      def bind(key: String, data: Map[String, String]) =
        stringFormat
          .bind(key, data)
          .flatMap { str =>
            Try(java.lang.Long.parseLong(str)).toEither.flatMap { long =>
              Try(new DateTime(long)).toEither
            }
          }
          .left
          .map(_ => Seq(FormError(key, "Invalid timestamp", Nil)))
      def unbind(key: String, value: org.joda.time.DateTime) = Map(key -> value.getMillis.toString)
    }
    val timestamp = of[org.joda.time.DateTime](formatter)
  }
  object ISODateOrTimestamp {
    val formatter = new Formatter[org.joda.time.DateTime] {
      def bind(key: String, data: Map[String, String]) =
        ISODate.formatter.bind(key, data) orElse Timestamp.formatter.bind(key, data)
      def unbind(key: String, value: org.joda.time.DateTime) = ISODate.formatter.unbind(key, value)
    }
    val isoDateOrTimestamp = of[org.joda.time.DateTime](formatter)
  }
  object ISODateTimeOrTimestamp {
    val formatter = new Formatter[org.joda.time.DateTime] {
      def bind(key: String, data: Map[String, String]) =
        ISODateTime.formatter.bind(key, data) orElse Timestamp.formatter.bind(key, data)
      def unbind(key: String, value: org.joda.time.DateTime) = ISODateTime.formatter.unbind(key, value)
    }
    val isoDateTimeOrTimestamp = of[org.joda.time.DateTime](formatter)
  }
}

{'fraction_non_alphanumeric': 0.13691298342541436, 'fraction_numerical': 0.0006906077348066298, 'mean_word_length': 3.2907407407407407, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 55, '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': '1192492', 'n_tokens_mistral': 3839, 'n_tokens_neox': 3740, 'n_words': 853}