All Downloads are FREE. Search and download functionalities are using the official Maven repository.

markovNamegen.GenerationOption.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2020 Braian De Roo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package markovNamegen

import scala.util.matching.Regex
import zio.UIO

sealed trait GenerationOption

// if the option doesnt return true the generation should keep going
trait GroupGenerationOption extends GenerationOption {
  def check(elements: Seq[String]): Boolean
}

trait GroupGenerationOptionM extends GenerationOption {
  def check(elements: Seq[String]): UIO[Boolean]
}

// if the option doesnt return true the generated string should be discarded
trait SingleGenerationOption extends GenerationOption {
  def check(element: String): Boolean
}

trait SingleGenerationOptionM extends GenerationOption {
  def check(element: String): UIO[Boolean]
}

case class Length(value: Int) extends SingleGenerationOption {
  override def check(element: String): Boolean = element.length == value
}

case class MinLength(value: Int) extends SingleGenerationOption {
  override def check(element: String): Boolean = element.length >= value
}

case class MaxLength(value: Int) extends SingleGenerationOption {
  override def check(element: String): Boolean = element.length <= value
}

case class StartsWith(value: String) extends SingleGenerationOption {
  override def check(element: String): Boolean = element.startsWith(value)
}

case class EndsWith(value: String) extends SingleGenerationOption {
  override def check(element: String): Boolean = element.endsWith(value)
}

case class Includes(value: String) extends SingleGenerationOption {
  override def check(element: String): Boolean = element.contains(value)
}

case class Excludes(value: String) extends SingleGenerationOption {
  override def check(element: String): Boolean = !element.contains(value)
}

case class ExcludesAny(values: Iterable[String]) extends
  SingleGenerationOption {
  override def check(element: String): Boolean = values.forall(s => element
    .contains(s))
}

case class DamerauLevenshteinDistance(value: String, maxDistance: Int,
                                      enableTranspositions: Boolean)
    extends SingleGenerationOptionM {
  import zio.Ref
  import zio.ZIO
  import zio.ZIO._

  private def damerauLevenshteinMatrix(
    source: String,
    target: String,
    enableTranspositions: Boolean
  ): ZIO[Any, Nothing, Vector[Int]] = {
    val w = source.length + 1
    val h = source.length + 1
    for {
      costs <- Ref.make[Vector[Int]](Vector.fill(w * h)(0))
      _     <- foreach_(0 until w)(x => costs.update(_.updated(x, x)))
      _     <- foreach_(1 until h)(x => costs.update(_.updated(x * w, x)))
      cost  <- Ref.make[Int](0)
      _ <- foreach_(1 until w) { x =>
            foreach_(1 until h) { y =>
              if (source.charAt(x - 1) == target.charAt(y - 1)) cost.set(0)
              else cost.set(1)

              cost.get >>= (c =>
                costs.update(old =>
                  old.updated(
                    x + y * w,
                    List(
                      old((x - 1) + (y * w)) + 1,
                      List(
                        old(x + ((y - 1) * w)) + 1,
                        old((x - 1) + ((y - 1) * w)) + c
                      ).min
                    ).min
                  )
                ) <*> when(
                  enableTranspositions && x > 1 && y > 1 && source.charAt(x)
                    == target.charAt(y - 1) && source
                    .charAt(x - 1) == target.charAt(y)
                )(costs.update(old => old.updated(x + y * w, List(old(x + y *
                  w), old(x - 2 + ((y - 2) * w)) + c).min))).unit
              )
            }
          }
      res <- costs.get
    } yield res
  }

  override def check(element: String): UIO[Boolean] =
    if (element.length == 0) succeed(value.length <= maxDistance)
    else if (value.length == 0) succeed(element.length <= maxDistance)
    else
      for {
        distance <- damerauLevenshteinMatrix(element, value,
          enableTranspositions) >>= (v => succeed(v(v.length - 1)))
      } yield distance <= maxDistance
}

case class RegexMatch(value: Regex) extends SingleGenerationOption {
  override def check(element: String): Boolean = value.matches(element)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy