This is an automated email from the ASF dual-hosted git repository.
aradzinski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
The following commit(s) were added to refs/heads/master by this push:
new 840e904 WIP on migration.
840e904 is described below
commit 840e9043be65039f2eb6c7616e656868169fe6cd
Author: Aaron Radzinski <[email protected]>
AuthorDate: Tue Oct 5 10:46:16 2021 -0700
WIP on migration.
---
.../org/apache/nlpcraft/common/ansi/NCAnsi.scala | 225 +++++++++++++++++
.../org/apache/nlpcraft/common/util/NCUtils.scala | 281 +++++++++++++++++++++
2 files changed, 506 insertions(+)
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsi.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsi.scala
new file mode 100644
index 0000000..b215ce1
--- /dev/null
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsi.scala
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * https://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 org.apache.nlpcraft.common.ansi
+
+import com.typesafe.scalalogging.LazyLogging
+import org.apache.nlpcraft.common.*
+import org.apache.nlpcraft.common.util.NCUtils
+
+/**
+ *
+ */
+sealed trait NCAnsi extends LazyLogging:
+ import NCAnsi.*
+
+ private final val ESC = "\u001b"
+ private final val BELL = "\u0007"
+ private final val CSI = s"$ESC["
+ private final val OSC = s"$ESC]"
+ private final val RESET = s"${CSI}0m"
+
+ // 4-bit colors.
+ private final val BLACK = s"${CSI}30m"
+ private final val RED = s"${CSI}31m"
+ private final val GREEN = s"${CSI}32m"
+ private final val YELLOW = s"${CSI}33m"
+ private final val BLUE = s"${CSI}34m"
+ private final val MAGENTA = s"${CSI}35m"
+ private final val CYAN = s"${CSI}36m"
+ private final val WHITE = s"${CSI}37m"
+ private final val BLACK_B = s"${CSI}40m"
+ private final val RED_B = s"${CSI}41m"
+ private final val GREEN_B = s"${CSI}42m"
+ private final val YELLOW_B = s"${CSI}43m"
+ private final val BLUE_B = s"${CSI}44m"
+ private final val MAGENTA_B = s"${CSI}45m"
+ private final val CYAN_B = s"${CSI}46m"
+ private final val WHITE_B = s"${CSI}47m"
+
+ def ansi256Fg(color: Int) = if (isEnabled) s"[38;5;${color}m" else ""
+ def ansi256Bg(color: Int) = if (isEnabled) s"[48;5;${color}m" else ""
+ def ansi256Fg(fgColor: Int, s: Any): String =
s"${ansi256Fg(fgColor)}${s.toString}$ansiReset"
+ def ansi256(fgColor: Int, bgColor: Int, s: Any): String =
s"${ansi256Fg(fgColor)}${ansi256Bg(bgColor)}${s.toString}$ansiReset"
+
+ // Effects.
+ private final val BOLD = s"${CSI}1m"
+ private final val UNDERLINED = s"${CSI}4m"
+ private final val BLINK = s"${CSI}5m"
+ private final val REVERSED = s"${CSI}7m"
+ private final val INVISIBLE = s"${CSI}8m"
+
+ // Erase functions.
+ private final val CLEAR_SCREEN = s"${CSI}J"
+ private final val CLEAR_SCREEN_AFTER = s"${CSI}0J"
+ private final val CLEAR_SCREEN_BEFORE = s"${CSI}1J"
+ private final val CLEAR_LINE = s"${CSI}K"
+ private final val CLEAR_LINE_AFTER = s"${CSI}0K"
+ private final val CLEAR_LINE_BEFORE = s"${CSI}1K"
+
+ // Cursor moves.
+ private final val CURSOR_UP = s"${CSI}1A"
+ private final val CURSOR_DOWN = s"${CSI}1B"
+ private final val CURSOR_LEFT = s"${CSI}1D"
+ private final val CURSOR_RIGHT = s"${CSI}1C"
+ private final val CURSOR_POS_SAVE= s"${CSI}s"
+ private final val CURSOR_POS_RESTORE = s"${CSI}u"
+ private final val CURSOR_LINE_HOME = s"${CSI}0G"
+ private final val CURSOR_SCREEN_HOME = s"${CSI}H"
+ private final val CURSOR_HIDE = s"${CSI}?25l"
+ private final val CURSOR_SHOW = s"${CSI}?25h"
+
+ def isEnabled: Boolean = !NCUtils.isSysEnvTrue(PROP)
+
+
+ // Re-route to 8-bit colors.
+ def G: String = ansi256Fg(34)
+ def M: String = ansi256Fg(177)
+ def R: String = ansi256Fg(202)
+
+ def C: String = ansiCyanFg
+ def Y: String = ansiYellowFg
+ def W: String = ansi256Fg(231)
+ def B: String = ansiBlueFg
+ def K: String = ansiBlackFg
+
+ def GB: String = ansi256Bg(34)
+ def MB: String = ansi256Bg(177)
+ def RB: String = ansi256Bg(202)
+ def CB: String = ansiCyanBg
+ def YB: String = ansiYellowBg
+ def WB: String = ansiWhiteBg
+ def BB: String = ansiBlueBg
+ def KB: String = ansiBlackBg
+
+ def BO: String = ansiBold
+ def RST: String = ansiReset
+
+ def g(s: Any): String = s"$G${s.toString}$RST"
+ def m(s: Any): String = s"$M${s.toString}$RST"
+ def r(s: Any): String = s"$R${s.toString}$RST"
+ def c(s: Any): String = s"$C${s.toString}$RST"
+ def y(s: Any): String = s"$Y${s.toString}$RST"
+ def w(s: Any): String = s"$W${s.toString}$RST"
+ def b(s: Any): String = s"$B${s.toString}$RST"
+ def k(s: Any): String = s"$K${s.toString}$RST"
+
+ def green(s: Any): String = s"$G${s.toString}$RST"
+ def magenta(s: Any): String = s"$M${s.toString}$RST"
+ def red(s: Any): String = s"$R${s.toString}$RST"
+ def cyan(s: Any): String = s"$C${s.toString}$RST"
+ def yellow(s: Any): String = s"$Y${s.toString}$RST"
+ def white(s: Any): String = s"$W${s.toString}$RST"
+ def blue(s: Any): String = s"$B${s.toString}$RST"
+ def black(s: Any): String = s"$K${s.toString}$RST"
+ def gb(s: Any): String = s"$GB${s.toString}$RST"
+ def rb(s: Any): String = s"$RB${s.toString}$RST"
+ def cb(s: Any): String = s"$CB${s.toString}$RST"
+ def yb(s: Any): String = s"$YB${s.toString}$RST"
+ def wb(s: Any): String = s"$WB${s.toString}$RST"
+ def bb(s: Any): String = s"$BB${s.toString}$RST"
+ def kb(s: Any): String = s"$KB${s.toString}$RST"
+ def greenBg(s: Any): String = s"$GB${s.toString}$RST"
+ def magentaBg(s: Any): String = s"$MB${s.toString}$RST"
+ def redBg(s: Any): String = s"$RB${s.toString}$RST"
+ def cyanBg(s: Any): String = s"$CB${s.toString}$RST"
+ def yellowBg(s: Any): String = s"$YB${s.toString}$RST"
+ def whiteBg(s: Any): String = s"$WB${s.toString}$RST"
+ def blueBg(s: Any): String = s"$BB${s.toString}$RST"
+ def blackBg(s: Any): String = s"$KB${s.toString}$RST"
+
+ // Effect shortcuts...
+ def rv(s: Any): String = s"$ansiReversed${s.toString}$RST"
+ def bo(s: Any): String = s"$ansiBold${s.toString}$RST"
+ def reverse(s: Any): String = s"$ansiReversed${s.toString}$RST"
+ def bold(s: Any): String = s"$ansiBold${s.toString}$RST"
+
+ // Color functions.
+ def ansiBlackFg: String = if (isEnabled) BLACK else ""
+ def ansiBlackBg: String = if (isEnabled) BLACK_B else ""
+ def ansiRedFg: String = if (isEnabled) RED else ""
+ def ansiRedBg: String = if (isEnabled) RED_B else ""
+ def ansiGreenFg: String = if (isEnabled) GREEN else ""
+ def ansiGreenBg: String = if (isEnabled) GREEN_B else ""
+ def ansiYellowFg: String = if (isEnabled) YELLOW else ""
+ def ansiYellowBg: String = if (isEnabled) YELLOW_B else ""
+ def ansiBlueFg: String = if (isEnabled) BLUE else ""
+ def ansiBlueBg: String = if (isEnabled) BLUE_B else ""
+ def ansiMagentaFg: String = if (isEnabled) MAGENTA else ""
+ def ansiMagentaBg: String = if (isEnabled) MAGENTA_B else ""
+ def ansiCyanFg: String = if (isEnabled) CYAN else ""
+ def ansiCyanBg: String = if (isEnabled) CYAN_B else ""
+ def ansiWhiteFg: String = if (isEnabled) WHITE else ""
+ def ansiWhiteBg: String = if (isEnabled) WHITE_B else ""
+
+ // Effect functions.
+ def ansiBold: String = if (isEnabled) BOLD else ""
+ def ansiUnderlined: String = if (isEnabled) UNDERLINED else ""
+ def ansiReset: String = if (isEnabled) RESET else ""
+ def ansiReversed: String = if (isEnabled) REVERSED else ""
+ def ansiBlink: String = if (isEnabled) BLINK else ""
+ def ansiInvisible: String = if (isEnabled) INVISIBLE else ""
+
+ def ansiGreen(s: Any): String = s"$ansiGreenFg${s.toString}$ansiReset"
+ def ansiRed(s: Any): String = s"$ansiRedFg${s.toString}$ansiReset"
+ def ansiCyan(s: Any): String = s"$ansiCyanFg${s.toString}s$ansiReset"
+ def ansiYellow(s: Any): String = s"$ansiYellowFg${s.toString}$ansiReset"
+ def ansiBlack(s: Any): String = s"$ansiBlackFg${s.toString}s$ansiReset"
+ def ansiWhite(s: Any): String = s"$ansiWhiteFg${s.toString}$ansiReset"
+ def ansiBlue(s: Any): String = s"$ansiBlueFg${s.toString}$ansiReset"
+ def ansiMagenta(s: Any): String = s"$ansiMagentaFg${s.toString}$ansiReset"
+ def ansiBold(s: Any): String = s"$ansiBold${s.toString}$ansiReset"
+
+ // Erase functions.
+ def ansiClearScreen: String = if (isEnabled) CLEAR_SCREEN else ""
+ def ansiClearScreenAfter: String = if (isEnabled) CLEAR_SCREEN_AFTER else
""
+ def ansiClearScreenBefore: String = if (isEnabled) CLEAR_SCREEN_BEFORE
else ""
+ def ansiClearLine: String = if (isEnabled) CLEAR_LINE else ""
+ def ansiClearLineAfter: String = if (isEnabled) CLEAR_LINE_AFTER else ""
+ def ansiClearLineBefore: String = if (isEnabled) CLEAR_LINE_BEFORE else ""
+
+ // Cursor movement functions.
+ def ansiCursorUp: String = if (isEnabled) CURSOR_UP else ""
+ def ansiCursorDown: String = if (isEnabled) CURSOR_DOWN else ""
+ def ansiCursorLeft: String = if (isEnabled) CURSOR_LEFT else ""
+ def ansiCursorRight: String = if (isEnabled) CURSOR_RIGHT else ""
+ def ansiCursorLineHome: String = if (isEnabled) CURSOR_LINE_HOME else ""
+ def ansiCursorScreenHome: String = if (isEnabled) CURSOR_SCREEN_HOME else
""
+ def ansiCursorPosSave: String = if (isEnabled) CURSOR_POS_SAVE else ""
+ def ansiCursorPosRestore: String = if (isEnabled) CURSOR_POS_RESTORE else
""
+ def ansiCursorShow: String = if (isEnabled) CURSOR_SHOW else ""
+ def ansiCursorHide: String = if (isEnabled) CURSOR_HIDE else ""
+
+
+object NCAnsi extends NCAnsi:
+ // Enabled by default.
+ // NOTE: it's not static as it can be changed at runtime.
+ private final val PROP = "NLPCRAFT_ANSI_COLOR_DISABLED"
+
+ /**
+ *
+ * @param f
+ */
+ def setEnabled(f: Boolean): Unit = System.setProperty(PROP, (!f).toString)
+
+ /**
+ *
+ */
+ def ackStatus(): Unit =
+ if isEnabled then
+ logger.info(s"${NCUtils.bgRainbow4Bit("ANSI")} coloring is
enabled. Use '-D${ansiCyanFg}NLPCRAFT_ANSI_COLOR_DISABLED${ansiReset}=true' to
disable it.", 130, 147)
+
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
new file mode 100644
index 0000000..7a6153e
--- /dev/null
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * https://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 org.apache.nlpcraft.common.util
+
+import com.typesafe.scalalogging.LazyLogging
+import org.apache.nlpcraft.common.ansi.NCAnsi.*
+
+import java.util.Random
+import scala.sys.SystemProperties
+
+/**
+ *
+ */
+object NCUtils extends LazyLogging:
+ final val NL = System getProperty "line.separator"
+ private final val RND = new Random()
+ private val sysProps = new SystemProperties
+ private val ANSI_FG_8BIT_COLORS = for (i <- 16 to 255) yield ansi256Fg(i)
+ private val ANSI_BG_8BIT_COLORS = for (i <- 16 to 255) yield ansi256Bg(i)
+ private val ANSI_FG_4BIT_COLORS = Seq(
+ ansiRedFg,
+ ansiGreenFg,
+ ansiBlueFg,
+ ansiYellowFg,
+ ansiWhiteFg,
+ ansiBlackFg,
+ ansiCyanFg
+ )
+ private val ANSI_BG_4BIT_COLORS = Seq(
+ ansiRedBg,
+ ansiGreenBg,
+ ansiBlueBg,
+ ansiYellowBg,
+ ansiWhiteBg,
+ ansiBlackBg,
+ ansiCyanBg
+ )
+ private val ANSI_4BIT_COLORS = for (fg <- ANSI_FG_4BIT_COLORS; bg <-
ANSI_BG_4BIT_COLORS) yield s"$fg$bg"
+
+ /**
+ * Gets system property, or environment variable (in that order), or
`None` if none exists.
+ *
+ * @param s Name of the system property or environment variable.
+ */
+ def sysEnv(s: String): Option[String] =
sysProps.get(s).orElse(sys.env.get(s))
+
+ /**
+ * Tests whether given system property of environment variable is set or
not.
+ *
+ * @param s @param s Name of the system property or environment variable.
+ * @return
+ */
+ def isSysEnvSet(s: String): Boolean = sysProps.get(s).nonEmpty ||
sys.env.contains(s)
+
+ /**
+ * Returns `true` if given system property, or environment variable is
provided and has value
+ * 'true'. In all other cases returns `false`.
+ *
+ * @param s Name of the system property or environment variable.
+ */
+ def isSysEnvTrue(s: String): Boolean = sysEnv(s) match
+ case None => false
+ case Some(v) => java.lang.Boolean.valueOf(v) == java.lang.Boolean.TRUE
+
+
+ /**
+ * Gets random value from given sequence.
+ *
+ * @param seq Sequence.
+ */
+ def getRandom[T](seq: Seq[T]): T = seq(RND.nextInt(seq.size))
+
+ /**
+ * Makes random filled sequence with given length from initial.
+ *
+ * @param seq Initial sequence.
+ * @param n Required sequence length.
+ */
+ def getRandomSeq[T](seq: Seq[T], n: Int): Seq[T] =
+ require(seq.lengthCompare(n) >= 0)
+
+ val src = scala.collection.mutable.ArrayBuffer.empty[T] ++ seq
+ val dest = scala.collection.mutable.ArrayBuffer.empty[T]
+
+ (0 until n).foreach(_ => dest += src.remove(RND.nextInt(src.size)))
+
+ dest.toSeq
+
+ /**
+ * Prints 4-bit ASCII-logo.
+ */
+ def asciiLogo4Bit(): String =
+ raw"$ansiBlueFg _ ____ $ansiCyanFg ______ ______
$ansiReset$NL" +
+ raw"$ansiBlueFg / | / / /___ $ansiCyanFg/ ____/________ _/ __/ /_
$ansiReset$NL" +
+ raw"$ansiBlueFg / |/ / / __ \$ansiCyanFg/ / / ___/ __ `/ /_/ __/
$ansiReset$NL" +
+ raw"$ansiBlueFg / /| / / /_/ /$ansiCyanFg /___/ / / /_/ / __/ /_
$ansiReset$NL" +
+ raw"$ansiBold$ansiRedFg/_/ |_/_/ .___/$ansiRedFg\____/_/ \__,_/_/
\__/ $ansiReset$NL" +
+ raw"$ansiBold$ansiRedFg /_/
$ansiReset$NL"
+
+ /**
+ * Prints 8-bit ASCII-logo.
+ */
+ def asciiLogo8Bit1(): String =
+ fgRainbow4Bit(
+ raw"${ansi256Fg(28)} _ ____ ______ ______
$ansiReset$NL" +
+ raw"${ansi256Fg(64)} / | / / /___ / ____/________ _/ __/ /_
$ansiReset$NL" +
+ raw"${ansi256Fg(100)} / |/ / / __ \/ / / ___/ __ `/ /_/ __/
$ansiReset$NL" +
+ raw"${ansi256Fg(136)} / /| / / /_/ / /___/ / / /_/ / __/ /_
$ansiReset$NL" +
+ raw"${ansi256Fg(172)}/_/ |_/_/ .___/\____/_/ \__,_/_/ \__/
$ansiReset$NL" +
+ raw"${ansi256Fg(208)} /_/
$ansiReset$NL"
+ )
+
+ /**
+ * Prints 8-bit ASCII-logo.
+ */
+ def asciiLogo8Bit(): String =
+ val startColor = getRandom(Seq(16, 22, 28, 34, 40, 46))
+ val range = 6
+
+ (for (lineIdx <- Seq(
+ raw" _ ____ ______ ______ $NL",
+ raw" / | / / /___ / ____/________ _/ __/ /_ $NL",
+ raw" / |/ / / __ \/ / / ___/ __ `/ /_/ __/ $NL",
+ raw" / /| / / /_/ / /___/ / / /_/ / __/ /_ $NL",
+ raw"/_/ |_/_/ .___/\____/_/ \__,_/_/ \__/ $NL",
+ raw" /_/ $NL"
+ ).zipWithIndex) yield {
+ val line = lineIdx._1
+ val idx = lineIdx._2
+ val start = startColor + (36 * idx)
+ val end = start + range - 1
+
+ gradAnsi8BitFgLine(line, start, end)
+ })
+ .mkString("")
+
+ /**
+ *
+ * @param line
+ * @param startColor Inclusive.
+ * @param endColor Inclusive.
+ * @return
+ */
+ def gradAnsi8BitFgLine(line: String, startColor: Int, endColor: Int):
String =
+ line.zipWithIndex.foldLeft(new StringBuilder())((buf, zip) => {
+ val ch = zip._1
+ val idx = zip._2
+ val color = startColor + idx % (endColor - startColor + 1)
+
+ buf ++= s"${ansi256Fg(color)}$ch"
+ })
+ .toString + ansiReset
+
+ /**
+ *
+ * @param line
+ * @param startColor Inclusive.
+ * @param endColor Inclusive.
+ * @return
+ */
+ def gradAnsi8BitBgLine(line: String, startColor: Int, endColor: Int):
String =
+ line.zipWithIndex.foldLeft(new StringBuilder())((buf, zip) => {
+ val ch = zip._1
+ val idx = zip._2
+ val color = startColor + idx % (endColor - startColor + 1)
+
+ buf ++= s"${ansi256Bg(color)}$ch"
+ })
+ .toString + ansiReset
+
+ /**
+ *
+ * @param s
+ * @return
+ */
+ def fgRainbow4Bit(s: String, addOn: String = ""): String = rainbowImpl(s,
ANSI_FG_4BIT_COLORS, addOn)
+
+ /**
+ *
+ * @param s
+ * @return
+ */
+ def fgRainbow8Bit(s: String, addOn: String = ""): String = rainbowImpl(s,
ANSI_FG_8BIT_COLORS, addOn)
+
+ /**
+ *
+ * @param s
+ * @return
+ */
+ def bgRainbow4Bit(s: String, addOn: String = ""): String = rainbowImpl(s,
ANSI_BG_4BIT_COLORS, addOn)
+
+ /**
+ *
+ * @param s
+ * @return
+ */
+ def bgRainbow8Bit(s: String, addOn: String = ""): String = rainbowImpl(s,
ANSI_BG_8BIT_COLORS, addOn)
+
+ /**
+ *
+ * @param s
+ * @return
+ */
+ def rainbow4Bit(s: String, addOn: String = ""): String =
randomRainbowImpl(s, ANSI_4BIT_COLORS, addOn)
+
+ /**
+ *
+ * @param s
+ * @param colors
+ * @param addOn
+ * @return
+ */
+ private def randomRainbowImpl(s: String, colors: Seq[String], addOn:
String): String =
+ s.zipWithIndex.foldLeft(new StringBuilder())((buf, zip) => {
+ buf ++= s"${colors(RND.nextInt(colors.size))}$addOn${zip._1}"
+ })
+ .toString + ansiReset
+
+ /**
+ *
+ * @param s
+ * @param colors
+ * @param addOn
+ * @return
+ */
+ private def rainbowImpl(s: String, colors: Seq[String], addOn: String):
String =
+ s.zipWithIndex.foldLeft(new StringBuilder())((buf, zip) => {
+ buf ++= s"${colors(zip._2 % colors.size)}$addOn${zip._1}"
+ })
+ .toString + ansiReset
+
+ /**
+ * ANSI color JSON string.
+ *
+ * @param json JSON string to color.
+ * @return
+ */
+ def colorJson(json: String): String =
+ val buf = new StringBuilder
+ var inQuotes = false
+ var isValue = false
+
+ for (ch <- json)
+ ch match
+ case ':' if !inQuotes => buf ++= r(":"); isValue = true
+ case '[' | ']' | '{' | '}' if !inQuotes => buf ++= y(s"$ch");
isValue = false
+ case ',' if !inQuotes => buf ++= ansi256Fg(213, s"$ch");
isValue = false
+ case '"' =>
+ if inQuotes then
+ buf ++= ansi256Fg(105, s"$ch")
+ else
+ buf ++= s"${ansi256Fg(105)}$ch"
+ buf ++= (if isValue then G else ansiCyanFg)
+
+ inQuotes = !inQuotes
+
+ case _ => buf ++= s"$ch"
+
+
+ buf.append(RST)
+ buf.toString()
+
+ /**
+ * Shortcut - current timestamp in milliseconds.
+ */
+ def now(): Long = System.currentTimeMillis()