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

com.velocidi.apso.ProgressBar.scala Maven / Gradle / Ivy

There is a newer version: 0.19.6
Show newest version
package com.velocidi.apso

/** A widget for printing a dynamic progress bar in a console.
  * @param total
  *   the number representing the full progress bar
  * @param width
  *   the line width of the progress bar
  * @param throughputUnit
  *   the throughput unit that is being measured
  * @param throughputTransformer
  *   a function to transform the measured throughput value, before displaying it
  */
case class ProgressBar(
    total: Long = 100,
    width: Int = 80,
    throughputUnit: String = "ops",
    throughputTransformer: Double => Double = identity
) {
  private[this] var done = 0L
  private[this] val startTimestamp = System.currentTimeMillis

  private[this] val workchars = List('|', '/', '-', '\\')
  private[this] var lastChar = 0
  private[this] def workChar = {
    if (lastChar >= (workchars.length - 1)) lastChar = 0
    else lastChar += 1
    workchars(lastChar)
  }

  /** Increase the progress by one.
    */
  def tick(): Unit = {
    tick(1)
  }

  /** Increase the progress by the given number of units.
    * @param inc
    *   the number of progress units to increase
    */
  def tick(inc: Long): Unit = {
    if (!isFinished) {
      done += inc
      if (done > total) done = total

      val currentTimestamp = System.currentTimeMillis
      val throughput =
        done.toDouble / (currentTimestamp - startTimestamp) * 1000

      val percent = done.toDouble / total
      val res = new StringBuilder(width)

      val prefix = f"${(percent * 100).toInt}%3d%% ["
      val suffix = f"] $workChar [ ${throughputTransformer(throughput)}%2.2f ] $throughputUnit/s  "
      val remainingWidth = width - prefix.length - suffix.length - (if (percent < 1.0) 1 else 0)

      res.append("\r")
      res.append(prefix)
      res.append("=" * (remainingWidth * percent).toInt)
      if (percent < 1.0) res.append(">")
      res.append(" " * (remainingWidth - (remainingWidth * percent).toInt))
      res.append(suffix)
      print(res.mkString)

      if (isFinished) {
        System.out.flush()
        println()
      }
    }
  }

  /** Returns `true` if this progress bar is full.
    * @return
    *   `true` if this progress bar is full, `false` otherwise.
    */
  def isFinished = done >= total
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy