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

gwen.gpm.process.ProgressBar.scala Maven / Gradle / Ivy

/*
 * Copyright 2017 Branko Juric, Brady Wood
 *
 * 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 gwen.gpm.process

import java.text.DecimalFormat

import scala.concurrent.duration.Duration

/**
  * Progress bar for displaying download status.
  *
  * @param totalUnits the number of progress units
  */
class ProgressBar(barLength: Int, totalUnits: Long) {

  private var unitsDone = 0L
  private val startTime = System.nanoTime()

  show()

  /** Steps the progress bar by 1 unit */
  def step(): Unit = {
    stepBy(1)
  }

  /**
    * Steps the progress bar by a given number of units.
    * @param units the number of units to step
    */
   def stepBy(units: Long): Unit = {
    unitsDone += units
    show()
  }

  private def show(): Unit = {
    val percentage = unitsDone.toDouble / totalUnits.toDouble
    val barUnits = (percentage * barLength).toInt
    val bar = s"${"=" * (barUnits - 1)}>${"-" * (barLength - barUnits)}"
    val duration = DurationFormatter.format(Duration.fromNanos(System.nanoTime() - startTime))
    print(s"\r[gwen-gpm] [$bar] ${(percentage * 100).toInt}% $duration ")
    if (barUnits == barLength) {
      Thread.sleep(100)
      print(s"\r[gwen-gpm] [${"=" * barLength}] 100% $duration ")
    }
  }
}

/**
  * Formats durations for presentation purposes.
  */
object DurationFormatter {

  import scala.concurrent.duration._

  private val Formatters = List(
    HOURS -> (("h", new DecimalFormat("00"))),
    MINUTES -> (("m", new DecimalFormat("00"))),
    SECONDS -> (("s", new DecimalFormat("00")))
  )

  /**
    * Formats a given duration to ##h ##m ##s ###ms format.
    *
    * @param duration the duration to format
    */
  def format(duration: Duration): String = {
    val nanos = duration.toNanos
    val secs = (nanos / 1000000000) + (if ((nanos % 1000000000) < 500000000) 0 else 1)
    if (secs > 0) {
      var duration = Duration(secs, SECONDS)
      Formatters.foldLeft("") { (acc: String, f: (TimeUnit, (String, DecimalFormat))) =>
        val (unit, (unitName, formatter)) = f
        val unitValue = duration.toUnit(unit).toLong
        if (acc.length() == 0 && unitValue == 0) ""
        else {
          duration = duration - Duration(unitValue, unit)
          s"$acc ${formatter.format(unitValue)}$unitName"
        }
      }.trim.replaceFirst("^0+(?!$)", "")
    } else "0s"
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy